on delete cascade和on update cascade需以innodb引擎为前提,要求父表被引用列有索引、子表外键列显式建索引、两字段类型严格一致(如int unsigned与int不兼容),否则级联失效。

ON DELETE CASCADE 和 ON UPDATE CASCADE 是 MySQL 中实现级联更新与删除最直接、最可靠的方式,但前提是必须用 InnoDB 引擎、正确建立外键并加索引。
外键级联必须满足的硬性条件
很多问题根本不是语法写错,而是底层约束没达标:
-
InnoDB引擎是强制要求 ——MyISAM表完全不支持外键,加了也会被忽略 - 父表被引用列(如
stu.sid)必须有索引(通常是主键,已自动满足) - 子表外键列(如
sc.sid)必须显式建索引,否则创建外键会失败 - 两字段类型必须严格一致:
INT UNSIGNED和INT不兼容,VARCHAR(20)和VARCHAR(25)也不行
CREATE TABLE 时直接定义级联行为
这是推荐做法,语义清晰、一次到位。别等表建好再 ALTER,容易漏掉索引或类型校验:
CREATE TABLE stu ( sid INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20) NOT NULL ) ENGINE=InnoDB CHARSET=utf8; <p>CREATE TABLE sc ( scid INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, sid INT UNSIGNED NOT NULL, score VARCHAR(20) DEFAULT '0', INDEX (sid), -- 必须!否则 FOREIGN KEY 创建失败 FOREIGN KEY (sid) REFERENCES stu(sid) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB CHARSET=utf8;</p>
注意:ON DELETE CASCADE 触发时机是父行被删后,子行自动消失;ON UPDATE CASCADE 是父行主键值被改时,子表对应外键值同步更新 —— 这个操作在业务中要慎用,主键更新本身就很罕见。
ALTER TABLE 添加外键级联(需补索引)
已有表想补级联?顺序不能错:
- 先给子表外键列加索引:
ALTER TABLE sc ADD INDEX (sid); - 再加外键约束:
ALTER TABLE sc ADD CONSTRAINT fk_sc_sid FOREIGN KEY (sid) REFERENCES stu(sid) ON DELETE CASCADE ON UPDATE CASCADE; - 如果报错
ERROR 1005 (HY000): Can't create table,大概率是类型不匹配或索引缺失
已存在的脏数据(比如 sc.sid = 999 但 stu 里没有 sid = 999)会导致外键添加失败,得先清理。
触发器是外键失效时的备选方案
当表是 MyISAM、或跨库、或需要复杂逻辑(比如删前记日志、按条件跳过某条子记录),才考虑触发器。但要注意:
-
AFTER DELETE触发器里不能再删同一张表,否则可能死锁或报Can't update table in stored function/trigger - 级联更新触发器必须判断
OLD.id != NEW.id,否则UPDATE stu SET name='x' WHERE sid=1也会误触发子表更新 - 触发器不参与事务回滚的自动管理 —— 如果主操作失败,触发器已执行的部分不会自动撤回
示例(安全的级联删除触发器):
DELIMITER $$ CREATE TRIGGER tr_after_delete_stu AFTER DELETE ON stu FOR EACH ROW BEGIN DELETE FROM sc WHERE sid = OLD.sid; END$$ DELIMITER ;
外键级联看着简单,但类型对齐、索引存在、引擎匹配这三点漏掉任何一个,ON DELETE CASCADE 就只是摆设。触发器看似灵活,却把一致性责任推给了开发者,出错时排查成本更高。











