摘要:在设计表时需要考虑表和表之间的一些关系,表与表之间的关系分为三种,分别为一对一、一对多(多对一)、多对多。下面用例子介绍了这三种关系,还重点介绍了几种不同情况下对外键的创建、删除以及查看的操作,并进行了代码实现。

一、一对一

一对一:一张表(a表)的一条记录对应另一张表(b表)的一条记录,反过来,另一张表(b表)的一条记录只能对应该表(a表)的一条记录。

1、简介

例如:

  • 人的信息和身份证信息,一个人只有一个身份证号,一个身份证号只能被一个人使用。

建表原则:

  • 主表的主键和从表的外键形成主外键关系,外键必须唯一,也就是说从表的外键必须是主键。

但实际应用不多,因为这种情况完全可以建在一张表里。

编号

姓名

身份证外键

1

李四

1

2

王五

2

身份证编号

身份证号

1

12345

2

54321

像这样就根本没有必要,可以合成一张表

编号

姓名

身份证

1

李四

12345

2

王五

54321

二、一对多(多对一)

一对多(多对一):一张表中(a表)的一条记录对应另一张表(b表)的多条记录,但反过来,另一张表(b表)的一条记录只能对应该表(a表)的一条记录。

1、简介

例如:

  • 分类和商品:一个分类对应多个商品,一个商品只能属于一个分类。
  • 部门和员工:一个部门可以有多个员工,一个员工只能属于一个部门。
  • 班级和学生:一个班级可以有多个学生,一个学生只能属于一个班级。

建表原则:

  • 在多的一方创建一个字段作为外键指向一的一方的主键,也就是说多的一方是从表,一的一方是主表。
  • 建表时,一般先建主表,再建从表。举个例子:先建部门表,再建员工表,员工表中有一个部门编号(外键)指向部门的主键。

学生编号

学生姓名

所属班级

1

张三

1班

2

李四

2班

3

王五

1班

4

赵六

2班

由于学生会越来越多,保存的数据也越来越多,所属班级的重复率也会越来越高,可以分为两张表:班级表和学生表
班级表(主表)

班级编号

班级名称

1

1班

2

2班

学生表(从表)

学生编号

学生姓名

班级编号(外键)

1

张三

1

2

李四

2

3

王五

1

4

赵六

2

学生表中有一列专门存储的班级表的主键值,那么这一列对于学生表来说叫做外键列,包含外键的表叫做外键表,外键对应的表的主键所在的表我们叫做主键表。这里使用数字代替了原来的汉字,因此存储空间也能节约不少。

2、代码实现

  • 准备工作:
  1. 创建班级表(主表)
-- 创建主表
create table class(
	cno int primary key auto_increment,
	cname varchar(32)
);
  1. 创建学生表(从表)
-- 创建从表
create table student(
	sno int primary key auto_increment,
	sname varchar(32),
	s_cno int not null
);
  1. 在学生表(从表)的s_cno(外键字段)添加外键约束,依赖于班级表(主表)的cno(主键)
-- 在从表上的一个字段(外键字段)添加外键约束,依赖于主表的主键(班级编号)
alter table student add constraint fk_class_student foreign key(s_cno) references class(cno);
  • 验证外键约束
  1. 向班级表(主表)中添加数据
-- 向主表添加数据
insert into class values(null, '1班'),(null, '2班');
  1. 向学生表(从表)中添加数据
-- 向从表添加数据
insert into student values(null, '张三', 1),(null, '李四', 2);
  1. 向学生表(从表)中添加班级表(主表)不存在的班级号(被依赖的字段)
-- 向从表中添加主表不存在的班级号 会报错,因为违反了外键约束
insert into student values(null, '王五', 3),(null, '赵六', 4);

zabbix 表关系 表与表的关联关系_zabbix 表关系


由于学生表添加的学生所在的班级在班级表中找不到,因此无法添加。

解决方案1:添加学生信息时,修改预添加学生的班级号

解决方案2:添加学生信息前,班级表中添加需要的班级号

解决方案3:删除外键约束

  1. 删除班级表(主表)中指定的记录(学生表在使用的班级号)
-- 删除主键中已存在的班级 会报错
delete from class where cno = 2;

zabbix 表关系 表与表的关联关系_sql_02


因为该班级正被学生表的学生引用,因此不能删除。

解决方案1:删除该班级前,删除引用该班级的学生

解决方案2:删除外键约束

  • 解除外键约束
  1. 查询外键名

方法一:在表的创建信息中可以找到外键名;

-- 查询外键
show create table student;

zabbix 表关系 表与表的关联关系_数据库_03


方法二:在报错信息中也能找到外键名;

zabbix 表关系 表与表的关联关系_zabbix 表关系_04


方法三:在mysql客户端中该表的设计表的外键选项卡中可以找到外键名

zabbix 表关系 表与表的关联关系_数据库_05


方法四:通过INFORMATION_SCHEMA.KEY_COLUMN_USAGE.CONSTRAINT_NAME字段找到外键名

SELECT     C.TABLE_SCHEMA            拥有者,
           C.REFERENCED_TABLE_NAME  父表名称 ,
           C.REFERENCED_COLUMN_NAME 父表字段 ,
           C.TABLE_NAME             子表名称,
           C.COLUMN_NAME            子表字段,
           C.CONSTRAINT_NAME        约束名,
           T.TABLE_COMMENT          表注释,
           R.UPDATE_RULE            约束更新规则,
           R.DELETE_RULE            约束删除规则
      FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE C
      JOIN INFORMATION_SCHEMA. TABLES T
        ON T.TABLE_NAME = C.TABLE_NAME
      JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS R
        ON R.TABLE_NAME = C.TABLE_NAME
       AND R.CONSTRAINT_NAME = C.CONSTRAINT_NAME
       AND R.REFERENCED_TABLE_NAME = C.REFERENCED_TABLE_NAME
      WHERE C.REFERENCED_TABLE_NAME IS NOT NULL ;

zabbix 表关系 表与表的关联关系_zabbix 表关系_06

  1. 删除外键约束
alter table student drop foreign key fk_class_student;

三、多对多

多对多:一张表(a表)的一条记录能够对应另一张表(b表)的多条记录,同时,另一张表(b表)的一条记录也能对应该表(a表)的多条记录。

1、简介

例如:

  • 老师和学生:一个老师能教多个学生,一个学生也能被多个老师教。
  • 人和身份:一个人可以有多个身份,一个身份也能被多人使用。

建表规则:

  • 需要创建第三张表,中间表(外键表)中至少两个字段,这两个字段分别作为外键指向各自一方的主键。

学生表:

学生编号

学生名称

1

张三

2

李四

3

王五

身份表:

身份编号

身份名称

1

学生

2

课代表

3

班长

中间表:

学生编号(外键)

身份编号(外键)

1

1

1

2

1

3

2

1

2

2

3

1

含义:张三既是学生也是课代表还是个班长;李四既是学生又是课代表;王五只有一个学生身份。

2、代码实现

  • 准备工作:
  1. 创建学生表(主表)
-- 创建学生表(主表)
-- 指定约束名创建主键
create table student(
	sno int auto_increment,
	sname varchar(32),
	constraint pk_student_sno primary key(sno)
);
  1. 创建身份表(主表)
-- 创建身份表(主表)
create table identity(
	ino int auto_increment,
	iname varchar(32),
	constraint pk_identity_ino primary key(ino)
);
  1. 创建中间表(从表),并添加外键约束
-- 创建中间表(从表),并添加外键约束
-- 指定约束名创建外键
create table mid_stu_ide(
	m_sno int not null,
	m_ino int not null,
	constraint fk_student_mid foreign key(m_sno) references student(sno),
	constraint fk_identity_mid foreign key(m_ino) references identity(ino)
);
  1. 创建中间表的主键(可以省略)
-- 为中间表创建联合主键(可以省略这步,创建表时忘了,表外创建一波)
alter table mid_stu_ide add constraint pk_mid_msno_mino primary key(m_sno,m_ino);
  • 验证外键约束
  1. 向学生表中添加数据
-- 向学生表中添加数据
insert into student(sname) values('张三'),('李四'),('王五');
  1. 向角色表中添加数据
-- 向角色表中添加数据
insert into identity(iname) values('学生'),('课代表'),('班长');
  1. 向中间表中添加数据
-- 向中间表中添加数据
insert into mid_stu_ide values(1,1),(1,2),(1,3),(2,1),(2,2),(3,1);
  1. 查看学生和角色的对应关系
-- 查看学生和职务的对应关系
select sname,iname
from student s, identity i, mid_stu_ide m
where s.sno = m.m_sno and i.ino = m.m_ino
order by sname;

zabbix 表关系 表与表的关联关系_外键_07

  1. 删除中间表的数据(取消张三的课代表职务)
-- 删除中间表的数据
-- 取消张三的课代表身份
delete from mid_stu_ide where m_sno = 1 and m_ino=2;

zabbix 表关系 表与表的关联关系_数据库_08

  1. 向中间表添加不存在学生或身份的数据,由于外键约束,会报错。
-- 向中间表添加不存在的学生或身份的数据
insert into mid_stu_ide values (100,100);

因为中间表在插入时,会去学生表和职务表中找对应主键,但学生表和职务表中找不到对应的数据,因此会报错。

zabbix 表关系 表与表的关联关系_数据库_09

  1. 删除学生表或角色表中的数据,由于外键约束,会报错。
-- 删除学生表或角色表中的数据
delete from student where sno=1;

因为中间表还保存着这主键表的信息,所以不能删除。

zabbix 表关系 表与表的关联关系_zabbix 表关系_10

  • 解除外键约束
-- 解除外键约束
alter table mid_stu_ide drop foreign key fk_student_mid;
alter table mid_stu_ide drop foreign key fk_identity_mid;