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

Add constraint to make column unique per group of rows

Postgres table 中有一列 status,它只能取两个值:ActiveInactive

其中一列名为 userid。 table 可以有多个具有相同 userid 的行,但其中最多可以有一个 status = 'Active'。我只需要一个或不需要 status 作为 Active 每个 userid。我怎样才能用这种条件创建约束?我无法从 Postgres 文档中找到任何帮助。

status 真的应该是 boolean。更便宜,更清洁。

无论哪种方式,您都可以使用 partial unique index.

强加您的规则

在整个table中status = 'Active'允许0行或1行:

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

允许零行或一行 status = 'Active' per userid, make userid索引列:

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

请注意,userid IS NULL 不会触发唯一违规,因为两个 NULL 值永远不会被视为相等。在这种情况下,userid 必须是 set NOT NULL

  • How to add a conditional unique index on PostgreSQL
  • Create unique constraint with null columns

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

正在解决您的 : This is an index, not a CONSTRAINT.

第一种情况的索引是 tiny,包含一行或没有行。
第二种情况的索引为每个现有 userid 保留一行,但它是 最便宜和最快的方式 ,除了干净安全。在任何情况下,您都需要一个索引来检查其他行以加快速度。

您不能对其他行进行 CHECK 约束检查 - 至少不能以干净、可靠的方式进行。对于这种情况,有些方法我当然不推荐

如果你在(userid, status)上使用UNIQUE约束(内部也是用唯一索引实现的!),你不能使它partial,并且 所有 组合都必须是唯一的。如果您对除 'Active' 以外的所有情况使用 status IS NULL,您 可以 仍然使用它。但这实际上会强加一个更大的索引,包括 all 行。