【问题标题】:how to set unique constraint over 2 columns when one column can be null当一列可以为空时,如何在两列上设置唯一约束
【发布时间】:2011-08-07 05:31:02
【问题描述】:

我有一个非常简单的表格

categories(parent_id, title)

我正在尝试设置唯一约束,以便两个类别不能具有相同的标题和父级。

class CreateCategories < ActiveRecord::Migration
  def change
    create_table :categories do |t|
      t.integer :parent_id
      t.string  :title, :null => false
    end
    add_index :categories, [:title, :parent_id], :unique => true   
  end
end

当 parent_id 为 null 时,它不会强制标题的唯一性,这是我们需要的。是否可以确保标题对于根类别也是唯一的?

【问题讨论】:

    标签: sql ruby-on-rails postgresql activerecord


    【解决方案1】:

    您可以为此创建一个唯一索引:

    CREATE UNIQUE INDEX ix_categories_root_title
        ON categories (title)
        WHERE parent_id IS NULL
    

    与依赖触发器或应用程序级验证相比,您晚上睡得更好:P

    【讨论】:

      【解决方案2】:

      您不能在 PostgreSQL 中使用 UNIQUE constraint 来做到这一点:

      但是,在此比较中,两个空值不相等。这意味着即使存在唯一约束,也可以在至少一个受约束的列中存储包含空值的重复行。此行为符合 SQL 标准,但我们听说其他 SQL 数据库可能不遵循此规则。

      根本的问题是x = NULL 在标准 SQL 中对于所有 x 都是错误的。

      您可以使用 BEFORE INSERT 和 BEFORE UPDATE 触发器对 NULL parent_id 值强制执行此操作,但 ActiveRecord 不知道触发器是什么,因此您必须手动维护触发器。或者,您可以在自定义验证中完成所有操作,并希望在不先检查您的模型的情况下,没有任何东西会触及您的数据库。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-01-30
        • 1970-01-01
        • 2013-01-21
        • 2021-04-10
        • 1970-01-01
        • 1970-01-01
        • 2019-09-29
        • 1970-01-01
        相关资源
        最近更新 更多