2

我必须实施一项规则,即只有一个具有给定 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
4

3 回答 3

4

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

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

但是,从您的描述中我不清楚为什么第二个预期失败会失败。你想只允许一个In ProgressProblem任何给定group_id的?如果是这样,您可以编写如下内容:

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

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

请注意,这不能表示为UNIQUE约束,因为唯一约束不采用谓词。PostgreSQL 唯一约束是使用(非部分)UNIQUE索引实现的,但它也会创建单纯的索引创建不会创建的元数据条目。部分唯一索引的工作方式类似于带有谓词的唯一约束,但无法通过诸如information_schema约束信息之类的元数据发现。

于 2012-10-25T10:02:55.320 回答
1

如果我理解正确:

create unique index group_restriction_index on group
(status) where status in ('In Progress', 'Problem')
于 2012-10-25T09:57:46.667 回答
0

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

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

(来自Postgresql 文档)。

但是,这将防止任何状态的重复,而不仅仅是'In Progress'and 'Problem'。我不确定这是否是你想要的。

于 2012-10-25T10:03:01.080 回答