在这种特定情况下,我使用的是 SQLite 数据库,但我认为这更像是一个具有实际意义的概念性问题。
我的数据库中有一个嵌套集模型,我想确保当父节点以某种方式从其中删除时,它的所有子节点也将被删除。
从 SQLite 的文档中,触发器允许多个语句,所以我得到了这样的东西:
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
;
但是,当使用一致的值填充表时,每当我删除一条记录时,触发器似乎什么都不做:所有其他值都保留下来,甚至没有一个警告。AFTER DELETE
我将其改为触发器,而不是BEFORE DELETE
,但无济于事。
这让我想到:您可以使用DELETE
触发器从表中删除更多值吗?或者 SQL 是否简单地忽略了对此类触发器的目标表的任何更改?
在 SQLite 中,触发器可以修改定义它的表。
此触发器执行的操作不会触发触发器。即,如果 ON DELETE 删除另一行,则此次要删除将不会再次触发此触发器。
但如果执行另一个操作,它将触发另一个触发器。如果这个辅助动作应该首先触发,那么它将被触发,因为这不是自触发的。例如,UPDATE 触发 ON UPDATE 执行 DELETE 触发 ON DELETE 执行 UPDATE 导致 ON UPDATE... 等等,直到链由于缺少要被触发器更改的行而停止。所以使用这种交叉射击要非常小心。这可能会导致无限循环或过多的行修改(直到完成表清除)。
您定义了每条语句触发器(没有 FOR EACH ROW),但操作看起来像每行触发器。