当一列可以为null时,如何在2列上设置唯一约束

时间:2011-08-07 05:31:03

标签: sql ruby-on-rails postgresql activerecord

我有一个非常简单的表

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时,它不会强制标题的唯一性,这是我们需要的。是否有可能确保标题对根类别也是唯一的?

2 个答案:

答案 0 :(得分:3)

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

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

晚上睡觉要好于依靠触发器或应用程序级验证:P

答案 1 :(得分:2)

你无法在PostgreSQL中使用UNIQUE constraint

  

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

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

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