Sfortunatamente, non esiste una soluzione così semplice e pulita come per la tua domanda precedente .
Questo dovrebbe fare il lavoro:
-
Aggiungi un flag ridondante
is_published
alChild
tabellaALTER TABLE child ADD column is_published boolean NOT NULL;
Rendilo
DEFAULT FALSE
o qualunque cosa tu abbia in genere nelle colonne principali durante l'inserimento.
Deve essereNOT NULL
per evitare una scappatoia conNULL
valori e predefinitoMATCH SIMPLE
comportamento nelle chiavi esterne:
vincolo di chiave esterna a due colonne solo quando la terza colonna NON è NULL -
Aggiungi un vincolo univoco (apparentemente inutile, ancora) su
parent(parent_id, is_published)
ALTER TABLE parent ADD CONSTRAINT parent_fk_uni UNIQUE (parent_id, is_published);
Da
parent_id
è la chiave primaria, la combinazione sarebbe univoca in entrambi i casi. Ma è necessario per il seguente vincolo fk. -
Invece di fare riferimento a
parent(parent_id)
con un semplice vincolo di chiave esterna , crea una chiave esterna a più colonne su(parent_id, is_published)
conON UPDATE CASCADE
.
In questo modo, lo stato dichild.is_published
viene mantenuto e applicato dal sistema automaticamente e in modo più affidabile di quanto potresti implementare con trigger personalizzati:ALTER TABLE child ADD CONSTRAINT child_special_fkey FOREIGN KEY (parent_id, is_published) REFERENCES parent (parent_id, is_published) ON UPDATE CASCADE;
-
Quindi aggiungi un indice UNIQUE parziale come nella tua risposta precedente.
CREATE UNIQUE INDEX child_txt_is_published_idx ON child (text) WHERE is_published;
Naturalmente, quando si inseriscono righe nel child
tabella sei costretto a usare lo stato corrente di parent.is_published
adesso. Ma questo è il punto:imporre l'integrità referenziale.
Schema completo
Oppure, invece di adattare uno schema esistente, ecco il layout completo:
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;