如何在两个列上设置唯一约束,其中一个列可以为null

3

我有一个非常简单的表格

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个回答

3
您可以为此创建一个唯一索引:
CREATE UNIQUE INDEX ix_categories_root_title
    ON categories (title)
    WHERE parent_id IS NULL

你可以比依赖触发器或应用级验证更放心地睡眠 :P

2
在PostgreSQL中,使用唯一约束无法实现这个功能:
然而,在这种比较中,两个空值不被认为是相等的。这意味着即使在唯一约束存在的情况下,仍然可以存储包含至少一个受限列中的空值的重复行。这种行为符合SQL标准,但我们听说其他SQL数据库可能不遵循此规则。
根本问题在于,在标准SQL中,对于所有x,x=NULL都是false。
你可以使用BEFORE INSERT和BEFORE UPDATE触发器来强制执行NULL parent_id值,但ActiveRecord不知道触发器是什么,因此您必须手动维护触发器。或者,您可以通过自定义验证完成所有操作,并希望没有东西越过模型直接访问数据库。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接