Leider gibt es keine so einfache und saubere Lösung wie für Ihre vorherige Frage .
Das sollte funktionieren:
-
Fügen Sie ein Redundanz-Flag
is_published
hinzu zumChild
TabelleALTER TABLE child ADD column is_published boolean NOT NULL;
Setzen Sie es auf
DEFAULT FALSE
oder was auch immer Sie normalerweise beim Einfügen in übergeordneten Spalten haben.
Es mussNOT NULL
sein um eine Lücke mitNULL
zu vermeiden Werte und StandardMATCH SIMPLE
Verhalten in Fremdschlüsseln:
Fremdschlüsselbeschränkung für zwei Spalten nur, wenn die dritte Spalte NICHT NULL ist -
Fügen Sie eine (scheinbar sinnlose, aber dennoch) eindeutige Einschränkung für
parent(parent_id, is_published)
hinzuALTER TABLE parent ADD CONSTRAINT parent_fk_uni UNIQUE (parent_id, is_published);
Seit
parent_id
der Primärschlüssel ist, wäre die Kombination in jedem Fall eindeutig. Aber das ist für die folgende fk-Einschränkung erforderlich. -
Statt auf
parent(parent_id)
zu verweisen mit einer einfachen Fremdschlüsselbeschränkung , erstellen Sie einen mehrspaltigen Fremdschlüssel für(parent_id, is_published)
mitON UPDATE CASCADE
.
Auf diese Weise wird der Status vonchild.is_published
angezeigt wird vom System automatisch und zuverlässiger gepflegt und durchgesetzt, als Sie es mit benutzerdefinierten Triggern implementieren könnten:ALTER TABLE child ADD CONSTRAINT child_special_fkey FOREIGN KEY (parent_id, is_published) REFERENCES parent (parent_id, is_published) ON UPDATE CASCADE;
-
Fügen Sie dann einen partial UNIQUE index hinzu wie in deiner vorherigen Antwort.
CREATE UNIQUE INDEX child_txt_is_published_idx ON child (text) WHERE is_published;
Natürlich beim Einfügen von Zeilen in das child
Tabelle sind Sie gezwungen, den aktuellen Stand von parent.is_published
zu verwenden jetzt. Aber das ist der Punkt:referentielle Integrität zu erzwingen.
Vollständiges Schema
Oder, anstatt ein bestehendes Schema anzupassen, hier das 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;