Tyvärr finns det ingen lösning riktigt så enkel och ren som för din tidigare fråga .
Detta borde göra jobbet:
-
Lägg till en redundant flagga
is_publishedtillChildbordALTER TABLE child ADD column is_published boolean NOT NULL;Gör det till
DEFAULT FALSEeller vad du vanligtvis har i överordnade kolumner när du infogar.
Det måste varaNOT NULLför att undvika ett kryphål medNULLvärden och standardMATCH SIMPLEbeteende i främmande nycklar:
Tvåkolumns främmande nyckelbegränsning endast när den tredje kolumnen INTE är NULL -
Lägg till en (till synes meningslös men ändå) unik begränsning på
parent(parent_id, is_published)ALTER TABLE parent ADD CONSTRAINT parent_fk_uni UNIQUE (parent_id, is_published);Sedan
parent_idär den primära nyckeln, skulle kombinationen vara unik oavsett. Men det krävs för följande fk-begränsning. -
Istället för att referera till
parent(parent_id)med en enkel restriktion för främmande nyckel , skapa en främmande nyckel med flera kolumner på(parent_id, is_published)medON UPDATE CASCADE.
På detta sätt är tillståndet förchild.is_publishedunderhålls och upprätthålls av systemet automatiskt och mer tillförlitligt än vad du skulle kunna implementera med anpassade utlösare:ALTER TABLE child ADD CONSTRAINT child_special_fkey FOREIGN KEY (parent_id, is_published) REFERENCES parent (parent_id, is_published) ON UPDATE CASCADE; -
Lägg sedan till ett partiellt UNIKT index som i ditt tidigare svar.
CREATE UNIQUE INDEX child_txt_is_published_idx ON child (text) WHERE is_published;
Naturligtvis när du infogar rader i child tabell du tvingas använda det nuvarande tillståndet för parent.is_published nu. Men det är poängen:att upprätthålla referensintegritet.
Fullständigt schema
Eller, istället för att anpassa ett befintligt schema, här är den fullständiga layouten:
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;