原在我的 Github 上,欢迎订阅。
其他文章:
前言
外键约束是mysql
提供的表与表之间的关联,使用它可以保证数据的一致性和完整性。
但是我问过同事,他们现在开发中不会使用外键约束,主要原因是数据量大或请求很频繁时会导致一些性能问题,实际开发中是通过业务代码来代替外键约束的功能。
但这不代表不需要学它,如果你的项目数据量不是很大,用外键约束还是非常方便的。
什么是外键
通过之前学习和练习,外键其实已经出现过,比如在student
表中:
学生表中包含一个class_id
,它指向class
(班级表)的id
,于是我们可以通过class_id
来查找这个学生的班级信息。
此时,对于student
表来说class_id
就是它的外键,外键字面意思就是指向外部的某个键,这里就是指向外部class
表的id
外键约束
多了“约束”两个字。 有约束代表着不能对含有外键关联的表随意删除和修改了,举个例子:
学生表 和 班级表 相互关联并有约束条件,如果有一天,你要删除某个班级,那班级里的学生怎么办呢?默认数据库会不让你删,因为班里还有学生存在。
OK,我们实际操作一把,现在把学生表和班级表加个外键约束:
ALTER TABLE student ADD CONSTRAINT student_class FOREIGN KEY (class_id) REFERENCES class(id);
解析一下上面的语句:
- ALTER TABLE student :对 student 表进行操作
- ADD CONSTRAINT student_class:添加约束,名称为 student_class
- FOREIGN KEY (class_id):指定外键是 class_id
- REFERENCES class(id):关联(参考) class 表的 id
看下结果:
为了好理解再看下 ER 图:
ON DELETE 和 ON UPDATE
ON DELETE 和 ON UPDATE 表示删除时 和 更新时 要处理的方式。
上面图里有删除时
和更新时
,这是数据删除和更新时的处理方式:
- NO ACTION 或 RESTRICT:对父表删除或更新时,必须把子表处理完才能删除或更新主表数据
- CASCADE:对父表删除或更新时,子表同时删除或更新
- SET NULL:对父表删除或更新时,子表设置为NULL
默认为 RESTRICT 。
NO ACTION 或 RESTRICT
来看下设置为 NO ACTION 或 RESTRICT 时,我们删除和更新数据试试:
id=1 的班级表中有对应的学生,我们来删除这个班级:
DELETE FROM class WHERE id=1;
更新也是一样:
UPDATE class SET id=10 WHERE id=1;
CASCADE
CASCADE: 对父表删除或更新时,子表同时删除或更新
我们来试一把。
先修改外键约束:
ALTER TABLE student DROP FOREIGN KEY student_class;
ALTER TABLE student ADD
CONSTRAINT student_class
FOREIGN KEY (class_id)
REFERENCES class(id)
ON DELETE CASCADE
ON UPDATE CASCADE;
可以看到已经改为CASCADE
了。
需要注意的是,要先删除外键约束 然后再重新生成。
现在我们来删除id=2
的班级:
DELETE FROM class WHERE id=2;
然后来看看班级和学生:
班级表中 id=2 的数据已经没有了
再看看学生表:
class_id=2 的学生也一起删了
现在修改一下试试,我们把id=1
的班级修改为 id=10
:
UPDATE class SET id=10 WHERE id=1;
修改成功:
再看看原本class_id=1
的学生怎么样了:class_id
也变成 10
了
SET NULL
SET NULL:对父表删除或更新时,子表设置为NULL
先把外键约束改成 SET NULL 的处理方式:
ALTER TABLE student DROP FOREIGN KEY student_class;
ALTER TABLE student
ADD CONSTRAINT student_class
FOREIGN KEY (class_id)
REFERENCES class(id)
ON DELETE SET NULL
ON UPDATE SET NULL;
为了演示方便,在student
表中添加一条数据:
现在我们删除 id=3
的班级:
id=3
的班级已经被删除,再看看 class_id=3
的学生怎么样了:
从图中看到,由于class_id=3
这个班级被删除,这个班里的学生没有了班级,所以class_id
为NULL
了。
我们再看下更新:
UPDATE class SET id=100 WHERE id=10;
上面语句是把id=10
的班级改为id=100
:
班级修改成功了,再看看这个班级下的学生:
原本 class_id=10
的学生现在也没有了班级,class_id
也置为 NULL
了。
总结
本篇学习了什么是外键约束,以及外键约束的几个处理方式:
- NO ACTION 或 RESTRICT:对父表删除或更新时,必须把子表处理完才能删除或更新主表数据
- CASCADE:对父表删除或更新时,子表同时删除或更新
- SET NULL:对父表删除或更新时,子表设置为NULL
默认为 RESTRICT 。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。