Postgres唯一约束未强制执行唯一性

18

这是我的限制条件:

CREATE UNIQUE INDEX index_subscriptions_on_user_id_and_class_type_id_and_deleted_at
  ON subscriptions
  USING btree
  (user_id, class_type_id, deleted_at);

这个查询证明了限制条件实际上并没有起作用:

SELECT id, user_id, class_type_id,deleted_at
FROM subscriptions;

这里是输出结果:

输入图像描述

为什么唯一性没有被强制执行?


1
你可能会对这个答案感兴趣:http://dba.stackexchange.com/questions/9759/postgresql-multi-column-unique-constraint-and-null-values/18110#18110 - Luc M
2个回答

59
在Postgres中,唯一索引是基于值相等的,但NULL永远不等于任何东西,包括其他的NULL。因此,任何带有NULL的deleted_at值的行都与任何其他可能的行不同 - 因此,您可以插入任意数量的它们。
解决这个问题的一种方法是创建部分索引,对带有和不带有NULL的行应用不同的规则:
 CREATE UNIQUE INDEX ... ON subscriptions
 (user_id, class_type_id) WHERE deleted_at IS NULL;

 CREATE UNIQUE INDEX ... ON subscriptions
 (user_id, class_type_id, deleted_at) WHERE deleted_at IS NOT NULL;

8
这是由于created_at列中的NULL值引起的。唯一索引(或约束)允许具有NULL值的多个行。
您可以采取以下两种方法来防止这种情况:要么将该列声明为NOT NULL,以强制规定其值;要么将唯一列减少为(user_id, class_type_id)

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