场景
- 我把学生信息存在 Student表 里,班级信息存在 Class表里。Student表的 每一位学生都有 Class表里对应的 班级号cno 。
- 可当我 Class表中 班级号 393班 被改为 387班时,我就必须要去 Student 表 中把原来393班所有同学的班级号都改为387班。
- 可是这个过程我得写两条sql语句。能不能就执行一条sql语句,实现上面这个过程的更新操作呢?
问题
- 如何实现只执行一条SQL语句,同时修改不同表对应相同字段的数据值呢?
解决
- 可以利用数据库的
级联删除 / 级联更新
操作 实现自动修改多张表的同一字段值。 - 注:如果你已经创建了表且有数据的情况下,想实现级联自动更新或删除,那么这需要你重新设计表结构,再重新创建表。因此,我们这个工作应该在数据库表设计的阶段完成。如果有数据的也不要紧,先备份一下数据,等新表创建后再插入也不迟。
我们以修改班级号为例来分情况实现级联删除 或 级联更新 ”
1、我们先来看看 班级表 Class 和 学生表 STUDENT
班级表 Class{
cno 班级号(主键),
...
}
学生表 STUDENT {
sid 学号(主键),
cno 班级号(外部主键 简称 外键 ),
...
}
假设以下情况发生时,我们该如何如何创建表,实现对应操作。
例1: 当 cno=393 的班级号 改变为 cno=387 的班级号 时,393 班所有学生的班级号也应该 随着班级表中的班级号的更新而更新
。
create table student(
Sid int not null primary key auto_increment,
Cno varchar(10) not null ,
...
FOREIGN KEY(Cno) REFERENCES Class(Cno) ON UPDATE CASCADE
);
例2:当 cno=387 的班级号 被删除 时,而该班还有学生,不能造成学生没班级了,所以拒绝该操作
。
create table student(
Sid int not null primary key auto_increment,
Cno varchar(10) not null ,
...
FOREIGN KEY(Cno) REFERENCES Class(Cno) ON DELETE NO ACTION
);
2、我们再来看另外一个案例:
表结构如下:
菜品表 goods {
gId 菜品号(主键)
gName 菜品名
…
}
图片表 img {
iId 图片号 (主键)
gId 菜品id (外键)
…
}
例3:当 菜品表中 gId=3 的菜品 被删除 时,
图片表中 菜品id 为3的图片 也应该 随着菜品表中 gId=3 这道菜的 删除而删除
。
create table img(
iId int not null primary key ,
gId int not null ,
…
FOREIGN KEY(gId) REFERENCES goods(gId) ON DELETE CASCADE
);
总结
-
FOREIGN KEY(abc) REFERENCES table2(abc) ON UPDATE CASCADE
执行: 当table2 的表 字段abc 值被修改时,该表中对应 abc字段相同的值 自动修改
-
FOREIGN KEY(abc) REFERENCES table2(abc) ON DELETE NO ACTION
执行: 当table2 的表 字段abc 值被删除时,拒绝该删除操作,既不删除table2的数据,也不删除该表中的数据
-
FOREIGN KEY(abc) REFERENCES table2(abc) ON DELETE CASCADE
执行: 当table2 的表 字段abc 被删除时,该表中abc字段 相同值 对应的数据 自动删除
注:
- 参照的外部键必须是主键
FOREIGN KEY(外键字段名)
关键字中: 所填的外键字段名
必须是参考表的主键
。 - 建表顺序:
若Student 表
中 建立了 参考Class 表
的 外键 cno ,那么建表的顺序必须是:先建Class 表
再 建Student 表
。因为没有Class表的cno, Stundent 表 去哪找Class表来参考呢?