貌似很久不写博客了,趁着项目刚完结,记录一下这段时间了解到的一些认识,或许有些地方理解的还不够到位,看到的希望能不吝赐教。

  • 外键

    • 概念
    • 与索引的关系
    • 写法
  • 查询
    • 一对多多对一查询
    • 多对多查询
  • 插入
    • 多对一一对多
    • 多对多插入
  • 总结

外键

虽然要记录的是关于MySQL的一些内容,但是对于大多数的关系型数据库也是通用的。

概念

在百度百科中,有这样的一个词条: 外键

如果公共关键字在一个关系中是主关键字,那么这个公共关键字被称为另一个关系的外键。由此可见,外键表示了两个关系之间的相关联系。以另一个关系的外键作主关键字的表被称为主表,具有此外键的表被称为主表的从表。外键又称作外关键字。

通俗来讲,外键就是从表用来关联主表的一个约束。外键是用来实现参照完整性的,不同的外键约束方式将可以使两张表紧密的结合起来,特别是修改或者删除的级联操作将使得日常的维护工作更加轻松。

外键主要用来保证数据的完整性和一致性。, 而且在MySQL中,由于引擎的关系,只有聚集索引InnoDB才支持外键,而非聚集索引MyISAM则不支持外键约束。所以接下来的内容是基于InnoDB的。

与索引的关系

可以认为,外键对于从表而言只是一个特殊的字段,一个约束关系。其功能就是实现两(多)张表的数据的完整性和一致性。

当创建完成一个外键的时候,数据库会默认创建索引。来提升两(多)表查询的效率。 关于更加低层的索引和外键的关系,这里暂且不过多叙述。

外键和索引的关系可以一起来看个小例子。

mysql> desc students;
+----------+-------------+------+-----+---------+----------------+
| Field    | Type        | Null | Key | Default | Extra          |
+----------+-------------+------+-----+---------+----------------+
| id       | int(12)     | NO   | PRI | NULL    | auto_increment |
| name     | varchar(32) | NO   |     | NULL    |                |
| class_id | int(12)     | NO   | MUL | NULL    |                |
+----------+-------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)mysql> desc classes;
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| id    | int(12)     | NO   | PRI | NULL    | auto_increment |
| name  | varchar(32) | NO   |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)

很典型的多对一(一对多)关系,一个学生属于一个班级,一个班级有好多学生。所以班级表为主表, 学生表即为从表

  • 索引信息:

  • 外键信息:

写法

标准的SQL式外键的写法如下:

[CONSTRAINT [symbol]] FOREIGN KEY
[index_name] (index_col_name, ...)
REFERENCES tbl_name (index_col_name,...)
[ON DELETE reference_option]
[ON UPDATE reference_option]

而对于上面的reference_option有这么几个可选项(在MySQL中):

  • RESTRICT: 当在主表(即外键的来源表)中更新、删除对应记录时,首先检查该记录是否有对应外键,如果有则不允许更新、删除。

  • CASCADE: 主表更新或者删除相关的记录,则会自动的更新或者删除从表中与之相匹配的数据。

  • SET NULL: 当从表中的外键字段没有被设置为NOT NULL的时候,当主表更新或者删除相关的记录时,从表中与之相匹配的记录会被设置为NULL

  • NO ACTION: InnoDB拒绝删除或者更新主表。即如果存在从数据,不允许删除主数据。

需要注意的是:

NO ACTION和RESTRICT的区别:只有在及个别的情况下会导致区别,前者是在其他约束的动作之后执行,后者具有最高的优先权执行。


查询

理解了上面的创建过程,其实还是远远不够的。最好是来几个比较生动的小例子来加深一下记忆。关于单表的查询内容,相比大家都很熟悉了。这里就不过多叙述咯。

一对多(多对一)查询

在数据库内,比单表操作稍微难那么一点点的,应该就是两张表上的查询了。下面来举个简单的小例子。

mysql> select * from classes;
+----+----------+
| id | name     |
+----+----------+
|  1 | 软1414班 |
|  2 | 软1413班 |
|  3 | 软1415班 |
|  4 | 软1409班 |
+----+----------+
4 rows in set (0.00 sec)mysql> select * from students;
+----+------------+----------+
| id | name       | class_id |
+----+------------+----------+
|  1 | 郭璞       |        1 |
|  2 | Gad GO     |        2 |
|  3 | 陈Sir      |        3 |
|  4 | MagicTiger |        4 |
+----+------------+----------+
4 rows in set (0.00 sec)

可以看出,一对多(多对一)关系的查询操作也是很简单的。由于我们设置的外键策略为CASCADE,所以当主表数据更新或者删除的时候,从表的数据也会相应的更改。

比如删除班级编号为4的行记录,然后再次观察一下结果会怎样。

mysql> select * from students;
+----+--------+----------+
| id | name   | class_id |
+----+--------+----------+
|  1 | 郭璞   |        1 |
|  2 | Gad GO |        2 |
|  3 | 陈Sir  |        3 |
+----+--------+----------+
3 rows in set (0.00 sec)

班级编号为4的记录被删除后,对应到从表(students)中的MagicTiger记录也被删除了。

那么我们将外键策略更改为RESTRICT试试。同样,这次将主表(classes)编号为1的记录内容更改一下。

根据错误提示,我们会发现,由于从表(students)有相关记录引用了主表(classes)的某条记录,根据外键约束原则,不能随意删除或者更改。


多对多查询

多对多的关系也比较普遍,比如对于一个博客系统而言。一篇文章可以附属多个标签,而一个标签下可以拥有很多文章。这就是典型的多对多关系了。

mysql> select * from posts;
+----+--------------------------+
| id | title                    |
+----+--------------------------+
|  1 | 张三,你快乐吗?         |
|  2 | 张三,编程能使你快乐吗? |
|  3 | 张三,编程能使你快乐吗? |
|  4 | 张三,编程能使你快乐吗? |
+----+--------------------------+
4 rows in set (0.00 sec)mysql> select * from tags;
+----+----------+
| id | name     |
+----+----------+
|  1 | 心情随笔 |
|  2 | 心得体会 |
|  3 | 感悟     |
|  4 | 心情随笔 |
|  5 | 心得体会 |
|  6 | 感悟     |
|  7 | 心情随笔 |
|  8 | 心得体会 |
|  9 | 感悟     |
+----+----------+
9 rows in set (0.00 sec)mysql> select * from posts_tags;
+----+---------+--------+
| id | post_id | tag_id |
+----+---------+--------+
|  1 |       1 |      1 |
|  2 |       1 |      2 |
|  3 |       1 |      3 |
+----+---------+--------+
3 rows in set (0.00 sec)

然后我们来个多对多关系的查询。

mysql> SELECT
    -> p.title '文章标题',
    -> t. NAME '标签'
    -> FROM
    -> posts AS p,
    -> tags AS t,
    -> posts_tags AS pt
    -> WHERE
    -> p.id = pt.post_id
    -> AND t.id = pt.tag_id;
+------------------+----------+
| 文章标题         | 标签     |
+------------------+----------+
| 张三,你快乐吗? | 心情随笔 |
| 张三,你快乐吗? | 心得体会 |
| 张三,你快乐吗? | 感悟     |
+------------------+----------+
3 rows in set (0.00 sec)

这样就能把多对多的两张表之间的数据关联起来了。核心在于,把表示关系的第三张表当做是查询的纽带


插入

刚才的数据其实是我使用SQL语句插入的,为了更好的记录这些知识点,就把插入数据的步骤留在了后面。

多对一(一对多)

对于多对一(一对多)这样的表,插入数据的情况比较简单,只需要注意好外键带来的约束关系即可。还是拿本次这个学生-班级表来说,一个新来的学生势必要分配给一个班级的(这里不考虑一个班级只有一个学生的情况)。也就是说,一定会先有班级,然后才能分配学生到底在哪个班级。

  • 正常插入一个有班级的学生。
mysql> select * from students;
+----+--------+----------+
| id | name   | class_id |
+----+--------+----------+
|  1 | 郭璞   |        1 |
|  2 | Gad GO |        2 |
|  3 | 陈Sir  |        3 |
+----+--------+----------+
3 rows in set (0.01 sec)mysql> insert into students(name, class_id) values('小薇', 1);
Query OK, 1 row affected (0.08 sec)mysql> select * from students;
+----+--------+----------+
| id | name   | class_id |
+----+--------+----------+
|  1 | 郭璞   |        1 |
|  2 | Gad GO |        2 |
|  3 | 陈Sir  |        3 |
|  4 | 小薇   |        1 |
+----+--------+----------+
4 rows in set (0.00 sec)
  • 当班级编号不存在时,由于外键约束,插入会失败。
mysql> select * from classes;
+----+----------+
| id | name     |
+----+----------+
|  1 | 软1411班 |
|  2 | 软1413班 |
|  3 | 软1415班 |
+----+----------+
3 rows in set (0.01 sec)mysql> insert into students(name, class_id) values('宋仲基', 7);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`relations`.`students`, CONSTRAINT `fk_student_class` FOREIGN KEY (`class_id`) REFERENCES `classes` (`id`))
mysql>

因此,在对一个数据库进行关系设计的时候,考虑清楚外键是否有必要还是挺有用的。

多对多插入

刚才记录了关于多对多关系查询的例子。而且从外键上也只能看到ON DELETEON UPDATE 这俩选项,也许你会疑惑, 为什么没有INSERT啊?答案是数据库其实并没有那么的智能,它没办法自动的分辨出你的这篇文章会被打上什么标签, 也不会分辨出你这个标签下会挂上多少个文章。这些工作是需要我们手动(或者说根据程序指定)的方式来添加的。

还是拿本次的博客系统中:博客–标签来举例。一篇文章被发表的时候会根据用户的选择打上一些个标签,我们需要把文章插入到数据库的同时,将标签与文章的关系放到关系表中。如下:

START TRANSACTION;INSERT INTO posts_tags (post_id, tag_id) SELECTp.id,t.id
FROMposts p,tags t
WHEREp.id = (SELECTp.idFROMpWHEREtitle = "张三,你快乐吗?")
AND t.id IN (SELECTt.idFROMtWHERENAME IN ('心情随笔','心得体会','感悟')
);COMMIT;

这样就可以将博客和标签之间的关系持久化到第三张关系表中了。

mysql> select * from posts_tags;
+----+---------+--------+
| id | post_id | tag_id |
+----+---------+--------+
|  1 |       1 |      1 |
|  2 |       1 |      2 |
|  3 |       1 |      3 |
+----+---------+--------+
3 rows in set (0.01 sec)

一般而言,使用事务会更加安全一些,当然了使用触发器也是可以的,但是触发器不能保证语句被正确执行。而采用事务就可以原子性的实现。

上面的SQL语句看起来仍然不够优雅,更好的替代方式是编写一个存储过程,接收参数,然后在事务中实现这个功能。


总结

回顾一下,感觉写的还是很浅显。由此可见,关系型数据库学问多着哩。O(∩_∩)O哈哈~

MySQL笔记之多表相关推荐

  1. MySQL 笔记5 -- 多表查询

    MySQL 笔记5 – 多表查询 MySQL 系列笔记是笔者学习.实践MySQL数据库的笔记 课程链接: MySQL 数据库基础入门教程 参考文档: MySQL 官方文档 一.表之间关系 1.一对一 ...

  2. MySql笔记之数据表

    数据表:行称为记录  列称为字段 用来存储数据 一.数据类型 数据类型是指列.存储过程参数.表达式和局部变量的数据特征,它决定了数据的存储格式,代表了不同的信息类型. 在我们存储不同类型的数据时,为了 ...

  3. 【MYSQL笔记】修改表

    实例表:员工信息表:id(varchar(10)),name(varchar(100)),age( int ) 修改列的数据类型: alter table 表名 modify 列名 数据类型; 例:列 ...

  4. MySQL笔记--2、3、4、5

    1.目的:设置合适的数据类型给字段 一.整数类型 例如 (1)create table student(xh char(10),nl tinyint unsigned,sr dataime,dz va ...

  5. MySQL学习笔记(六)-MySQL中库和表的管理

    MySQL学习笔记(六)-MySQL中库和表的管理 作者:就叫易易好了 日期:2020/11/23 1 2 DDL即数据定义语言 创建:create 修改:alter 删除:drop 库和表的管理: ...

  6. 5.15 mysql 数据库(数据库/表操作/索引/pymysql/备份与恢复/事务/锁) 学习笔记

    文章目录 1 初始数据库 1)数据库 2)mysql 3)和用户权限相关的 4)基本操作 2 表操作 1)存储引擎 2)表和数据的一些基本操作 3)mysql中的数据类型 4)表的完整性约束 5)修改 ...

  7. mysql事务手写笔记_兴奋了!阿里技术官手写“MySQL笔记”,传授你年薪百万级干货...

    前言 MySQL重要吗?重要!为什么重要?因为它在Java企业级开发中非常常用,因为 MySQL 是开源免费的,并且方便扩展.阿里巴巴数据库系统也大量用到了 MySQL,因此它的稳定性是有保障的.My ...

  8. 涂抹mysql笔记-mysql复制特性

    涂抹mysql笔记-mysql复制特性 mysql复制特性:既可以实现整个服务(all databases)级别的复制,也可以只复制某个数据库或某个数据库中的某个指定的表对象.即可以实现A复制到B(主 ...

  9. MySQL 笔记9 -- PyMySQL

    MySQL 笔记9 – PyMySQL MySQL 系列笔记是笔者学习.实践MySQL数据库的笔记 参考文档: MySQL 官方文档 SQL 教程 PyMySQL官方文档 一.基础 1.简介 PyMy ...

最新文章

  1. PHP设计模式之组合模式(Composite Pattern)
  2. Http接口开发(自测服务端客户端)
  3. Java虚拟机的Heap监狱
  4. nacos dataid修改配置文件_nacos 配置中心自动化运维之namespace坑
  5. postgreSQL源码分析——索引的建立与使用——GIST索引(3)
  6. 据说微软已撤销了测试部门?
  7. Silverlight 5的新功能预测
  8. 全国行政区划json数据包
  9. ECharts绘制中国地图、广西地图
  10. Android必知必会-App 常用图标尺寸规范汇总
  11. 用python还需要stata吗_极冷知识点——Stata/Python/R自带数据导入(附代码)
  12. MG513P30 12V直流减速电机编码器电线与杜邦线焊接教程
  13. 电脑录制网课视频怎么操作?
  14. 安庆集团-冲刺日志(第四天)
  15. Kali离线安装Nessus及过程中可能遇到的问题解决方案
  16. 在梦想的道路上,一路前行
  17. 小野さん と ペット
  18. 高性能消息中间件 nsq 解析-介绍
  19. 关于联合体及联合体嵌套结构体
  20. Hadoop、Pig、Hive、Storm、NOSQL 学习资源收集【Updating】

热门文章

  1. 共赴 Google Cloud 2022 中国出海数字峰会,探索更多可能
  2. 哪个平板电脑触控笔最好用,好用又便宜的平替苹果笔
  3. 【雅思大作文考官范文】——第二十篇: 'university subjects'
  4. SLAM综述性论文阅读手记
  5. 4.18 使用HDR色调工具制作特殊艺术效果 [原创Ps教程]
  6. 微信小程序云开发-云数据库表里所有数据新增某字段
  7. Python入门级爬虫教材,获取天天基金网站的基金数据
  8. SaaS产品订阅模式客户分析方法总结
  9. php中上传图片到mysql数据库中
  10. 学校智慧照明系统的应用意义