我必须实施一条规则,即只有一个具有给定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
答案 0 :(得分:4)
我认为你需要一个部分唯一索引。
CREATE UNIQUE INDEX group_status_unq_idx
ON "group"(group_id, status) WHERE (status IN ('In Progress', 'Problem'));
但是,从您的描述中我不清楚为什么第二次预期失败会失败。对于任何给定的In Progress
,您是否只允许 Problem
或group_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)
);
这可以防止任何状态的重复,不仅仅是'In Progress'
和'Problem'
。我不确定这是不是你想要的。