postgres可以检查*有条件地*限制重复吗?

时间:2012-10-25 09:50:06

标签: sql database postgresql duplicates

我必须实施一条规则,即只有一个具有给定ID的“组”可以同时具有“进行中”或“问题”状态。是否有可能在Postgres检查中表示这一点,或者我是否必须求助于应用程序中的逻辑?

例如:

INSERT INTO group (group_id, status) VALUES (1, 'In Progress'); -- okay
INSERT INTO group (group_id, status) VALUES (2, 'Problem'); -- okay
INSERT INTO group (group_id, status) VALUES (3, 'In Progress'); -- okay
INSERT INTO group (group_id, status) VALUES (4, 'Problem'); -- okay
INSERT INTO group (group_id, status) VALUES (1, 'Something else'); -- okay
INSERT INTO group (group_id, status) VALUES (2, 'Foo bar'); -- okay

INSERT INTO group (group_id, status) VALUES (1, 'In Progress'); -- should fail
INSERT INTO group (group_id, status) VALUES (1, 'Problem'); -- should fail
INSERT INTO group (group_id, status) VALUES (2, 'In Progress'); -- should fail
INSERT INTO group (group_id, status) VALUES (2, 'Problem'); -- should fail

3 个答案:

答案 0 :(得分:4)

我认为你需要一个部分唯一索引。

CREATE UNIQUE INDEX group_status_unq_idx 
ON "group"(group_id, status) WHERE (status IN ('In Progress', 'Problem'));

但是,从您的描述中我不清楚为什么第二次预期失败会失败。对于任何给定的In Progress ,您是否只允许 Problemgroup_id中的一个?如果是这样,你可以这样写:

CREATE UNIQUE INDEX group_status_unq_idx
ON "group"(group_id) WHERE (status IN ('In Progress', 'Problem'));

...从部分唯一索引中省略status并仅将其用于谓词。请参阅this SQLFiddle

请注意,这不能表示为UNIQUE约束,因为唯一约束不采用谓词。 PostgreSQL唯一约束是使用 a(非部分)UNIQUE索引实现的,但它也创建了仅仅索引创建不会创建的元数据条目。部分唯一索引的作用类似于带谓词的唯一约束,但它不会通过information_schema的约束信息等元数据发现。

答案 1 :(得分:1)

如果我理解正确:

create unique index group_restriction_index on group
(status) where status in ('In Progress', 'Problem')

答案 2 :(得分:0)

您可以对多个列进行唯一约束:

CREATE TABLE group (
    group_id integer,
    status char(100),
    UNIQUE (group_id, status)
);

(来自Postgresql documentation)。

这可以防止任何状态的重复,不仅仅是'In Progress''Problem'。我不确定这是不是你想要的。