За съжаление, няма толкова просто и чисто решение, колкото за предишния ви въпрос .
Това трябва да свърши работата:
-
Добавете излишен флаг
is_published
къмChild
таблицаALTER TABLE child ADD column is_published boolean NOT NULL;
Направете го
DEFAULT FALSE
или каквото обикновено имате в родителските колони при вмъкване.
Трябва да еNOT NULL
за да избегнете вратичка сNULL
стойности и по подразбиранеMATCH SIMPLE
поведение във външни ключове:
Ограничение за външен ключ за две колони само когато третата колона НЕ е NULL -
Добавете (привидно безсмислено, но все пак) уникално ограничение към
parent(parent_id, is_published)
ALTER TABLE parent ADD CONSTRAINT parent_fk_uni UNIQUE (parent_id, is_published);
От
parent_id
е първичен ключ, комбинацията ще бъде уникална и в двата случая. Но това е необходимо за следното fk ограничение. -
Вместо да препраща към
parent(parent_id)
с просто ограничение за чужд ключ , създайте външен ключ с няколко колони на(parent_id, is_published)
сON UPDATE CASCADE
.
По този начин състоянието наchild.is_published
се поддържа и налага от системата автоматично и по-надеждно, отколкото бихте могли да приложите с персонализирани тригери:ALTER TABLE child ADD CONSTRAINT child_special_fkey 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;
Разбира се, когато вмъквате редове в child
таблица сте принудени да използвате текущото състояние на parent.is_published
сега. Но това е смисълът:да се наложи референтна цялост.
Пълна схема
Или, вместо да адаптирате съществуваща схема, ето пълното оформление:
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;