【问题标题】:Ruby on Rails: How do I add a not null constraint to an existing column using a migration?Ruby on Rails:如何使用迁移向现有列添加非空约束?
【发布时间】:2012-03-06 08:51:45
【问题描述】:

在我的 Rails (3.2) 应用程序中,我的数据库中有一堆表,但我忘记添加一些非空约束。我已经用谷歌搜索了,但我找不到如何编写一个向现有列添加非 null 的迁移。

TIA。

【问题讨论】:

    标签: ruby-on-rails database migration constraints notnull


    【解决方案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 中检查您的更改。

      如果简单迁移的列数很少,可以使用这种方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-07-18
        • 2013-04-22
        • 2011-06-07
        • 2010-12-29
        • 2011-06-17
        • 1970-01-01
        • 2011-03-23
        • 2015-08-12
        相关资源
        最近更新 更多