MySQL 外键约束和表关系相关总结


Posted in MySQL onJune 20, 2021
目录
  • 外键(Foreign Key)
  • 如何确定表关系
  • 如何建立表关系
    • 一对多关系 - 员工表和部门表
    • 多对多
    • 一对一
  • 表关系总结

 

外键(Foreign Key)

按照上述所说,一张表存储员工信息会极大的浪费资源,重复数据太多,这个问题就类似于将所有的代码都写在了一个py文件中,因此我们可以将一个表拆成不同的表,在这不同的表之间建立关联,而建立关联就需要使用外键foreign key。外键也属于约束条件的一种。

 

如何确定表关系

表与表之间的关系有三种一对多、多对多、一对一。那么如何确定表与表之间的关系呢?

在确定表与表之间的关系时建议换位思考,什么意思呢?就是分别站在两张表的角度去考虑,比如员工表和部门表的关系:

先站在员工表的角度:员工表中一个员工能否属于多个部门呢?答案是不能

再站在部门表的角度:部门表中一个部门能否有多个员工呢?答案是可以

因此员工表与部门表是单向的一对多,那么员工表和部门表就是一对多的关系。

 

如何建立表关系

在建立表关系时,表与表之间的关联通常以主键id作为关联字段。

 

一对多关系 - 员工表和部门表

在MySQL的关系在没有多对一的概念,一对多和多对一都是一对多。在创建一对多表关系时需要遵循以下几点:

第一,外键字段建立在多的一方,即员工表

第二,在创建表的时候,一定要先创建被关联一方,即部门表

第三,在录入数据的时候也必须先录入被关联表的数据,即部门表的数据

第四,当不同的表建立关系时,需要进行级联更新和删除也可以称为同步更新同步删除,如果不建立级联更新和删除的话,无法对被关联表中被关联的数据进行删除或者修改id的操作,因为两张表是相互关联的。

-- 创建被关联表,部门表
mysql> create table bm(
    id int primary key auto_increment, 
    bm_name varchar(10), 
    bm_desc char(64)
);
Query OK, 0 rows affected (0.01 sec)

mysql> desc bm;
+---------+-------------+------+-----+---------+----------------+
| Field   | Type        | Null | Key | Default | Extra          |
+---------+-------------+------+-----+---------+----------------+
| id      | int(11)     | NO   | PRI | NULL    | auto_increment |
| bm_name | varchar(10) | YES  |     | NULL    |                |
| bm_desc | char(64)    | YES  |     | NULL    |                |
+---------+-------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)

-- 创建外键所在的表,员工表
mysql> create table yg(
    id int primary key auto_increment, 
    yg_name varchar(6), 
    bm_id int, 
    foreign key(bm_id) references bm(id)  -- 表示bm_id是外键字段,关联到bm表中的id字段
    on update cascade  # 级联更新
    on delete cascade  # 级联删除
);
Query OK, 0 rows affected (0.10 sec)

mysql> desc yg;
+---------+------------+------+-----+---------+----------------+
| Field   | Type       | Null | Key | Default | Extra          |
+---------+------------+------+-----+---------+----------------+
| id      | int(11)    | NO   | PRI | NULL    | auto_increment |
| yg_name | varchar(6) | YES  |     | NULL    |                |
| bm_id   | int(11)    | YES  | MUL | NULL    |                |
+---------+------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)


-- 插入数据
mysql> insert into bm (bm_name, bm_desc) values ('python', '人生苦短'),('go', 'let us go');
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> select * from bm;
+----+---------+--------------+
| id | bm_name | bm_desc      |
+----+---------+--------------+
|  1 | python  | 人生苦短     |
|  2 | go      | let us go    |
+----+---------+--------------+
2 rows in set (0.00 sec)


mysql> insert into yg (yg_name, bm_id) values ('xu', 1), ('zhuang', 2), ('lili', 1);
Query OK, 3 rows affected (0.09 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select * from yg;
+----+---------+-------+
| id | yg_name | bm_id |
+----+---------+-------+
|  2 | xu      |     1 |
|  3 | zhuang  |     2 |
|  4 | lili    |     1 |
+----+---------+-------+
3 rows in set (0.00 sec)

-- 外键关联的数据必须在被关联表中存在否则会报错哦~
mysql> insert into yg (yg_name, bm_id) values ('xu', 3);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`book_manage`.`yg`, CONSTRAINT `yg_ibfk_1` FOREIGN KEY (`bm_id`) REFERENCES `bm` (`id`))

-- 如果不使用级联更新和删除的话会出现下面的错误,下述的SQL语句后面的文章都会介绍。。。
mysql> update bm set id=5 where id=2;  -- 将bm表中id=2的记录改为id=5
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`book_manage`.`yg`, CONSTRAINT `yg_ibfk_1` FOREIGN KEY (`bm_id`) REFERENCES `bm` (`id`))

mysql> delete from bm where id =2;  -- 删除bm表中id为2的那条记录
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`book_manage`.`yg`, CONSTRAINT `yg_ibfk_1` FOREIGN KEY (`bm_id`) REFERENCES `bm` (`id`))

 

多对多

多对多的关系以书籍和作者为例进行详细介绍,为什么书籍和作者属于多对多的关系呢?

先站在书籍表的角度:一本书是否可以有多个作者?答案是可以

再站在作者表的角度:一个作者是否可以写多本书?答案是可以

书籍表和作者表是双向的一对多那么这两张表的关系就是多对多。

我们先来创建两张表:

-- 创建书籍表
create table book(
    id int primary key auto_increment,
    title varchar(32),
    price int,
    author_id int,
    foreign key(author_id) references author(id)
    on update cascade
    on delete cascade
);

-- 创建作者表
create table author(
    id int primary key auto_increment,
    name varchar(32),
    age int,
    book_id int,
    foreign key(book_id) references book(id)
    on update cascade
    on delete cascade
);

如果按照上述方式创建表的话肯定是不可能成功的,在创建一对多的表关系时我我们说要先创建被关联表,也就是没有外键的表,可是多对多关系是双向的一对多,每张表中都会有外键的存在,怎么办呢?解决方案就是创建第三张表,这第三张表用来专门存储多对多关系的两张表的关联。

-- 创建书籍表
mysql> create table book(
    id int primary key auto_increment, 
    name varchar(10), 
    price int
);
Query OK, 0 rows affected (0.01 sec)

-- 创建作者表
mysql> create table author(
    id int primary key auto_increment, 
    name varchar(6), 
    age int
);
Query OK, 0 rows affected (0.01 sec)


-- 创建第三章表,存储book和author表的关联关系
mysql> create table book2author(
    id int primary key auto_increment, 
    author_id int, 
    book_id int, 
    foreign key(author_id) references author(id) 
    on update cascade 
    on delete cascade, 	
    foreign key(book_id) references book(id) 
    on update cascade 
    on delete cascade);
Query OK, 0 rows affected (0.02 sec)

 

一对一

如果一张表的字段特别多,每次查询数据时又不是所有的字段都能用的到,我们就可以将表一一分为二,比如说用户信息表,用户的信息包括用户名 密码 用户的年龄 用户的性别 地址 电话等等,可能经常用的只有用户的用户名和密码,这种情况我们就可以将一张用户信息表拆分成用户基本信息表和用户详细信息表,同样判断这两张表的关系还是通过换位思考:

首先看用户基本信息表:一个用户能否有多个详细信息?答案是不可以;

再看用户详情表:一个用户详情能否属于多个用户?答案是不可以;

单向的一对多都不成立,那么两者之间的表关系就是一对一或者没有关系。

使用SQL语句建立一对一的外键关系时,外键建在任意一方都可以,但是推荐将外键建在查询频率较高的表中,同样的,在创建表时还是先创建被关联表。

-- 创建用户详情表
create table authordetail(
	id int primary key auto_increment,
	phone int,
	addr varchar(64)
);

-- 用户基本信息表
create table author(
	id int primary key auto_increment,
    name varchar(32),
    age int,
    authordetali_id int,
    foreign key(authordetali_id) references authordetali(id)
    on update cascade
    on delete cascade
);

 

表关系总结

表关系建立需要使用外键foreign key,判断表与表之间的关系通过换位思考的方式。

一对多表关系:外键建在多的一方

一对一表关系:外键建在任意一方都可以,推荐建在查询频率高的一方

多对多表关系:需要单独创建第三张表存储两张表的关联关系

以上就是MySQL 外键约束和表关系相关总结的详细内容,更多关于MySQL 外键约束和表关系的资料请关注三水点靠木其它相关文章!

MySQL 相关文章推荐
MySQL表的增删改查(基础)
Apr 05 MySQL
.Net Core导入千万级数据至Mysql的步骤
May 24 MySQL
MySQL系列之四 SQL语法
Jul 02 MySQL
mysql 直接拷贝data 目录下文件还原数据的实现
Jul 25 MySQL
SQL实现LeetCode(175.联合两表)
Aug 04 MySQL
MySQL空间数据存储及函数
Sep 25 MySQL
一文弄懂MySQL索引创建原则
Feb 28 MySQL
MySQL之MyISAM存储引擎的非聚簇索引详解
Mar 03 MySQL
MySQL如何快速创建800w条测试数据表
Mar 17 MySQL
如何创建一个创建MySQL数据库中的datetime类型
Mar 21 MySQL
解决MySQL Varchar 类型尾部空格的问题
Apr 06 MySQL
解决Mysql中的innoDB幻读问题
Apr 29 MySQL
MySQL 使用索引扫描进行排序
Jun 20 #MySQL
新手入门Mysql--概念
mysql获取指定时间段中所有日期或月份的语句(不设存储过程,不加表)
MySQL REVOKE实现删除用户权限
Jun 18 #MySQL
MySQL GRANT用户授权的实现
Jun 18 #MySQL
浅谈MySQL user权限表
Jun 18 #MySQL
解决mysql模糊查询索引失效问题的几种方法
Jun 18 #MySQL
You might like
php扩展ZF――Validate扩展
2008/01/10 PHP
ThinkPHP上使用多说评论插件的方法
2014/10/31 PHP
php编写简单的文章发布程序
2015/06/18 PHP
php判断两个日期之间相差多少个月份的方法
2015/06/18 PHP
php生成4位数字验证码的实现代码
2015/11/23 PHP
PHP与jquery实时显示网站在线人数实例详解
2016/12/02 PHP
PHP配置ZendOpcache插件加速
2019/02/14 PHP
thinkphp5框架实现的自定义扩展类操作示例
2019/05/16 PHP
nicejforms——美化表单不用愁
2007/02/20 Javascript
锋利的jQuery 第三章章节总结的例子
2010/03/23 Javascript
jQuery的实现原理的模拟代码 -5 Ajax
2010/08/07 Javascript
js读取本地excel文档数据的代码
2010/11/11 Javascript
JavaScript全局函数使用简单说明
2011/03/11 Javascript
jQuery的.live()和.die() 使用介绍
2011/09/10 Javascript
javascript如何动态加载表格与动态添加表格行
2013/11/27 Javascript
不使用ajax实现无刷新提交表单
2014/12/21 Javascript
jQuery短信验证倒计时功能实现方法详解
2016/05/25 Javascript
AngularJS ui-router (嵌套路由)实例
2017/03/10 Javascript
基于Vue实现timepicker
2017/04/25 Javascript
vue给input file绑定函数获取当前上传的对象完美实现方法
2017/12/15 Javascript
记一次webpack3升级webpack4的踩坑经历
2018/06/12 Javascript
JS 数组基本用法入门示例解析
2020/01/16 Javascript
Python3爬虫之自动查询天气并实现语音播报
2019/02/21 Python
PyTorch中常用的激活函数的方法示例
2019/08/20 Python
Pytorch修改ResNet模型全连接层进行直接训练实例
2019/09/10 Python
python 实现dict转json并保存文件
2019/12/05 Python
Python基于Dlib的人脸识别系统的实现
2020/02/26 Python
Pycharm pyuic5实现将ui文件转为py文件,让UI界面成功显示
2020/04/08 Python
韩国爱茉莉太平洋化妆品美国站:Amore Pacific US
2016/10/28 全球购物
Brora官网:英国领先的羊绒服装品牌
2019/08/28 全球购物
LN-CC日本:高端男装和女装的奢侈时尚目的地
2019/09/01 全球购物
美国轻奢时尚购物网站:REVOLVE(支持中文)
2020/07/18 全球购物
企业统计员岗位职责
2013/12/13 职场文书
《花钟》教学反思
2016/02/17 职场文书
Ajax常用封装库——Axios的使用
2021/05/08 Javascript
Java 中的 Lambda List 转 Map 的多种方法详解
2022/07/07 Java/Android