不对称两列上的唯一性



这是我的Friendship(user_id1:integer, user_id2:integer)

我想给数据库添加一个约束,这样,如果它的符号已经存在,那么两个user_id就会被拒绝。

例如,如果我在数据库中已经有一对(42, 17),我不想保存(17, 42)

我在postgresql中使用rails。

您可以在数据库中使用表达式的索引:

create unique index unq_friendship_1_2
     on (least(user_id1, user_id2), greatest(user_id1, user_id2));

我不知道你是怎么用铁轨表达的。

您可以使用普通唯一约束和检查约束的组合来实现这一点,如果您能够以某种方式实现应用程序,即它在字段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)

如果您的应用程序无法插入如上所述排序的值,您仍然可以使用例如触发器,但这是特定于DB供应商的。

您可以在Rails中这样做。在您的轨道型号friendship.rb中,添加以下validates_uniqueness调用:

validates_uniqueness_of :user_id1, :scope => :user_id2。这保证了不会有两对相同的user_id1user_id2

然而,@potashin解释说,这种方法并不完全安全,因为如果同时发送两个请求,它们可能会被接受,并且您的行会重复。他的解决方案是还将以下迁移添加到您的友谊模型中:

class AddUniqueConstraints < ActiveRecord::Migration
  def change
   add_index :friendships, [:user_id1, :user_id2], unique: true
  end
end

最新更新