Postgres表中有一列status,它只能接受两个值:Active和Inactive。其中一列名为userid。表中可以有多行具有相同的userid,但其中最多一行具有status = 'Active'。我只需要一个或没有status作为Active每userid。如何使用此条件创建约束?我无法从Postgres文档中找到任何帮助。
status
Active
Inactive
userid
status = 'Active'
fgw7neuy1#
status应该是boolean。更便宜更干净。无论哪种方式,您都可以使用partial unique index强制执行规则。要在整个表中允许零行或一行带有status = 'Active'***:
boolean
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,或者看:
NULLS NOT DISTINCT
NOT NULL
*创建空列唯一约束
在评论中回答您的问题:这是一个索引,而不是CONSTRAINT。第一种情况的索引是 tiny,包含一行或不包含一行。第二种情况的索引为每个现有的userid保存一行,但它是*最便宜和最快的方式***,除了干净和安全。在任何情况下,您都需要一个索引来检查其他行,以便快速执行此操作。不能对其他行进行CHECK约束检查-至少不能以干净、可靠的方式进行。对于这种情况,我有一些方法肯定不推荐**:
CONSTRAINT
CHECK
如果您在(userid, status)上使用UNIQUE约束(也是通过内部唯一索引实现的!),则不能将其设置为 partial,并且 all 组合将强制为唯一的。如果您使用status IS NULL处理除'Active'以外的所有情况,您仍然可以使用此选项。但这将创建一个更大的索引,包括 * 所有 * 行。
(userid, status)
UNIQUE
status IS NULL
'Active'
1条答案
按热度按时间fgw7neuy1#
status
应该是boolean
。更便宜更干净。无论哪种方式,您都可以使用partial unique index强制执行规则。
要在整个表中允许零行或一行带有
status = 'Active'
***:要允许
status = 'Active'
*peruserid
* 的零行或一行,请将userid
作为索引列:userid
中的空值不会触发唯一的违规,因为两个空值根本不被认为是相等的,或者默认情况下,因为Postgres 15添加了**NULLS NOT DISTINCT
**子句。如果你不想这样,设置列NOT NULL
,或者看:*创建空列唯一约束
为什么使用索引而不是约束?
在评论中回答您的问题:这是一个索引,而不是
CONSTRAINT
。第一种情况的索引是 tiny,包含一行或不包含一行。
第二种情况的索引为每个现有的
userid
保存一行,但它是*最便宜和最快的方式***,除了干净和安全。在任何情况下,您都需要一个索引来检查其他行,以便快速执行此操作。不能对其他行进行
CHECK
约束检查-至少不能以干净、可靠的方式进行。对于这种情况,我有一些方法肯定不推荐**:如果您在
(userid, status)
上使用UNIQUE
约束(也是通过内部唯一索引实现的!),则不能将其设置为 partial,并且 all 组合将强制为唯一的。如果您使用status IS NULL
处理除'Active'
以外的所有情况,您仍然可以使用此选项。但这将创建一个更大的索引,包括 * 所有 * 行。