postgresql 添加约束以使每一组行的列唯一

wvyml7n5  于 2023-06-29  发布在  PostgreSQL
关注(0)|答案(1)|浏览(110)

Postgres表中有一列status,它只能接受两个值:ActiveInactive
其中一列名为userid。表中可以有多行具有相同的userid,但其中最多一行具有status = 'Active'。我只需要一个或没有status作为Activeuserid。如何使用此条件创建约束?我无法从Postgres文档中找到任何帮助。

fgw7neuy

fgw7neuy1#

status应该是boolean。更便宜更干净。
无论哪种方式,您都可以使用partial unique index强制执行规则。
要在整个表中允许零行或一行带有status = 'Active'***:

CREATE UNIQUE INDEX tbl_active_uni ON tbl (status)
WHERE status = 'Active';

要允许status = 'Active' *per userid * 的零行或一行,请将userid作为索引列:

CREATE UNIQUE INDEX tbl_userid_active_uni ON tbl (userid)
WHERE status = 'Active';

userid中的空值不会触发唯一的违规,因为两个空值根本不被认为是相等的,或者默认情况下,因为Postgres 15添加了**NULLS NOT DISTINCT**子句。如果你不想这样,设置列NOT NULL,或者看:

*创建空列唯一约束

  • 如何在PostgreSQL上添加条件唯一索引

为什么使用索引而不是约束?

在评论中回答您的问题:这是一个索引,而不是CONSTRAINT
第一种情况的索引是 tiny,包含一行或不包含一行。
第二种情况的索引为每个现有的userid保存一行,但它是*最便宜和最快的方式***,除了干净和安全。在任何情况下,您都需要一个索引来检查其他行,以便快速执行此操作。
不能对其他行进行CHECK约束检查-至少不能以干净、可靠的方式进行。对于这种情况,我有一些方法
肯定不推荐**:

如果您在(userid, status)上使用UNIQUE约束(也是通过内部唯一索引实现的!),则不能将其设置为 partial,并且 all 组合将强制为唯一的。如果您使用status IS NULL处理除'Active'以外的所有情况,您仍然可以使用此选项。但这将创建一个更大的索引,包括 * 所有 * 行。

相关问题