MySQL 必须用 BEFORE DELETE 触发器清理子表,AFTER 会因 ERROR 1442 失败;PostgreSQL 和 SQL Server 更推荐外键 ON DELETE CASCADE 或 INSTEAD OF 触发器,避免手动逻辑踩坑、难维护。
可以,但必须用 BEFORE DELETE,且仅限于 MySQL 中需手动补逻辑的场景;PostgreSQL 和 SQL Server 更推荐用外键 ON DELETE CASCADE 或 INSTEAD OF 触发器——不是不能做,而是容易踩坑、难维护。
MySQL 在 AFTER DELETE 触发器里禁止对原表做任何读写操作(包括 SELECT 或 JOIN),否则直接抛出 ERROR 1442 (HY000)。因为行已物理删除,OLD.id 虽然还能访问,但无法安全定位子表关联数据(尤其当子表字段类型不一致时可能漏删)。
BEFORE DELETE 才能可靠拿到 OLD.id,并执行 DELETE FROM child WHERE parent_id = OLD.id
DELIMITER $$ 包裹触发器体,否则分号会让 MySQL 提前结束语句COMMIT 或 START TRANSACTION,MySQL 不允许显式事务控制ON DELETE CASCADE,就根本不需要这个触发器——先查约束是否存在PostgreSQL 原生支持 ON DELETE CASCADE,性能好、原子性强、可预测。触发器(如 BEFORE DELETE + 函数)只应在需要条件判断、日志记录或跨 schema 清理时才介入。
ON DELETE CASCADE,光有 REFERENCES 不生效parent_id 都指向真实父记录,否则 ADD CONSTRAINT 会失败并提示 violates foreign key constraint
DELETE FROM A 可能锁表数秒,需评估业务容忍度SQL Server 的 INSTEAD OF DELETE 会完全接管删除动作,但有个致命陷阱:它不会自动删父表本身——你得在触发器里显式写 DELETE FROM parent_table WHERE id IN (SELECT id FROM deleted),否则看起来“级联”了,其实父表还在。
deleted 是只读临时表,仅在触发器内可见,存着本次将被删的行INSTEAD OF 触发器,需确认是否开启嵌套触发器:sp_configure 'nested triggers', 1
JOIN 或分步 DELETE,避免单条语句锁表太久真正麻烦的不是写法,而是递归调用和隐式类型转换——比如主表 id 是 BIGINT UNSIGNED,子表 parent_id 是 INT,MySQL 会隐式转成有符号整型,导致索引失效、漏删;又或者父子表双向外键,触发器一触发就死循环。这些细节不跑通测试根本看不出来。
网易冷兵器新作《诡影藏锋》实机首曝:女鬼魅惑,恐怖拉满
炉石传说: Escape from Violet Hold 今日上线——探索游戏背后的人生哲理
亚马逊开启精选 4K 铁盒版促销:《回到未来》《侏罗纪世界》三部曲等作品迎来优惠
火线战姬最强英雄推荐:火线战姬高胜率角色排行与实战解析
斗罗大陆传承:新手入门指南与快速上手技巧
分析师称: 刺客信条4:黑旗 记忆重置 的 Steam 预购量已超过 碧海黑帆 的累计销量。