这是我的约束:
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;
这是输出:
为什么没有强制执行唯一性?
答案 0 :(得分:20)
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;
答案 1 :(得分:4)
这是因为NULL
列中的created_at
值。唯一索引(或约束)允许其中包含NULL
的多行。
唯一可以阻止这种情况的方法是将列声明为NOT NULL
以强制为其添加值,或将唯一列减少为(user_id, class_type_id)