MySQL 里 FOREIGN KEY 的 CASCADE 、RESTRICT 选项有优先级吗?

2023-01-05 21:52:29 +08:00
 XiiLii

我有歌手、专辑和单曲三张表,关系如下:

如果删除歌手,专辑和单曲会被删除;

但,专辑被删除前,单曲会阻止专辑被删除;

现在我删除张三报错了(在 Django ORM 构建的这种关系是可以将张三删除的)

DELETE FROM Artist WHERE id=1; # 无法删除 张三

请问有没有大佬了解 MySQL 里外键的 CASCADE 、RESTRICT 选项有没有优先级?或其它什么机制?

我测试的表结构及数据如下:

CREATE TABLE Artist(# 歌手
	id INT PRIMARY KEY,
	NAME VARCHAR(10)
)

CREATE TABLE Album(# 专辑
	id INT PRIMARY KEY,
	artist VARCHAR(10),
	artist_id INT,
	FOREIGN KEY (artist_id)	REFERENCES Artist(id) 
	ON DELETE CASCADE ON UPDATE CASCADE # 歌手被删除时,他的专辑跟随一起被删除
)

CREATE TABLE Song(# 单曲
	id INT PRIMARY KEY,
	NAME VARCHAR(10),
	artist_id INT,
	album_id INT,
	FOREIGN KEY (album_id) REFERENCES Album(id) 
	ON DELETE RESTRICT ON UPDATE RESTRICT,# 专辑被删除前,单曲阻止专辑被删除
	FOREIGN KEY (artist_id) REFERENCES Artist(id) 
	ON DELETE CASCADE ON UPDATE CASCADE# 歌手被删除时,单曲跟随一起被删除
)

INSERT INTO Artist VALUES (1, "张三"), (2, "李四"); # 添加两名歌手:张三、李四
INSERT INTO Album VALUES (1, "光专辑", 1), (2, "夜专辑", 2); # 添加两张专辑:光专辑 属于 张三,夜专辑 属于 李四
INSERT INTO Song VALUES (1, "太阳", 1, 1), (2, "月亮", 1, 2); # 添加两首单曲:太阳 属于 张三的光专辑,月亮 属于 夜专辑(但不属于李四的单曲,而是属于张三的单曲)
653 次点击
所在节点    MySQL
2 条回复
lookStupiToForce
2023-01-06 12:10:32 +08:00
emmmmmm
手头没有 mysql 环境,而且也不知道你 mysql 版本,所以没测试 mysql
不过你确定删除张三会报错?按理来说不会的啊

至少我在 pgsql 里没有复现( version 12 )

另外感觉这不仅是 restrict 和 cascade 优先级的问题,而是 mysql 有没有检测到 restrict 的对象还有一层相关联的 cascade 的问题
也就是说,如果 mysql 检测到专辑 cascade 了歌手,而专辑 restrict 的歌曲也 cascade 了歌手,那么对歌手的所有操作都应当顺畅地 cascade 到专辑和歌曲上,而不用管什么 restrict 和 cascade 的优先级
如果你确定你报错了,说明你的 mysql 版本可能还不支持这种检测或者这种多层带 restrict 的 cascade 操作
XiiLii
2023-01-08 02:28:48 +08:00
@lookStupiToForce 是的,MySQL 8.0.24 报错:错误代码:1451
Cannot delete or update a parent row: a foreign key constraint fails (`test1`.`song`, CONSTRAINT `song_ibfk_1` FOREIGN KEY (`album_id`) REFERENCES `album` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT)

我之前用 Django ORM 可以成功删除,例子原型: https://docs.djangoproject.com/zh-hans/3.2/ref/models/fields/#django.db.models.RESTRICT

经过我测试,Django ORM 中的 PROTECT 才是 MySQL 中的 RESTRICT

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/906856

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX