MySQL笔记之多表
貌似很久不写博客了,趁着项目刚完结,记录一下这段时间了解到的一些认识,或许有些地方理解的还不够到位,看到的希望能不吝赐教。
外键
虽然要记录的是关于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 DELETE 和 ON UPDATE 这俩选项,也许你会疑惑, 为什么没有INSERT啊?答案是数据库其实并没有那么的智能,它没办法自动的分辨出你的这篇文章会被打上什么标签, 也不会分辨出你这个标签下会挂上多少个文章。这些工作是需要我们手动(或者说根据程序指定)的方式来添加的。
还是拿本次的博客系统中:博客–标签来举例。一篇文章被发表的时候会根据用户的选择打上一些个标签,我们需要把文章插入到数据库的同时,将标签与文章的关系放到关系表中。如下:
START TRANSACTION;
INSERT INTO posts_tags (post_id, tag_id) SELECT
p.id,
t.id
FROM
posts p,
tags t
WHERE
p.id = (
SELECT
p.id
FROM
p
WHERE
title = "张三,你快乐吗?"
)
AND t.id IN (
SELECT
t.id
FROM
t
WHERE
NAME 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笔记之多表的更多相关文章
- MySql笔记之数据表
数据表:行称为记录 列称为字段 用来存储数据 一.数据类型 数据类型是指列.存储过程参数.表达式和局部变量的数据特征,它决定了数据的存储格式,代表了不同的信息类型. 在我们存储不同类型的数据时,为了 ...
- Mysql笔记4数据表操作1
1查看表的结构 (1)show create table +数据库名称 (2)desc+数据库名称 2修改表 (1)表中添加列 alter table 数据库名称 add column addr va ...
- 涂抹mysql笔记-管理mysql库和表
mysql的表对象是基于库维护的,也就是说它属于某个库,不管对象是由谁创建的,只要库在表就在.这根Oracle不同Oracle中的表对象是基于用户的.属于创建改对象的用户所有,用户在表就在.mysql ...
- MySQL笔记汇总
[目录] MySQL笔记汇总 一.mysql简介 数据简介 结构化查询语言 二.mysql命令行操作 三.数据库(表)更改 表相关 字段相关 索引相关 表引擎操作 四.数据库类型 数字型 字符串型 日 ...
- 涂抹mysql笔记-数据库中的权限体系
涂抹mysql笔记-数据库中的权限体系<>能不能连接,主机名是否匹配.登陆使用的用户名和密码是否正确.mysql验证用户需要检查3项值:用户名.密码和主机来源(user.password. ...
- MySQL笔记(六)游标练习
23.3.1 Trigger Syntax and Examples 意义不明的几道练习,留着备用. 感觉不好写,而且难以调试..不知道以后会不会有实际的应用场景. 环境:MySQL 笔记(三)由 t ...
- mysql 笔记(一)
mysql 笔记 预留 mysql> use mysql; mysql> grant all privileges on *.* to root@'%' identified by &q ...
- 【MySQL笔记】SQL语言四大类语言
SQL语言共分为四大类:数据查询语言DQL,数据操纵语言DML,数据定义语言DDL,数据控制语言DCL. 1. 数据查询语言DQL 数据查询语言DQL基本结构是由SELECT子句,FROM子句, ...
- 【MySQL笔记】mysql报错"ERROR 1206 (HY000): The total number of locks exceeds the lock table size"的解决方法
step1:查看 1.1 Mysql命令行里输入"show engines:"查看innoddb数据引擎状态, 1.2 show variables "%_buffer% ...
随机推荐
- 20145231熊梓宏 《网络对抗》 Bof逆向基础.shellcode注入
20145231网络对抗<逆向及Bof基础>shellcode注入 实验目的与要求 1.本次实践的对象是一个名为pwn1的linux可执行文件. 2.若该程序正常执行,则main函数会调用 ...
- C++实现最基本的LRUCache服务器缓存
目录: 一.介绍: 二.数据结构: 三.主要的两个函数接口Put()和Get(): 四.C++代码实现: 后台开发必备知识,不过我不是搞这个的,只是因为很久以前就想写这些东西,事情多,拖到现在.写的过 ...
- RMI远程方法调用
RMI远程方法调用:适用于 客户端 调用 服务器 内的方法:(Kotlin 语言编写) 如果业务为二个服务器之间的通信,还是得用消息队列的形式,因为RMI 不适合 双向 调用 下面介绍RMI 的使用方 ...
- LightOJ 1341 Aladdin and the Flying Carpet(唯一分解定理)
http://lightoj.com/volume_showproblem.php?problem=1341 题意:给你矩形的面积(矩形的边长都是正整数),让你求最小的边大于等于b的矩形的个数. 思路 ...
- Asp.Net Core 2.0 WebUploader FastDfs 文件上传 分段上传
功能点: 1. 使用.net core 2.0 实现文件上传 2. 使用webuploader实现单文件,多文件上传 3. 使用webuploader实现大文件的分段上传. 4. 使用webuploa ...
- C# 一些常用的字符串扩展方法
以下可能是常用的.net扩展方法,记录下 EString.cs文件 /// <summary> /// 扩展字符串类 /// </summary> public static ...
- Asp.Net将Session保存在数据库中
1.由于项目dll文件变动比较频繁,而保存登陆的状态又保存在Session中,所以导致用户经常无故掉线.(dll变动的时候导致Session丢失) 2.有一种方法可以长期保存session,那就是se ...
- (局部刷新)jquery.ajax提交并实现单个div刷新
web开发中我们经常会遇到局部刷新页面的需求,以前我经常使用ajax和iframe实现局部刷新,后来做政府的项目,对页面的样式要求比较多,发现使用iframe控制样式什么的很麻烦,所以就采用了新的办法 ...
- Memcached stats slabs 命令
Memcached stats slabs 命令用于显示各个slab的信息,包括chunk的大小.数目.使用情况等. 语法: stats slabs 命令的基本语法格式如下: stats slabs ...
- Linux虚拟机忘记root密码的拯救办法
于是百度之,还是有很多解决方案的.其原理就是,进入到single单用户模式下,去修改root密码: 1.重启系统,选择Linux引导,然后按住e,出现如下界面: 按下e 出现如下页面 选择kernel ...