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

时间:2015-12-28 14:36:47

标签: database postgresql constraints unique-index partial-index

Postgres表格中有一列status,只有两个值:ActiveInactive

其中一列名为userid。该表可以包含多个具有相同userid的行,但最多只能有一行status = 'Active'。每status我只需要一Active userid <%= render partial: 'vote', locals: {:@post => post} %> 。如何使用此条件创建约束?我无法从Postgres文档中找到任何帮助。

1 个答案:

答案 0 :(得分:8)

@lad2025 commented一样,status应该是boolean。更便宜,更清洁。

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

强制执行规则

要在整个表格中使用status = 'Active' 允许零行或一行

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

要使status = 'Active' userid 允许零行或一行,请将userid设为索引列:

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

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

为什么索引而不是约束?

解决您的question in the comment:这是一个索引,而不是CONSTRAINT

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

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

如果您在CHECK上使用UNIQUE约束(后台也使用唯一索引实现!),则无法使其成为 partial 所有组合都被强制为唯一。如果您使用(userid, status)处理除status IS NULL案例之外的所有情况, 仍然可以使用此功能。但这实际上会产生更大的索引,包括所有行。