Ruby on Rails:如何使用迁移向现有列添加非null约束?


130

在我的Rails(3.2)应用程序中,我的数据库中有一堆表,但是我忘记添加一些非空约束。我已经四处搜寻,但找不到如何编写将不添加null的迁移添加到现有列的方法。

TIA。

Answers:


93

对于Rails 4 +,nates的答案(使用change_column_null)更好。

预发布4,请尝试change_column


25
使用这种方法时要小心-如果该列具有其他属性(例如:limit约束),则在使用时需要重复这些属性change_column,否则它们将丢失。因此,我更喜欢使用change_column_null
Nathan Wallace

请注意,这生成的IrreversibleMigration可能不是您想要的。
Nic Nilov

@NicNilov您在谈论答案还是Nathan Wallace的评论?
Mark

@Mark我在谈论答案,对不起,因为不够具体。
Nic Nilov

@NicNilov no dw我确实认为,尽管我只是想仔细检查一下:)
马克

273

您也可以使用change_column_null

change_column_null :table_name, :column_name, false

8
最干净的答案!
乔许点击

1
我不得不为一堆列更改它,这不需要为每个列指定列类型,更好!
多里安

1
这是更好的答案。在我的数据库中,我在具有空值的列上添加了空约束。change_column不会更新这些值。根据文档,change_column_null具有可选的第四个值,它是更新的新值。
Merovex '16

谢谢你 最佳答案。
瑞安·雷沃

1
有趣的副作用...。回滚迁移会将字段设置为相反的字段(false-> true)。因此,如果您为多个字段创建迁移以添加空约束,并且某些字段已经具有空约束,然后回滚迁移,它将从任何已有空约束的字段中删除空约束。
jpw

10

1)第一:添加具有默认值的列

2)然后:删除默认值

add_column :orders, :items, :integer, null: false, default: 0
change_column :orders, :items, :integer, default: nil

2
当您需要添加不为null的新列时,这是正确的解决方案,您首先需要定义它具有默认值,因为SQLLite会抱怨(无法添加默认值NULL的NOT NULL列),然后将其删除!
米兰

2

如果您在新创建的迁移脚本/方案上使用它,则可以通过以下方法定义它

class CreateUsers < ActiveRecord::Migration[5.2]
  def change
    create_table :users do |t|
    t.string :name, null: false     # Notice here, NOT NULL definition
    t.string :email, null: false
    t.string :password, null: false
    t.integer :created_by
    t.integer :updated_by 

    t.datetime :created_at
    t.datetime :updated_at, default: -> { 'CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP' }
   end
  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.