Infelizmente, não há solução tão simples e limpa quanto para sua pergunta anterior .
Isso deve fazer o trabalho:
-
Adicione um sinalizador redundanteis_published
para oChild
tabela
ALTER TABLE child ADD column is_published boolean NOT NULL;
Torne-oDEFAULT FALSE
ou o que você normalmente tem nas colunas pai ao inserir.
Precisa serNOT NULL
para evitar uma brecha comNULL
valores e padrãoMATCH SIMPLE
comportamento em chaves estrangeiras:
Restrição de chave estrangeira de duas colunas somente quando a terceira coluna NÃO é NULL
-
Adicione uma restrição exclusiva (aparentemente inútil, mas) emparent(parent_id, is_published)
ALTER TABLE parent ADD CONSTRAINT parent_fk_uni UNIQUE (parent_id, is_published);
Desdeparent_id
é a chave primária, a combinação seria única de qualquer maneira. Mas isso é necessário para a seguinte restrição fk.
-
Em vez de referenciarparent(parent_id)
com uma simples restrição de chave estrangeira , crie uma chave estrangeira de várias colunas em(parent_id, is_published)
comON UPDATE CASCADE
.
Dessa forma, o estado dechild.is_published
é mantido e aplicado pelo sistema de forma automática e mais confiável do que você poderia implementar com gatilhos personalizados:
ALTER TABLE child ADD CONSTRAINT child_special_fkey FOREIGN KEY (parent_id, is_published) REFERENCES parent (parent_id, is_published) ON UPDATE CASCADE;
-
Em seguida, adicione um índice ÚNICO parcial como na sua resposta anterior.
CREATE UNIQUE INDEX child_txt_is_published_idx ON child (text) WHERE is_published;
Claro, ao inserir linhas no
child
tabela você é forçado a usar o estado atual de parent.is_published
agora. Mas esse é o ponto:reforçar a integridade referencial. Esquema completo
Ou, em vez de adaptar um esquema existente, aqui está o 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;