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 kill不掉线程的原因
May 07 MySQL
如何用Navicat操作MySQL
May 12 MySQL
MySQL中in和exists区别详解
Jun 03 MySQL
Mysql 如何实现多张无关联表查询数据并分页
Jun 05 MySQL
MySQL 全文检索的使用示例
Jun 07 MySQL
浅谈mysql增加索引不生效的几种情况
Jun 23 MySQL
mysql 数据插入优化方法之concurrent_insert
Jul 01 MySQL
MySQL系列之四 SQL语法
Jul 02 MySQL
mysql脏页是什么
Jul 26 MySQL
SQL实现LeetCode(180.连续的数字)
Aug 04 MySQL
mysql自增长id用完了该怎么办
Feb 12 MySQL
面试官问我Mysql的存储引擎了解多少
Aug 05 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
笑谈配置,使用Smarty技术
2007/01/04 PHP
php操作mysqli(示例代码)
2013/10/28 PHP
SCP远程VPS快速搬家和WDCP升级php5.3安装memcached和eaccelerator教程
2017/07/27 PHP
PHP convert_cyr_string()函数讲解
2019/02/13 PHP
window.location.hash 使用说明
2010/11/08 Javascript
DOM事件阶段以及事件捕获与事件冒泡先后执行顺序(图文详解)
2015/08/18 Javascript
JavaScript的History API使搜索引擎抓取AJAX内容
2015/12/07 Javascript
分享自己用JS做的扫雷小游戏
2016/02/17 Javascript
实例讲解JavaScript中call、apply、bind方法的异同
2016/09/13 Javascript
BootStrap表单宽度设置方法
2017/03/10 Javascript
基于VUE选择上传图片并页面显示(图片可删除)
2017/05/25 Javascript
Ionic项目中Native Camera的使用方法
2017/06/07 Javascript
把vue-router和express项目部署到服务器的方法
2018/02/21 Javascript
微信小程序实现图片滚动效果示例
2018/12/05 Javascript
详解Vue3.0 前的 TypeScript 最佳入门实践
2019/06/18 Javascript
详解webpack的文件监听实现(热更新)
2020/09/11 Javascript
python编程使用selenium模拟登陆淘宝实例代码
2018/01/25 Python
python爬虫获取新浪新闻教学
2018/12/23 Python
Python中的异常处理try/except/finally/raise用法分析
2019/02/28 Python
flask 实现上传图片并缩放作为头像的例子
2020/01/09 Python
python opencv如何实现图片绘制
2020/01/19 Python
pymysql之cur.fetchall() 和cur.fetchone()用法详解
2020/05/15 Python
Python字节单位转换(将字节转换为K M G T)
2021/03/02 Python
英国标志性奢侈品牌:Burberry
2016/07/28 全球购物
手工制作的意大利礼服鞋:Ace Marks
2018/12/15 全球购物
附答案的Java面试题
2012/11/19 面试题
通信工程专业个人找工作求职信范文
2013/09/21 职场文书
班组长岗位职责范本
2014/01/05 职场文书
自我反省检讨书
2014/01/23 职场文书
生产厂长岗位职责
2014/02/21 职场文书
新任教师自我鉴定
2014/02/24 职场文书
诚实守信演讲稿
2014/09/01 职场文书
2015年试用期工作总结
2014/12/12 职场文书
师德先进个人事迹材料
2014/12/19 职场文书
聘任书范文大全
2015/09/21 职场文书
MySQL去除密码登录告警的方法
2022/04/20 MySQL