Ruby on Rails:如何使用迁移向现有列添加非空约束?
Posted
技术标签:
【中文标题】Ruby on Rails:如何使用迁移向现有列添加非空约束?【英文标题】:Ruby on Rails: How do I add a not null constraint to an existing column using a migration? 【发布时间】:2012-03-06 08:51:45 【问题描述】:在我的 Rails (3.2) 应用程序中,我的数据库中有一堆表,但我忘记添加一些非空约束。我已经用谷歌搜索了,但我找不到如何编写一个向现有列添加非 null 的迁移。
TIA。
【问题讨论】:
【参考方案1】:对于 Rails 4+,nates' answer(使用change_column_null)更好。
Pre-Rails 4,试试change_column。
【讨论】:
小心使用这种方法——如果你有关于该列的其他属性(例如:limit
约束),你需要在使用change_column
时重复这些属性,否则它们会丢失.出于这个原因,我更喜欢使用change_column_null
请注意,这会生成一个IrreversibleMigration
,这可能不是您想要的。
@NicNilov 你说的是答案还是内森·华莱士的评论?
@Mark 我说的是答案,抱歉不够具体。
@NicNilov no dw 我确实认为,虽然我只是想仔细检查:)【参考方案2】:
你也可以使用change_column_null:
change_column_null :table_name, :column_name, false
【讨论】:
我不得不为一堆列更改它,这不需要为每列指定列类型,好多了! 这是更好的答案。在我的数据库中,我在具有预先存在的空值的列上添加空约束。 change_column 不会更新这些值。根据文档,change_column_null 有一个可选的第四个值,它是更新的新值。 谢谢。最佳答案。 有趣的副作用....回滚迁移会将字段设置为相反的 (false -> true)。因此,如果您为多个字段创建迁移以添加空约束,并且某些字段已经有空约束,然后回滚迁移,它将从任何已经具有空约束的字段中删除空约束。 第四个选项将为这些条目设置默认值,其中列确实为空。 但要小心!如果它是一张大桌子,它可能会导致停机。最好先批量回填这些记录,然后在没有第四选项的情况下添加约束。【参考方案3】:1) FIRST:添加具有默认值的列
2) THEN: 移除默认值
add_column :orders, :items, :integer, null: false, default: 0
change_column :orders, :items, :integer, default: nil
【讨论】:
当您需要添加不为空的新列时,这是正确的解决方案,您需要首先定义它具有默认值,因为 SQLLite 会报错(无法添加默认值为 NULL 的 NOT NULL 列) ,然后将其删除!【参考方案4】:如果您在新的创建迁移脚本/模式中使用它,我们可以在这里定义它
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
【讨论】:
【参考方案5】:在我的方法中,我向现有迁移迁移中需要的列添加 NOT NULL 约束。 之后,我使用以下命令重置所有迁移:
rake db:migrate:reset
这将删除数据库,重新创建它并运行所有迁移。 您可以在 schema.rb 中检查您的更改。
如果简单迁移的列数很少,可以使用这种方法。
【讨论】:
以上是关于Ruby on Rails:如何使用迁移向现有列添加非空约束?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Ruby on Rails 3 中一次恢复所有迁移?
如何在 Ruby on Rails 迁移中使列唯一并为其编制索引?
如何在 Ruby on Rails ActiveRecord 迁移中处理过长的索引名称?
Heroku上的现有Ruby on Rails Web应用程序(PostgreSQL),Devise身份验证,需要为移动支持添加Rails API