我有这个:
alter table supplier
add constraint supplier_unique
unique (supplier_id) where supplier_id is not null;
但我收到了错误。
结果定义应为:
CREATE UNIQUE INDEX supplier_unique
ON supplier (supplier_id) WHERE (supplier_id IS NOT NULL)
感谢。
答案 0 :(得分:4)
PostgreSQL中的unique constraint没有WHERE子句,因此您在“where”处收到语法错误。在任何情况下,supplier_id is not null
都不需要具有唯一约束:
通常,如果表中有多行,其中约束中包含的所有列的值相等,则会违反唯一约束。但是,在此比较中,两个空值不相等。这意味着即使存在唯一约束,也可以在至少一个约束列中存储包含空值的重复行。此行为符合SQL标准,...
所以你需要的就是:
alter table supplier
add constraint supplier_unique
unique (supplier_id);
您的唯一约束将被添加,您可以拥有多个supplier_id IS NULL
行,并且您将索引作为唯一约束的副作用。
但是,如果要直接创建索引,可以create a partial index使用谓词:
当存在WHERE子句时,将创建部分索引。部分索引是一个索引,它只包含表的一部分的条目,通常是比索引的其余部分更有用的索引部分。
[...]
另一个可能的应用是使用带有UNIQUE的WHERE来强制表的一个子集的唯一性。
但是在NULL的情况下,supplier_id IS NOT NULL
的部分索引不会对唯一性做任何事情,因为PostgreSQL唯一约束已经允许多个NULL值(可能是因为标准因为x = NULL
是所有x
)都是假的。
因此,如果您的意图过于限制非NULL值的唯一性,那么您不需要您的部分索引;但是,如果您只是想避免索引NULL值,那么您可以通过CREATE INDEX(但不是ALTER TABLE)来完成。我不知道是否从你的索引中留下NULL会产生任何明显的影响。
我认为部分混乱(你和我的)是UNIQUE既是约束又是索引。您可以在将其创建为索引时包括WHERE,但在将其创建为约束时则不包括WHERE。这肯定是不一致的。