更新一列,所有行


71

我在表中添加了新列,但忘记添加:default选项。现在,我想在每一行上填充该列。

有使用控制台的方法吗?我过去一个小时一直在搜索google,但找不到任何内容。

我知道如何针对单个对象而不是针对模型中的所有对象。Foo.find(1).update_attribute(:myattribute,'value')


您要为每行分配相同的值还是为每行分配不同的值?
Jimmy Huang,2010年

相同的值。谢谢
Martin Petrov 2010年

好的,@ petrov。您可以尝试update_all方法
Jimmy Huang,2010年

Answers:


133

尝试这个:

Foo.update_all(some_column: "bar")

这将生成对数据库的SQL查询:

UPDATE "foos" SET "some_column" = "bar"; 

谢谢pake007。这可行。最初,我尝试了ModelName.update,但没有成功
Martin Petrov 2010年

4
@Petrov没问题,甚至更多,您可以将条件参数传递给此方法。例如:Foo.update_all({:new_column =>“ bar”},{:old_column_1 => nil})。它将更新“ old_column_1”列上所有值为零的记录。
Jimmy Huang,2010年

但是对于rails 2.2?使用什么语法?
13年

2
在rails 3和4中,此方法是的成员ActiveRecord::Relation,因此可以与where和链接,例如:Foo.where(old_column_1: nil).update_all(new_column: 'bar')
Envek 2013年

25

由于您已经在先前的迁移中创建了新字段,因此请创建全新的迁移:

rails g migration UpdateFoos

修改迁移:

def self.up    
  say_with_time "Updating foos..." do
    Foo.find(:all).each do |f|
      f.update_attribute :myattribute, 'value'
    end
  end
end

# from command line
Rake db:migrate

让我知道这是否可行,可能需要进行一些调整。有关更多信息,请参见rails文档


4
好答案。Rails3的人,在上面的示例中使用Foo.all而不是Foo.find(:all)。
幻影鲸鱼2012年

2
虽然您对新迁移是正确的,但是如果您有很多专栏,请参阅:每一种都是更新所有这些专栏的缓慢方法。:update_all将大大加快。
加伦2014年

3

您可以这样做:

Foo.update_all(new_column:“ bar”)


2

当然,您可以使用像这样的smth Foo.update_all(:myattribute => "value"),但是它只会修改已经创建的数据。要为所有“未来”数据设置默认值,这是一种创建单独的迁移的好方法,如下所示:

rails generate migration AddDefaultValueToFoo

修改新的迁移(例如,myattribute具有字符串类型),如下所示:

class AddDefaultValueToFoo < ActiveRecord::Migration
  def self.up
    change_column :foos, :myattribute, :string, :default => "value"
    Foo.update_all(:myattribute => "value")
  end
end
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.