向列组合添加唯一约束的迁移

我需要的是一个迁移,以便对列的组合应用唯一约束。也就是说,对于 people表,first_namelast_NameDob的组合应该是唯一的。

90340 次浏览

例如,您可以在向列的迁移中添加唯一索引

add_index(:accounts, [:branch_id, :party_id], :unique => true)

或为每个列分开唯一索引

add_index :people, [:firstname, :lastname, :dob], unique: true

您可能希望添加不带索引的约束。这将取决于您使用的数据库。下面是 Postgres 的迁移代码示例。(tracking_number, carrier)是要用于约束的列的列表。

class AddUniqeConstraintToShipments < ActiveRecord::Migration
def up
execute <<-SQL
alter table shipments
add constraint shipment_tracking_number unique (tracking_number, carrier);
SQL
end


def down
execute <<-SQL
alter table shipments
drop constraint if exists shipment_tracking_number;
SQL
end
end

可以添加不同的约束

根据 howmanyofme.com 的数据,仅在美国就有46427个人叫约翰 · 史密斯。那就是127天。由于这远远超过了人类的平均寿命,这意味着出生日期冲突在数学上是确定无疑的。

我想说的是,这种独特字段的特殊组合可能会在未来导致极端的用户/客户挫折感。

考虑一些实际上是独一无二的东西,如果合适的话,比如国家识别号码。

(我意识到自己在这个问题上来得太晚了,但它可能会对未来的读者有所帮助。)

在用户和帖子之间的联接表的典型示例中:

create_table :users
create_table :posts


create_table :ownerships do |t|
t.belongs_to :user, foreign_key: true, null: false
t.belongs_to :post, foreign_key: true, null: false
end


add_index :ownerships, [:user_id, :post_id], unique: true

试图创建两个类似的记录将抛出一个数据库错误(在我的例子中是 Postgres) :

ActiveRecord::RecordNotUnique: PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "index_ownerships_on_user_id_and_post_id"
DETAIL:  Key (user_id, post_id)=(1, 1) already exists.
: INSERT INTO "ownerships" ("user_id", "post_id") VALUES ($1, $2) RETURNING "id"

例如:

Ownership.create!(user_id: user_id, post_id: post_id)
Ownership.create!(user_id: user_id, post_id: post_id)

完全可运行的例子: https://gist.github.com/Dorian/9d641ca78dad8eb64736173614d97ced

产生: https://gist.github.com/Dorian/a8449287fa62b88463f48da986c1744a

为了完整起见,为了避免混淆,这里有3种做同样事情的方法:
向 Rails 5.2 + 中的列组合添加命名的唯一约束

假设我们有一个属于广告商的 Locations 表,其中有一列 reference _ code,每个广告商只需要一个引用代码。因此,您希望向列的组合添加唯一约束,并将其命名为。

做:

rails g migration AddUniquenessConstraintToLocations

让你的迁移看起来像这样的一行:

class AddUniquenessConstraintToLocations < ActiveRecord::Migration[5.2]
def change
add_index :locations, [:reference_code, :advertiser_id], unique: true, name: 'uniq_reference_code_per_advertiser'
end
end

或者这个版本。

class AddUniquenessConstraintToLocations < ActiveRecord::Migration[5.2]
def change
change_table :locations do |t|
t.index ['reference_code', 'advertiser_id'], name: 'uniq_reference_code_per_advertiser', unique: true
end
end
end

或这个原始 SQL 版本

class AddUniquenessConstraintToLocations < ActiveRecord::Migration[5.2]
def change
execute <<-SQL
ALTER TABLE locations
ADD CONSTRAINT uniq_reference_code_per_advertiser UNIQUE (reference_code, advertiser_id);
SQL
end
end

任何这些将有相同的结果,检查你的 schema.rb