Postgres唯一约束不强制唯一性

Lee*_*Lee 5 postgresql

这是我的约束:

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);
Run Code Online (Sandbox Code Playgroud)

此查询证明约束实际上不起作用:

SELECT id, user_id, class_type_id,deleted_at
FROM subscriptions;
Run Code Online (Sandbox Code Playgroud)

这是输出:

在此输入图像描述

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

IMS*_*SoP 23

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;
Run Code Online (Sandbox Code Playgroud)


a_h*_*ame 5

发生这种情况是由于NULLcreated_at列中的值。唯一索引(或约束)允许其中包含多行NULL

唯一可以避免的方法是将列声明NOT NULL为强制值,或者将唯一列减少为(user_id, class_type_id)