Neste caso específico estou usando um banco de dados SQLite, mas acredito que seja mais uma questão conceitual com implicações práticas.
Eu tenho um modelo de conjunto aninhado no meu banco de dados e gostaria de garantir que, quando um nó pai for excluído de alguma forma, todos os seus filhos também serão excluídos.
Da documentação do SQLite , os gatilhos permitem várias instruções, então eu tenho algo assim:
CREATE TABLE "tbl_nsm" (
"lft" INTEGER,
"rgt" INTEGER
);
CREATE TRIGGER IF NOT EXISTS "delete_entire_leaf" AFTER DELETE ON tbl_nsm
BEGIN
DELETE FROM tbl_nsm
WHERE 1=1
AND lft > OLD.lft
AND lft < OLD.rgt;
UPDATE tbl_nsm SET rgt = rgt - (OLD.rgt - OLD.lft + 1) WHERE rgt > OLD.rgt;
UPDATE tbl_nsm SET lft = lft - (OLD.rgt - OLD.lft + 1) WHERE lft > OLD.rgt;
END
;
No entanto, ao preencher a tabela com valores consistentes, sempre que apago um registro, o gatilho parece não fazer nada: todos os outros valores permanecem e não há um único aviso. Em vez de um AFTER DELETE
, mudei para um BEFORE DELETE
gatilho, mas sem sucesso.
Isso me fez pensar: você pode usar DELETE
gatilhos para excluir outros valores da sua tabela? Ou o SQL simplesmente ignora quaisquer alterações na tabela de destino de tal gatilho?
No SQLite, o gatilho pode modificar a tabela na qual está definido.
O gatilho não será acionado pela ação executada por este gatilho. Ou seja, se ON DELETE excluir outra linha, essa exclusão secundária não acionará esse gatilho novamente.
Mas ele disparará outro gatilho se outra ação for executada. Se esta ação secundária disparar primeiro, ela será disparada porque isso não é auto-disparo. Por exemplo, UPDATE aciona ON UPDATE que executa DELETE que aciona ON DELETE que executa UPDATE que causa ON UPDATE... e assim por diante, até que a cadeia pare devido à ausência da linha a ser alterada pelo gatilho. Portanto, use esse disparo cruzado com muita cautela. Isso pode resultar em loop infinito ou modificação de linhas em excesso (até a limpeza completa da tabela).
Você define o gatilho por instrução (não há FOR EACH ROW), mas a ação se parece com um por linha.