在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;`