添加约束以使每组行的列唯一
Add constraint to make column unique per group of rows
Postgres table 中有一列 status
,它只能取两个值:Active
和 Inactive
。
其中一列名为 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
约束检查 - 至少不能以干净、可靠的方式进行。对于这种情况,有些方法我当然不推荐:
- 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
约束(内部也是用唯一索引实现的!),你不能使它partial,并且 所有 组合都必须是唯一的。如果您对除 'Active'
以外的所有情况使用 status IS NULL
,您 可以 仍然使用它。但这实际上会强加一个更大的索引,包括 all 行。
Postgres table 中有一列 status
,它只能取两个值:Active
和 Inactive
。
其中一列名为 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
为什么使用索引而不是约束?
正在解决您的 CONSTRAINT
.
第一种情况的索引是 tiny,包含一行或没有行。
第二种情况的索引为每个现有 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
约束(内部也是用唯一索引实现的!),你不能使它partial,并且 所有 组合都必须是唯一的。如果您对除 'Active'
以外的所有情况使用 status IS NULL
,您 可以 仍然使用它。但这实际上会强加一个更大的索引,包括 all 行。