Helaas is er geen oplossing die zo eenvoudig en schoon is als voor je vorige vraag .
Dit zou het werk moeten doen:
-
Voeg een overbodige vlag toe
is_published
aan hetChild
tafelALTER TABLE child ADD column is_published boolean NOT NULL;
Maak het
DEFAULT FALSE
of wat je gewoonlijk in bovenliggende kolommen hebt bij het invoegen.
Het moetNOT NULL
zijn om een maas in de wet te vermijden metNULL
waarden en standaardMATCH SIMPLE
gedrag in buitenlandse sleutels:
Twee-koloms refererende sleutel beperking alleen wanneer de derde kolom NIET NULL is -
Voeg een (schijnbaar zinloze, maar toch) unieke beperking toe aan
parent(parent_id, is_published)
ALTER TABLE parent ADD CONSTRAINT parent_fk_uni UNIQUE (parent_id, is_published);
Sinds
parent_id
de primaire sleutel is, zou de combinatie hoe dan ook uniek zijn. Maar dat is vereist voor de volgende fk-beperking. -
In plaats van te verwijzen naar
parent(parent_id)
met een simpele buitenlandse sleutelbeperking , maak een externe sleutel met meerdere kolommen op(parent_id, is_published)
metON UPDATE CASCADE
.
Op deze manier wordt de status vanchild.is_published
wordt automatisch en betrouwbaarder door het systeem onderhouden en gehandhaafd dan u zou kunnen implementeren met aangepaste triggers:ALTER TABLE child ADD CONSTRAINT child_special_fkey FOREIGN KEY (parent_id, is_published) REFERENCES parent (parent_id, is_published) ON UPDATE CASCADE;
-
Voeg vervolgens een gedeeltelijke UNIEKE index toe zoals in je vorige antwoord.
CREATE UNIQUE INDEX child_txt_is_published_idx ON child (text) WHERE is_published;
Natuurlijk, bij het invoegen van rijen in de child
tabel bent u gedwongen om de huidige status van parent.is_published
. te gebruiken nu. Maar daar gaat het om:referentiële integriteit afdwingen.
Volledig schema
Of, in plaats van een bestaand schema aan te passen, is hier de volledige lay-out:
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;