残念ながら、前の質問 。
これでうまくいくはずです:
-
冗長フラグ
is_published
を追加しますChild
へ テーブルALTER TABLE child ADD column is_published boolean NOT NULL;
DEFAULT FALSE
にします または、挿入時に親列に通常あるものは何でも。
NOT NULL
である必要があります。NULL
の抜け穴を避けるため 値とデフォルトのMATCH SIMPLE
外部キーでの動作:
3番目の列がNULLでない場合にのみ2列の外部キー制約 -
parent(parent_id, is_published)
に(一見無意味ですが)一意の制約を追加しますALTER TABLE parent ADD CONSTRAINT parent_fk_uni UNIQUE (parent_id, is_published);
parent_id
以降 が主キーである場合、組み合わせはどちらの方法でも一意になります。ただし、これは次のfk制約に必要です。 -
parent(parent_id)
を参照する代わりに 単純な外部キー制約> 、 (parent_id, is_published)
に複数列の外部キーを作成しますON UPDATE CASCADE
を使用 。
このようにして、child.is_published
の状態 カスタムトリガーで実装するよりも自動的かつ確実にシステムによって維持および実施されます:ALTER TABLE child ADD CONSTRAINT child_special_fkey FOREIGN KEY (parent_id, is_published) REFERENCES parent (parent_id, is_published) ON UPDATE CASCADE;
-
次に、部分的な一意のインデックス を追加します。 前の答えのように。
CREATE UNIQUE INDEX child_txt_is_published_idx ON child (text) WHERE is_published;
もちろん、Child
に行を挿入する場合 parent.is_published
の現在の状態を使用するように強制されたテーブル 今。しかし、それがポイントです。参照整合性を強制することです。
完全なスキーマ
または、既存のスキーマを適応させる代わりに、完全なレイアウトを次に示します。
CREATE TABLE parent(
parent_id serial PRIMARY KEY
, is_published bool NOT NULL DEFAULT FALSE
--, more columns ...
, UNIQUE (parent_id, is_published) -- required for fk
);
CREATE TABLE child (
child_id serial PRIMARY KEY
, parent_id integer NOT NULL
, is_published bool NOT NULL DEFAULT FALSE
, txt text
, FOREIGN KEY (parent_id, is_published)
REFERENCES parent (parent_id, is_published) ON UPDATE CASCADE
);
CREATE UNIQUE INDEX child_txt_is_published_idx ON child (text)
WHERE is_published;