Desafortunadamente, no existe una solución tan simple y limpia como para su pregunta anterior .
Esto debería hacer el trabajo:
-
Agregue una bandera redundante
is_published
alChild
mesaALTER TABLE child ADD column is_published boolean NOT NULL;
Hágalo
DEFAULT FALSE
o lo que tenga normalmente en las columnas principales al insertar.
Debe serNOT NULL
para evitar una escapatoria conNULL
valores y predeterminadoMATCH SIMPLE
comportamiento en claves foráneas:
Restricción de clave externa de dos columnas solo cuando la tercera columna NO es NULL -
Agregue una restricción única (aparentemente inútil, sin embargo) en
parent(parent_id, is_published)
ALTER TABLE parent ADD CONSTRAINT parent_fk_uni UNIQUE (parent_id, is_published);
Desde
parent_id
es la clave principal, la combinación sería única de cualquier manera. Pero eso es necesario para la siguiente restricción fk. -
En lugar de hacer referencia a
parent(parent_id)
con una simple restricción de clave externa , cree una clave externa de varias columnas en(parent_id, is_published)
conON UPDATE CASCADE
.
De esta manera, el estado dechild.is_published
es mantenido y aplicado por el sistema de forma automática y más confiable de lo que podría implementar con disparadores personalizados:ALTER TABLE child ADD CONSTRAINT child_special_fkey FOREIGN KEY (parent_id, is_published) REFERENCES parent (parent_id, is_published) ON UPDATE CASCADE;
-
Luego agregue un índice ÚNICO parcial como en tu respuesta anterior.
CREATE UNIQUE INDEX child_txt_is_published_idx ON child (text) WHERE is_published;
Por supuesto, al insertar filas en el child
estás obligado a usar el estado actual de parent.is_published
ahora. Pero ese es el punto:hacer cumplir la integridad referencial.
Esquema completo
O, en lugar de adaptar un esquema existente, aquí está el diseño 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;