Rails的方式来重置id字段上的种子
我发现这个问题的答案是“纯粹的SQL”。 有没有办法, 在Rails中 ,重置特定表的ID字段?
我为什么要这样做? 因为我的表格中有不断移动的数据 – 很less有超过100行,但总是不同的。 现在已经达到25K了,这里没有任何意义。 我打算使用Rails应用程序(rufus-scheduler)内部的调度程序来每月运行id字段重置。
我根据hgimenez的回答提出了一个解决scheme,而另一个解决scheme。
由于我通常使用Sqlite或PostgreSQL,所以我只为这些开发。 但将其扩展到MySQL,不应该太麻烦。
把这个放在lib /里面,并且在初始化器上需要它:
# lib/active_record/add_reset_pk_sequence_to_base.rb module ActiveRecord class Base def self.reset_pk_sequence case ActiveRecord::Base.connection.adapter_name when 'SQLite' new_max = maximum(primary_key) || 0 update_seq_sql = "update sqlite_sequence set seq = #{new_max} where name = '#{table_name}';" ActiveRecord::Base.connection.execute(update_seq_sql) when 'PostgreSQL' ActiveRecord::Base.connection.reset_pk_sequence!(table_name) else raise "Task not implemented for this DB adapter" end end end end
用法:
Client.count # 10 Client.destroy_all Client.reset_pk_sequence Client.create(:name => 'Peter') # this client will have id=1
编辑:由于最常见的情况下,你会想要做到这一点是清除数据库表后,我build议看看database_cleaner 。 它自动处理ID重置。 你可以告诉它删除像这样select的表:
DatabaseCleaner.clean_with(:truncation, :only => %w[clients employees])
你从来没有提到你正在使用的DBMS。 如果这是postgreSQL,ActiveRecord postgres适配器有一个reset_pk_sequences!
您可以使用的方法:
ActiveRecord::Base.connection.reset_pk_sequence!('table_name')
我假设你不关心数据:
def self.truncate! connection.execute("truncate table #{quoted_table_name}") end
或者如果你这样做,但不是太多(有一段时间数据只存在于内存中):
def self.truncate_preserving_data! data = all.map(&:clone).each{|r| raise "Record would not be able to be saved" unless r.valid? } connection.execute("truncate table #{quoted_table_name}") data.each(&:save) end
这将给新的logging,具有相同的属性,但ID从1开始。
任何belongs_to
这张桌子的东西都可能变得棘手。
一个问题是这些types的字段对于不同的数据库 – 序列,自动增量等是不同的。
您可以随时删除并重新添加表格。
不,Rails中没有这样的东西。 如果您需要一个很好的ID来显示用户,然后将它们存储在一个单独的表中,并重新使用它们。
你只能在rails中做这个,如果_ids被rails设置的话。 只要你的数据库正在设置_ids,你将无法使用SQL来控制它们。
附注:我想用rails来定期调用一个重置或删除重新创build序列的SQL过程并不是一个纯粹的SQL解决scheme,但我不认为这就是你所要求的…
编辑:
免责声明:我对轨道了解不多。
从SQL的angular度来看,如果你有一个列id first_name last_name
的表,并且你通常insert into table (first_name, last_name) values ('bob', 'smith')
你可以改变你的查询insert into table (id, first_name, last_name) values ([variable set by rails], 'bob', 'smith')
这样,_id由variables设置,而不是由SQL自动设置。 在这一点上,钢轨完全控制_id是什么(虽然如果它是一个PK,你需要确保你不使用相同的值,而它仍然在那里)。
如果您要将作业留给数据库,则必须有轨道运行(无论何时间表),如下所示:
DROP SEQUENCE MY_SEQ; CREATE SEQUENCE MY_SEQ START WITH 1 INCREMENT BY 1 MINVALUE 1;
以任何顺序控制你的桌子的ID。 这将摆脱当前的序列,并创build一个新的。 这是我知道你“重置”一个序列的最简单的方法。
基于@hgmnz的回答,我做了这个方法,将序列设置为您喜欢的任何值…(仅用Postgres适配器testing)。
# change the database sequence to force the next record to have a given id def set_next_id table_name, next_id connection = ActiveRecord::Base.connection def connection.set_next_id table, next_id pk, sequence = pk_and_sequence_for(table) quoted_sequence = quote_table_name(sequence) select_value <<-end_sql, 'SCHEMA' SELECT setval('#{quoted_sequence}', #{next_id}, false) end_sql end connection.set_next_id(table_name, next_id) end
Rails的方式,例如MySQL,但丢失了表users
所有数据 :
ActiveRecord::Base.connection.execute('TRUNCATE TABLE users;')
也许帮助某人;)