2

特定の ID を持つ 1 つの「グループ」のみが、一度に「進行中」または「問題」のステータスを持つことができるというルールを実装する必要があります。これを 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'));

ただし、2番目の予期された失敗が失敗する理由は、あなたの説明からはわかりません。指定された の 1 つまたは1 つだけIn ProgressProblemgroup_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'これにより、 と だけでなく、あらゆるステータスの重複が防止されます'Problem'。それがあなたの望むものかどうかはわかりません。

于 2012-10-25T10:03:01.080 に答える