【问题标题】:Unicity on two columns asymmetrically两列不对称的唯一性
【发布时间】:2016-09-03 23:18:21
【问题描述】:

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

我想在数据库中添加一个约束,这样如果几个 user_id 的对称性已经存在,就会被拒绝。

例如,如果我在数据库中已经有(42, 17) 这对夫妇,我不希望能够保存(17, 42)

我正在使用带有 postgresql 的 Rails。

【问题讨论】:

    标签: ruby-on-rails postgresql constraints unique-constraint


    【解决方案1】:

    您可以使用表达式索引在数据库中执行此操作:

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

    我不知道你在 Rails 中是如何表达的。

    【讨论】:

      【解决方案2】:

      如果您能够以某种方式实现应用程序,您可以结合使用普通唯一约束和检查约束来执行此操作,它将较小的值存储在字段 user_id_1 中,将较大的值存储在字段 user_id_2 中.

      在 (user_id_1, user_id_2) 上定义一个唯一约束,另外定义一个检查约束,即 (user_id_1

      在 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 供应商的。

      【讨论】:

        【解决方案3】:

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

        validates_uniqueness_of :user_id1, :scope =&gt; :user_id2。 这保证不会有两个相同的user_id1s 或user_id2s 对。

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-06-02
          • 2012-10-10
          • 2017-12-25
          • 1970-01-01
          • 2016-03-29
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多