Niestety, nie ma tak prostego i przejrzystego rozwiązania jak w przypadku Twoje poprzednie pytanie .
To powinno wystarczyć:
-
Dodaj nadmiarową flagę
is_published
doChild
stółALTER TABLE child ADD column is_published boolean NOT NULL;
Ustaw
DEFAULT FALSE
lub cokolwiek, co zwykle masz w kolumnach nadrzędnych podczas wstawiania.
Musi to byćNOT NULL
aby uniknąć luki zNULL
wartości i domyślneMATCH SIMPLE
zachowanie w kluczach obcych:
Dwukolumnowe ograniczenie klucza obcego tylko wtedy, gdy trzecia kolumna NIE JEST NULL -
Dodaj (pozornie bezsensowne, ale) unikalne ograniczenie do
parent(parent_id, is_published)
ALTER TABLE parent ADD CONSTRAINT parent_fk_uni UNIQUE (parent_id, is_published);
Od
parent_id
jest kluczem podstawowym, kombinacja byłaby unikalna. Ale jest to wymagane dla następującego ograniczenia fk. -
Zamiast odwoływać się do
parent(parent_id)
z prostym ograniczeniem klucza obcego , utwórz wielokolumnowy klucz obcy w(parent_id, is_published)
zON UPDATE CASCADE
.
W ten sposób stanchild.is_published
jest utrzymywany i wymuszany przez system automatycznie i bardziej niezawodnie niż można zaimplementować za pomocą niestandardowych wyzwalaczy:ALTER TABLE child ADD CONSTRAINT child_special_fkey FOREIGN KEY (parent_id, is_published) REFERENCES parent (parent_id, is_published) ON UPDATE CASCADE;
-
Następnie dodaj częściowy UNIKALNY indeks jak w Twojej poprzedniej odpowiedzi.
CREATE UNIQUE INDEX child_txt_is_published_idx ON child (text) WHERE is_published;
Oczywiście podczas wstawiania wierszy w child
tabela, w której musisz użyć aktualnego stanu parent.is_published
Teraz. Ale o to właśnie chodzi:wymusić integralność referencyjną.
Pełny schemat
Lub zamiast dostosowywać istniejący schemat, oto kompletny układ:
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;