不对称地在两列上的唯一性
Unicity on two columns asymmetrically
这是我的tableFriendship(user_id1:integer, user_id2:integer)
我想向数据库添加一个约束,这样如果它的对称性已经存在,一些 user_id 将被拒绝。
例如,如果我已经在数据库中有一对(42, 17)
,我不希望能够保存(17, 42)
我正在使用 rails 和 postgresql。
您可以在数据库中使用表达式索引执行此操作:
create unique index unq_friendship_1_2
on (least(user_id1, user_id2), greatest(user_id1, user_id2));
我不知道你在rails中是怎么表达的。
您可以结合使用普通唯一约束和检查约束来执行此操作,如果您能够以某种方式实施应用程序,它将较小的值存储在字段 user_id_1 中,并且字段 user_id_2.
中的值更大
在 (user_id_1, user_id_2) 上定义一个唯一约束,另外还有一个检查约束,即 (user_id_1 <= user_id_2) 以验证您的应用程序的行为按照上面定义的方式。
在 Oracle 中,这将是
ALTER TABLE tablename ADD CONSTRAINT cname1 UNIQUE (user_id_1, user_id_2)
ALTER TABLE tablename ADD CONSTRAINT cname2 CHECK (user_id_1 <= user_id_2)
如果您的应用程序无法插入如上所述排序的值,您仍然可以使用例如触发器,但这是更具体的数据库供应商。
您可以在 Rails 中这样做。
在您的 rails 模型 friendship.rb
中,添加以下 validates_uniqueness
调用:
validates_uniqueness_of :user_id1, :scope => :user_id2
。
这保证不会有两对相同的 user_id1
s 或 user_id2
s.
但是,@potashin 已经解释说这种方法并不完全安全,因为如果同时发送两个请求,它们可能会被接受并且您的行会被复制。他的解决方案是将以下迁移添加到您的友谊模型中:
class AddUniqueConstraints < ActiveRecord::Migration
def change
add_index :friendships, [:user_id1, :user_id2], unique: true
end
end
这是我的tableFriendship(user_id1:integer, user_id2:integer)
我想向数据库添加一个约束,这样如果它的对称性已经存在,一些 user_id 将被拒绝。
例如,如果我已经在数据库中有一对(42, 17)
,我不希望能够保存(17, 42)
我正在使用 rails 和 postgresql。
您可以在数据库中使用表达式索引执行此操作:
create unique index unq_friendship_1_2
on (least(user_id1, user_id2), greatest(user_id1, user_id2));
我不知道你在rails中是怎么表达的。
您可以结合使用普通唯一约束和检查约束来执行此操作,如果您能够以某种方式实施应用程序,它将较小的值存储在字段 user_id_1 中,并且字段 user_id_2.
中的值更大在 (user_id_1, user_id_2) 上定义一个唯一约束,另外还有一个检查约束,即 (user_id_1 <= user_id_2) 以验证您的应用程序的行为按照上面定义的方式。
在 Oracle 中,这将是
ALTER TABLE tablename ADD CONSTRAINT cname1 UNIQUE (user_id_1, user_id_2)
ALTER TABLE tablename ADD CONSTRAINT cname2 CHECK (user_id_1 <= user_id_2)
如果您的应用程序无法插入如上所述排序的值,您仍然可以使用例如触发器,但这是更具体的数据库供应商。
您可以在 Rails 中这样做。
在您的 rails 模型 friendship.rb
中,添加以下 validates_uniqueness
调用:
validates_uniqueness_of :user_id1, :scope => :user_id2
。
这保证不会有两对相同的 user_id1
s 或 user_id2
s.
但是,@potashin 已经解释说这种方法并不完全安全,因为如果同时发送两个请求,它们可能会被接受并且您的行会被复制。他的解决方案是将以下迁移添加到您的友谊模型中:
class AddUniqueConstraints < ActiveRecord::Migration
def change
add_index :friendships, [:user_id1, :user_id2], unique: true
end
end