六、数据表中的关联关系
6.1 关联关系介绍
MySQL是一个关系型数据库,不仅可以存储数据,还可以维护数据与数据之间的关系——通过在数据表中添加字段建立外键约束
数据与数据之间的关联关系分为四种:
-
一对一关联
-
一对多关联
-
多对一关联
-
多对多关联
6.2 一对一关联
人 — 身份证 一个人只有一个身份证、一个身份证只对应一个人
学生 — 学籍 一个学生只有一个学籍、一个学籍也对应唯一的一个学生
用户 — 用户详情 一个用户只有一个详情、一个详情也只对应一个用户
方案1: 主键关联——两张数据表中主键相同的数据为相互对应的数据
方案2:唯一外键一一在任意一张表中添加一个字段添加外键约束与另一张表主键关联,并且将外键列添加唯一约束
6.3 一对多与多对一
班级——学生 (一对多) 一个班级包含多个学生
学生——班级 (多对一) 多个学生可以属于同一个班级
图书——分类 商品-商品类别
方案:在多的一端添加外键,与一的一端主键进行关联
6.4 多对多关联
学生 — 课程 一个学生可以选择多门课、一门课程也可以由多个学生选择
会员 — 社团 一个会员可以参加多个社团、一个社团也可以招纳多个会员
方法:额外创建一张关系表来维护多对多关联——在关系表中定义两个外键,分别与两个数据表的主键进行关联
6.5 外键约束
外键约束——将一个列添加外键约束与另一张表的主键(唯一列)进行关联之后,这个外键约
束的列添加的数据必须要在关联的主键字段中存在
这里新建一个新的数据库,为了方便后续的测试,数据库名称为:db_test2
create database db_test2;
use db_test2;
案例:学生表 与 班级表 (在学生表中添加外键与班级表的主键进行关联)
创建原则,先创建不包含外键的表也就是班级表
-
先创建班级表
create table classes(class_id int primary key auto_increment,class_name varchar(40) not null unique,class_remark varchar(200) );
-
创建学生表(在学生表中添加外键与班级表的主键进行关联)
# 【方式一】在创建表的时候,定义cid字段,并添加外键约束 # 由于cid 列 要与classes表的class_id进行关联,因此cid字段类型和长度要与class_id一致 create table students(stu_num char(8) primary key,stu_name varchar(20) not null,stu_gender char(2) not null,stu_age int not null,cid int unique, #如果需要一对一关系,那么需要添加unique约束constraint FK_STUDENTS_CLASSES foreign key(cid) referencesclasses(class_id)# constraint(关键字) FK_STUDENTS_CLASSES(约束名称) foreign key(cid)(外键约束+具体字段) references classes(class_id)(关联的表的具体字段) );#【方式二】先创建表,再添加外键约束 create table students(stu_num char(8) primary key,stu_name varchar(20) not null,stu_gender char(2) not null,stu_age int not null,cid int );# 在创建表之后,为cid添加外键约束 # 修改学生表 添加约束 约束名称 外键约束(具体字段) 关联classes表的class_id列 alter table students add constraint FK_STUDENTS_CLASSES foreign key(cid) references classes(class_id);# 删除外键约束 alter table students drop foreign key FK_STUDENTS_CLASSES;
-
向班级表添加班级信息
insert into classes(class_name,class_remark) values('Java2104','...'); insert into classes(class_name,class_remark) values('Java2105','...'); insert into classes(class_name,class_remark) values('Java2106','...'); insert into classes(class_name,class_remark) values('Python2106','...'); select * from classes; +----------+------------+--------------+ | class_id | class_name | class_remark | +----------+------------+--------------+ | 1 | Java2104 | ... | | 2 | Java2105 | ... | | 3 | Java2106 | ... | | 4 | Python2106 | ... | +----------+------------+--------------+
-
向学生表中添加学生信息
insert into students(stu_num,stu_name,stu_gender,stu_age,cid) values('20210102','李斯','女',20, 4 );# 添加学生时,设置给cid外键列的值必须在其关联的主表classes的classs_id列存在 insert into students(stu_num,stu_name,stu_gender,stu_age,cid) values('20210103','王五','男',20, 6 );
6.6 外键约束级联
当学生表中存在学生信息关联班级表的某条记录时,就不能对班级表的这条记录进行修改
ID和删除操作,如下:
select * from classes;
+----------+------------+--------------+
| class_id | class_name | class_remark |
+----------+------------+--------------+
| 1 | Java2104 | ... | # 班级表中class_id=1的班级信息被学生表中的记录关联了
| 2 | Java2105 | ... | # 我们就不能修改Java2104的class_id,并且不能删除
| 3 | Java2106 | ... |
| 4 | Python2106 | ... |
+----------+------------+--------------+
mysql> select * from students;
+----------+----------+------------+---------+------+
| stu_num | stu_name | stu_gender | stu_age | cid |
+----------+----------+------------+---------+------+
| 20210101 | 张三 | 男 | 18 | 1 |
| 20210102 | 李四 | 男 | 18 | 1 |
| 20210103 | 王五 | 男 | 18 | 1 |
| 20210104 | 赵柳 | 女 | 18 | 2 |
+----------+----------+------------+---------+------+
update classes set class_id=5 where class_name='Java2104';
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key
constraint fails (`db_test2`.`students`, CONSTRAINT `FK_STUDENTS_CLASSES`
FOREIGN KEY (`cid`) REFERENCES `classes` (`class_id`))
delete from classes where class_id=1;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key
constraint fails (`db_test2`.`students`, CONSTRAINT `FK_STUDENTS_CLASSES`
FOREIGN KEY (`cid`) REFERENCES `classes` (`class_id`))
如果一定要修改Java2104 的班级ID,该如何实现呢 ?
将引用Java2104班级id的学生记录中的cid修改为 NULL
在修改班级信息表中Java2104记录的 class_id
将学生表中cid设置为NULL的记录的cid重新修改为 Java2104这个班级的新的id
1 update students set cid=NULL where cid=1; # 结果如下:
+----------+----------+------------+---------+------+
| stu_num | stu_name | stu_gender | stu_age | cid |
+----------+----------+------------+---------+------+
| 20210101 | 张三 | 男 | 18 | NULL |
| 20210102 | 李四 | 男 | 18 | NULL |
| 20210103 | 王五 | 男 | 18 | NULL |
| 20210104 | 赵柳 | 女 | 18 | 2 |
+----------+----------+------------+---------+------+
2 update classes set class_id=5 where class_name='Java2104'; # 结果如下
+----------+------------+--------------+
| class_id | class_name | class_remark |
+----------+------------+--------------+
| 2 | Java2105 | ... |
| 3 | Java2106 | ... |
| 4 | Python2106 | ... |
| 5 | Java2104 | ... |
+----------+------------+--------------+
3 update students set cid=5 where cid IS NULL; # 结果如下(null值需要通过IS关键字判断)
+----------+----------+------------+---------+------+
| stu_num | stu_name | stu_gender | stu_age | cid |
+----------+----------+------------+---------+------+
| 20210101 | 张三 | 男 | 18 | 5 |
| 20210102 | 李四 | 男 | 18 | 5 |
| 20210103 | 王五 | 男 | 18 | 5 |
| 20210104 | 赵柳 | 女 | 18 | 2 |
+----------+----------+------------+---------+------+
我 们 可 以 使 用 级 联 操 作 来 实 现 :
-
在添加外键时,设置级联修改 和 级联删除
# 删除原有的外键 alter table students drop foreign key FK_STUDENTS_CLASSES;# 重新添加外键,并设置级联修改和级联删除 alter table students add constraint FK_STUDENTS_CLASSES foreign key(cid) references classes(class_id) ON UPDATE CASCADE ON DELETE CASCADE; # ON UPDATE CASCADE ON DELETE CASCADE 表示添加修改和删除的级联操作
-
测试级联修改:
# 班级信息 +----------+------------+--------------+ | class_id | class_name | class_remark | +----------+------------+--------------+ | 2 | Java2105 | ... | | 3 | Java2106 | ... | | 4 | Python2106 | ... | | 5 | Java2104 | ... | +----------+------------+--------------+ # 学生信息 +----------+----------+------------+---------+------+ | stu_num | stu_name | stu_gender | stu_age | cid | +----------+----------+------------+---------+------+ | 20210101 | 张三 | 男 | 18 | 5 | | 20210102 | 李四 | 男 | 18 | 5 | | 20210103 | 王五 | 男 | 18 | 5 | | 20210104 | 赵柳 | 女 | 18 | 2 | +----------+----------+------------+---------+------+ # 直接修改Java2104的class_id,关联Java2104这个班级的学生记录的cid也会同步修 改 update classes set class_id=1 where class_name='Java2104'; # 班级信息 +----------+------------+--------------+ | class_id | class_name | class_remark | +----------+------------+--------------+ | 2 | Java2105 | ... | | 3 | Java2106 | ... | | 4 | Python2106 | ... | | 1 | Java2104 | ... | +----------+------------+--------------+ # 学生信息 +----------+----------+------------+---------+------+ | stu_num | stu_name | stu_gender | stu_age | cid | +----------+----------+------------+---------+------+ | 20210101 | 张三 | 男 | 18 | 1 | | 20210102 | 李四 | 男 | 18 | 1 | | 20210103 | 王五 | 男 | 18 | 1 | | 20210104 | 赵柳 | 女 | 18 | 2 | +----------+----------+------------+---------+------+
-
测试级联删除
# 删除class_id=1的班级信息,学生表引用此班级信息的记录也会被同步删除 delete from classes where class_id=1; +----------+------------+--------------+ | class_id | class_name | class_remark | +----------+------------+--------------+ | 2 | Java2105 | ... | | 3 | Java2106 | ... | | 4 | Python2106 | ... | +----------+------------+--------------++----------+----------+------------+---------+------+ | stu_num | stu_name | stu_gender | stu_age | cid | +----------+----------+------------+---------+------+ | 20210104 | 赵柳 | 女 | 18 | 2 | +----------+----------+------------+---------+------+
本笔记参考于[B站千锋教育javaweb开发视频教程],仅作学习用途,方便随时查看。
参考资料:B站千锋教育javaweb开发视频教程