Postgres 表中有一列status
,它只能取两个值:Active
和Inactive
。
其中一列名为 userid
。该表可以有多个具有相同 userid
的行,但其中最多可以有一个 status = 'Active'
。对于每个 userid
,我只需要一个或不需要 status
作为 Active
。我怎样才能用这种条件创建约束?我无法从 Postgres 文档中找到任何帮助。
最佳答案
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 IS NULL
不会触发唯一违规,因为两个 NULL 值永远不会被视为相等。 userid
必须是 set NOT NULL
在这种情况下。
为什么使用索引而不是约束?
解决您的 question in the comment : 这是索引,不是 CONSTRAINT
.
第一种情况的索引很小,包含一行或没有行。
第二种情况的索引为每个现有 userid
保留一行,但它是最便宜和最快的方式,而且干净和安全。在任何情况下,您都需要一个索引来检查其他行以加快速度。
您不能对其他行进行 CHECK
约束检查 - 至少不能以干净、可靠的方式进行检查。对于这种情况,我肯定不推荐有一些方法:
- Trigger vs. check constraint
- How to avoid a cyclic dependency (circular reference) between 3 tables?
- Disable all constraints and table checks while restoring a dump
如果你在 (userid, status)
上使用了 UNIQUE
约束(它在内部也是用唯一索引实现的!),你不能让它部分,并且所有组合都被强制为唯一的。如果您对除 'Active'
情况之外的所有情况使用 status IS NULL
,您仍然可以使用它。但这实际上会强加一个更大的索引,包括所有行。
关于database - 添加约束以使每组行的列唯一,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34495479/