如何在Rails迁移中将可空列更改为不可空?
我在之前的迁移中创build了一个date列,并将其设置为空。 现在我想改变它是不可空的。 假如数据库中有空行,我该怎么做? 如果他们目前为空,我可以将这些列设置为Time.now。
如果你在迁移中这样做,那么你可以这样做:
# Make sure no null value exist MyModel.update_all({ date_column: Time.now }, { date_column: nil }) # Change the column to not allow null change_column :my_models, :date_column, :datetime, null: false
在Rails 4中,这是一个更好的解决scheme(DRY):
change_column_null :my_models, :date_column, false
要确保该列中没有null
值的logging:
MyModel.update_all({ date_column: Time.now }, { date_column: nil })
Rails 4(其他Rails 4的答案有问题):
def change change_column_null(:users, :admin, false, <put a default value here> ) # change_column(:users, :admin, :string, :default => "") end
更改一个列中的NULL值不允许NULL将导致问题。 这正是在开发环境中能够正常工作的代码types,然后当你尝试将其部署到实际的生产环境时,就会崩溃。 您应该首先将NULL值更改为有效, 然后禁止NULL。 change_column_null
中的第四个值就是这个值。 请参阅文档了解更多详情。
此外,我通常更喜欢为该字段设置默认值,所以我不需要每次创build一个新对象时指定该字段的值。 我还包括注释掉的代码来做到这一点。
创build一个具有:default =>
值的change_column
语句的迁移。
change_column :my_table, :my_column, :integer, :default => 0, :null => false
请参阅: change_column
根据数据库引擎,您可能需要使用change_column_null
Rails 4:
def change change_column_null(:users, :admin, false ) end
根据文档 ,在Rails 4.02+中 ,没有像2个参数的update_all
一样的方法。 相反,可以使用这个代码:
# Make sure no null value exist MyModel.where(date_column: nil).update_all(date_column: Time.now) # Change the column to not allow null change_column :my_models, :date_column, :datetime, null: false
如果您有现有logging,则不能使用add_timestamps和null:false,所以解决scheme如下:
def change add_timestamps(:buttons, null: true) Button.find_each { |b| b.update(created_at: Time.zone.now, updated_at: Time.zone.now) } change_column_null(:buttons, :created_at, false) change_column_null(:buttons, :updated_at, false) end