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

Ruby on Rails 在现有资源上返回 404

ruby on rails Heroku 迁移错误