如何从 Rails 中的数据库列中删除唯一约束?

How can I remove a unique constraint from a database column in Rails?

我使用以下迁移创建了 table:

class CreateProfilePictures < ActiveRecord::Migration
  def change
    create_table :profile_pictures do |t|
      t.integer :user_id, null: false
      t.integer :picture_id, null: false
      t.timestamps null: false
    end

    add_index :profile_pictures, :user_id, unique: true
    add_index :profile_pictures, :picture_id, unique: true
  end
end

我尝试使用以下方法删除约束:

class FixProfilePic < ActiveRecord::Migration
  def change
    change_column :profile_pictures, :picture_id, :integer, unique: false
  end
end

如果我尝试在多个地方使用相同的 picture_id,我仍然会遇到违反唯一约束的错误。从 picture_id 中删除唯一性约束的正确方法是什么?

add_index :profile_pictures, :picture_id, unique: true

因此将您的索引更新为:

  remove_index :profile_pictures, :picture_id
  add_index :profile_pictures, :picture_id

我猜是这样。

您必须删除您的索引:

remove_index :profile_pictures, :picture_id

并再次添加:

add_index :profile_pictures, :picture_id

ActiveRecord::Migration

已接受的答案存在问题:回滚无法正常工作,因为唯一索引未恢复。

您可以试试这个:

reversible do |dir|
  dir.up do
    remove_index :profile_pictures, :picture_id
    add_index :profile_pictures, :picture_id
  end

  dir.down do
    remove_index :profile_pictures, :picture_id
    add_index :profile_pictures, :picture_id, unique: true
  end
end

要使迁移可逆,您现在(Rails 6 岁以上)需要使用 :column 选项。

添加 unique: true 还确保回滚迁移将重新创建具有唯一性约束的索引(除非同时插入有问题的数据)。

  remove_index :profile_pictures, column: :picture_id, unique: true
  add_index :profile_pictures, :picture_id

还有一点需要注意:如果您的 table 很大,那么在其上创建新索引可能会长时间锁定对其的写入。如果您使用 Postgres

,请考虑使用 algorithm: :concurrently