Desværre er der ingen løsning helt så enkel og ren som for dit tidligere spørgsmål .
Dette burde gøre jobbet:
-
Tilføj et redundant flag
is_published
tilChild
bordALTER TABLE child ADD column is_published boolean NOT NULL;
Gør det til
DEFAULT FALSE
eller hvad du typisk har i overordnede kolonner, når du indsætter.
Det skal væreNOT NULL
for at undgå et smuthul medNULL
værdier og standardMATCH SIMPLE
adfærd i fremmede nøgler:
To-søjlets fremmednøglebegrænsning kun, når tredje kolonne IKKE er NULL -
Tilføj en (tilsyneladende meningsløs, men alligevel) unik begrænsning på
parent(parent_id, is_published)
ALTER TABLE parent ADD CONSTRAINT parent_fk_uni UNIQUE (parent_id, is_published);
Siden
parent_id
er den primære nøgle, ville kombinationen være unik på begge måder. Men det er påkrævet for følgende fk-begrænsning. -
I stedet for at henvise til
parent(parent_id)
med en simpel fremmednøglebegrænsning , opret en fremmednøgle med flere kolonner på(parent_id, is_published)
medON UPDATE CASCADE
.
På denne måde er tilstandenchild.is_published
vedligeholdes og håndhæves af systemet automatisk og mere pålideligt, end du kunne implementere med tilpassede triggere:ALTER TABLE child ADD CONSTRAINT child_special_fkey FOREIGN KEY (parent_id, is_published) REFERENCES parent (parent_id, is_published) ON UPDATE CASCADE;
-
Tilføj derefter et delvist UNIKT indeks ligesom i dit tidligere svar.
CREATE UNIQUE INDEX child_txt_is_published_idx ON child (text) WHERE is_published;
Selvfølgelig, når du indsætter rækker i child
tabel er du tvunget til at bruge den aktuelle tilstand parent.is_published
nu. Men det er pointen:at håndhæve referentiel integritet.
Fuldstændig skema
Eller, i stedet for at tilpasse et eksisterende skema, er her det komplette layout:
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;