Ruby-on-rails 在 Rails 迁移中将一列更新为另一列的值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5224881/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Update one column to value of another in Rails migration
提问by jrdioko
I have a table in a Rails app with hundreds of thousands of records, and they only have a created_attimestamp. I'm adding the ability to edit these records, so I want to add an updated_attimestamp to the table. In my migration to add the column, I want to update all rows to have the new updated_atmatch the old created_at, since that's the default for newly created rows in Rails. I could do a find(:all)and iterate through the records, but that would take hours because of the size of the table. What I really want to do is:
我在 Rails 应用程序中有一个包含数十万条记录的表,它们只有一个created_at时间戳。我正在添加编辑这些记录的功能,所以我想updated_at在表中添加一个时间戳。在我添加列的迁移中,我想更新所有行以使新行updated_at与旧行匹配created_at,因为这是 Rails 中新创建的行的默认设置。我可以执行 afind(:all)并遍历记录,但由于表的大小,这需要几个小时。我真正想做的是:
UPDATE table_name SET updated_at = created_at;
Is there a nicer way to do that in a Rails migration using ActiveRecord rather than executing raw SQL?
在使用 ActiveRecord 而不是执行原始 SQL 的 Rails 迁移中,有没有更好的方法来做到这一点?
回答by nathanvda
I would create a migration
我会创建一个迁移
rails g migration set_updated_at_values
and inside it write something like:
在里面写一些类似的东西:
class SetUpdatedAt < ActiveRecord::Migration
def self.up
Yourmodel.update_all("updated_at=created_at")
end
def self.down
end
end
This way you achieve two things
这样你就可以实现两件事
- this is a repeatable process, with each possible deploy (where needed) it is executed
- this is efficient. I can't think of a more rubyesque solution (that is as efficient).
- 这是一个可重复的过程,每个可能的部署(在需要的地方)都会执行
- 这是有效的。我想不出更像红宝石的解决方案(效率一样高)。
Note: you could also run raw sql inside a migration, if the query gets too hard to write using activerecord. Just write the following:
注意:如果使用 activerecord 编写查询太难,您也可以在迁移中运行原始 sql。只需编写以下内容:
Yourmodel.connection.execute("update your_models set ... <complicated query> ...")
回答by Greg Dan
You can use update_allwhich works very similar to raw SQL. That's all options you have.
您可以使用与原始 SQL 非常相似的update_all。这就是你拥有的所有选择。
BTW personally I do not pay that much attention to migrations. Sometimes raw SQL is really best solution. Generally migrations code isn't reused. This is one time action so I don't bother about code purity.
顺便说一句,我个人不太关注迁移。有时原始 SQL 确实是最好的解决方案。通常不会重用迁移代码。这是一次性操作,所以我不关心代码纯度。
回答by Martin Streicher
As gregdan wrote, you can use update_all. You can do something like this:
正如 gregdan 所写,您可以使用update_all. 你可以这样做:
Model.where(...).update_all('updated_at = created_at')
The first portion is your typical set of conditions. The last portion says how to make the assignments. This will yield an UPDATEstatement, at least in Rails 4.
第一部分是您的典型条件集。最后一部分说明如何进行分配。这将产生一个UPDATE声明,至少在 Rails 4 中是这样。
回答by Sarwan Kumar
You can directly run following command to your rails consoleActiveRecord::Base.connection.execute("UPDATE TABLE_NAME SET COL2 = COL1")
您可以直接运行以下命令到您的 rails consoleActiveRecord::Base.connection.execute("UPDATE TABLE_NAME SET COL2 = COL1")
For example: I want to update sku of my items table with remote_id of items tables. the command will be as following:ActiveRecord::Base.connection.execute("UPDATE items SET sku = remote_id")
例如:我想用 items 表的 remote_id 更新我的 items 表的 sku。命令如下:ActiveRecord::Base.connection.execute("UPDATE items SET sku = remote_id")
回答by Wilson Varghese
This is a General way of solving, without the need for Writing Query, as queries are subjected to risk.
这是一种通用的解决方法,不需要编写查询,因为查询存在风险。
class Demo < ActiveRecord::Migration
def change
add_column :events, :time_zone, :string
Test.all.each do |p|
p.update_attributes(time_zone: p.check.last.time_zone)
end
remove_column :sessions, :time_zone
end
end
回答by ghoppe
As a one time operation, I would just do it in the rails console. Will it really take hours? Maybe if there are millions of records…
作为一次性操作,我只会在rails console. 真的需要几个小时吗?也许如果有数百万条记录......
records = ModelName.all; records do |r|; r.update_attributes(:updated_at => r.created_at); r.save!; end;`

