在Rails迁移中将一列更新为另一列的值
我在Rails应用程序中有一个包含数十万条logging的表,并且它们只有一个created_at
时间戳。 我添加了编辑这些logging的function,所以我想添加一个updated_at
时间戳到表中。 在我的迁移中添加列,我想更新所有的行,让新的updated_at
匹配旧的created_at
,因为这是在Rails中新创build的行的默认值。 我可以做一个find(:all)
并遍历logging,但这将需要几个小时,因为表的大小。 我真正想要做的是:
UPDATE table_name SET updated_at = created_at;
使用ActiveRecord进行Rails迁移,而不是执行原始SQL有没有更好的方法?
我会创build一个迁移
rails g migration set_updated_at_values
里面写着这样的东西:
class SetUpdatedAt < ActiveRecord::Migration def self.up Yourmodel.update_all("updated_at=created_at") end def self.down end end
这样你就可以做到两件事情
- 这是一个可重复的过程,每个可能的部署(在需要的地方)执行
- 这是有效的。 我想不出更多的rubyesque解决scheme(这是有效的)。
注意:如果查询变得太难以使用activerecord写入,你也可以在迁移中运行原始的sql。 只要写下面的内容:
Yourmodel.connection.execute("update your_models set ... <complicated query> ...")
您可以使用与原始SQL非常类似的update_all 。 这是你所有的select。
顺便说一句,我不太关心迁移。 有时候,原始SQL是最好的解决scheme。 通常迁移代码不会被重复使用。 这是一次性操作,所以我不打扰代码的纯度。
正如gregdan写的,你可以使用update_all
。 你可以做这样的事情:
Model.where(...).update_all('updated_at = created_at')
第一部分是你典型的一套条件。 最后一部分说明如何完成作业。 这将产生一个UPDATE
语句,至less在Rails 4中。
作为一次性操作,我只是在rails console
。 它真的需要几个小时? 也许如果有数百万条logging…
records = ModelName.all; records do |r|; r.update_attributes(:updated_at => r.created_at); r.save!; end;`