MySQL之多表操作
前言:之前已经针对数据库的单表查询进行了详细的介绍:MySQL之增删改查,然而实际开发中业务逻辑较为复杂,需要对多张表进行操作,现在对多表操作进行介绍。
前提:为方便后面的操作,我们首先创建一个数据库 test,再在 test 里创建两个数据表:grade(班级表)和student(学生表)
创建数据库:CREATE DATABASE test;
选择要操作的数据表:USE test;
创建数据表:CREATE TABLE grade
(
id INT(4) NOT NULL PRIMARY KEY,
name varchar(36)
);
CREATE TABLE student
(
sid INT(4) NOT NULL PRIMARY KEY,
sname VARCHAR(36),
gid INT(4) NOT NULL
);
1、外键
定义:外键是指引用另一个表中的一列或多列,被引用的列应该具有主键约束或唯一性约束,外键用于建立和加强两个表数据之间的连接。在已经建立的grade表和student表中,student表中的gid就是grade表中的id,那么gid就可以作为student表的外键。其中,被引用的表grade就是主表,引用外键的表,即student表就是从表,两个表示主从关系。
1.1 为表添加外键约束
语法:ALTER TABLE 表名 ADD CONSTRAINT 外键名 FOREIGN KEY(外键字段名) REFERENCES 外表表名(主键字段名);
举例:为student表添加外键约束
命令:ALTER TABLE student ADD CONSTRAINT FK_ID FOREIGN KEY (gid) REFERENCES grade(id);
注意:定义外键名时不能加引号。
使用SHOW CREATE ABLE student命令查看student表:
结果:
说明名为“FK_ID”的外键已经成功添加。
注意:如果未出现此结果,需要先将 grade 表和 student 的 engine 改为 InnoDB ,命令为:ALTER TABLE grade ENGINE=InnoDB;ALTER TABLE student ENGINE=InnoDB;
1.2 删除外键约束
语法:ALTER TABLE 表名 DROP FOREIGN KEY 外键名;
举例:删除student表中的外键约束
命令:ALTER TABLE student DROP FOREIGN KEY FK_ID;
执行删除外键命令之后再使用 SHOW CREATE TABLE student;查看:
出现此结果说明外键已被成功删除。
2、操作关联表
2.1 关联关系
(1)多对一
数据表中最常见的一种关系,比如学生与班级的关系,一个班级可以有多个学生,但是一个学生不能属于多个班级。在多对一的关系中,应该将外键建在多的一方。
(2)多对多
比如学生与课程的关系,一个学生可以选择多门课程,一门课程也供多个学生选择
(2)一对一
比如一个人只有一张身份证,而一张身份证也只对应一个人。
2.2 添加数据
在表grade和表student中添加约束来建立两个表的关联关系:
ALTER TABLE student ADD CONSTRAINT FK_ID FOREIGN KEY(gid) REFERENCES grade (id);
先为主表grade添加数据:
INSERT INTO grade(id,name) VALUES (1,'软件一班'),(2,'软件二班');
此处若出现“1366错误”,可先执行如下命令:
ALTER TABLE grade CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci ;
查询插入数据后的grade表:
同理再在student表中插入数据,而且因为grade中添加的主键id只有1和2,所以student表中的gid字段值只能为1或者2,如下:
INSERT INTO student (sid,sname,gid) VALUES (1,'王红',1),(2,'李强',1),(3,'赵四',2),(4,'郝娟',2);
查询插入数据后的student表:
上述命令执行完之后,两个表之间就具有了关联性,假如要查询软件一班有哪些学生,就要先查询软件一班的 id ,再根据这个 id 在student表中查询有哪些学生。
步骤一:查出grade表中软件一班的 id :
命令:SELECT id FROM grade WHERE name='软件一班';
结果:
步骤二:根据 id=1 ,在student表中查出对应的学生。
命令:SELECT name FROM student WHERE gid=1;
结果:
2.3 删除数据
因为grade表和student表具有关联关系,,而参照列的被参照值是不能被删除的,所以若想删除grade表中的软件一班,必须先删除student表中软件一班对应的所有学生。
步骤1:删除软件一班所有学生
命令:DELETE FROM student WHERE sname='王红' OR sname='李强';
或者 DELETE FROM student WHERE gid=1;
查询:SELECT * FROM student WHERE gid=1;
结果:
说明软件一班的学生已经全部删除。
步骤二:在grade表中将软件一班删除
命令:DELETE FROM grade WHERE id=1;
查询:SELECT * FROM grade;
结果:
可见软件一班已被成功删除。
现在我们来看看直接删除软件二班会出现什么结果:
命令:DELETE FROM grade WHERE id=2;
结果:
由此可以得出结论:在两个具有关联关系的表中删除数据时,一定要先删除从表中的数据,再删除主表中的数据。
3、连接查询
在进行下面的操作之前,先在test数据库中创建两个表:department表和employee表。
USE test;
CREATE TABLE department
(
did INT(4) NOT NULL PRIMARY KEY,
dname VARCHAR(36)
);
CREATE TABLE employee
(
id INT(4) NOT NULL PRIMARY KEY,
name VARCHAR(36),
age INT(2),
did INT(4) NOT NULL
);
再向两个表插入数据:
INSERT INTO department(did,dname)
VALUES (1,'网络部'),(2,'媒体部'),(3,'研发部'),(5,'人事部');
INSERT INTO employee(id,name,age,did)
VALUES (1,'王红',20,1),(2,'李强',22,1),(3,'赵四',20,2),(4,'郝娟',20,4);
3.1 交叉连接
交叉连接返回的结果是被连接的两个表中所有数据行的笛卡尔集,也即返回第一个表中符合查询条件的数据行数乘以第二个表中符合查询条件的数据行数,例如,department表中有四个部门,employee表中有四个员工,那么交叉连接的结果就有4 * 4 = 16 条数据。
交叉连接的语法:SELECT * FROM 表1 CROSS JOIN 表2;
举例:使用交叉连接查询department表和employee表中的所有数据
命令:SELECT * FROM department CROSS JOIN employee;
结果:
3.2 内连接
内连接(Inner Join)又称简单连接或自然连接,是一种常见的连接查询。内连接使用比较运算符对两个表中的数据进行比较,并列出与连接条件匹配的数据行,组成新的记录。
语法:SELECT 查询字段 FROM 表1 [ INNER ] JOIN 表2 ON 表1.关系字段=表2.关系字段
其中 INNER JOIN 用于连接两个表,ON 来指定连接条件
举例:在department表和employee表之间使用内连接查询。
命令:SELECT employee.name,department.dname FROM department JOIN employee ON department.did=employee.did;
结果:
从结果可以看出,只有department.did 与employee.did 相等的员工才会被显示。
此处还可以使用WHERE 语句来实现同样的功能:
SELECT employee.name,department.dname FROM department,employee WHERE department.did=employee.did;
3.3 自连接
如果在一个连接查询中涉及的两个表其实是同一个表,这种查询称为自连接查询,例如要查询王红所在的部门有多少个人,就可以用自连接查询。
命令:SELECT p1.* FROM employee AS p1 JOIN employee AS p2 ON p1.did=p2.did WHERE p2.name='王红';
结果:
从结果看来,王红所在的部门有两个员工,分别是王红和李强。
3.4 外连接
外连接分为左连接和右连接,当返回的查询结果不仅需要包含符合条件的数据,还需要包含其中一个表或者两个表的所有数据的时候,需要用到外连接查询。
语法:SELECT 所查字段 FROM 表1 LEFT | RIGHT [ OUTER ] JOIN 表2
ON 表1.关系字段=表2.关系字段
WHERE 条件
(1)LEFT JOIN ——左连接:返回包括左表中的所有记录和右表中符合条件的记录。
举例:SELECT department.did,department.dname,employee.name FROM department LEFT JOIN employee ON department.did=employee.did;
结果:
在此结果中,department中的记录全部显示,而employee中只显示了符合条件的数据(一共四条记录,只显示了符合条件的其中3条),因为“人事部”没有人,所以相应的字段显示为NULL。
(2)LEFT JOIN ——右连接:与左连接相反,返回包括右表中的所有记录和左表中符合条件的记录。
举例:SELECT department.did,department.dname,employee.name FROM department RIGHT JOIN employee ON department.did=employee.did;
结果:
在此结果中,employee中的记录全部显示,而department中只显示了符合条件的数据,因为“郝娟”没有对应部门,所以相应的字段显示为NULL。
3.5 复合条件连接查询
复合条件连接查询指在连接查询时,通过添加限制条件来过滤结果。
举例:在department表和employee表中使用内连接查询,并将结果按照年龄降序排列
命令:SELECT employee.name,employee.age,department.dname FROM department JOIN employee ON department.did=employee.did ORDER BY age DESC;
结果:
5、子查询
子查询是指一个查询语句嵌套在另一个查询语句内部的查询。在执行时,首先执行子查询中的语句,然后将返回的结果作为外层查询的过滤条件。
5.1 带 IN 关键字的子查询
举例1:查询年龄为20岁的员工的部门
命令:SELECT * FROM department WHERE id IN (SELECT did FROM employee WHERE age=20);
结果:
举例2:查询不存在年龄为20岁的员工的部门
命令:SELECT * FROM department WHERE did NOT IN (SELECT did WHERE age=20);
结果:
5.2 带 EXISTS 关键字的子查询
EXISTS 关键字后面的参数可以是任意一个子查询,这个子查询不产生任何数据,只返回 TRUE 或 FALSE,当返回 TRUE 时,外层查询才会执行。
举例:查询employee表中是否存在年龄大于21岁的员工,若存在则查询department表中所有记录。
命令:SELECT * FROM department WHERE EXISTS (SELECT did FROM employee WHERE age >21 );
结果:
5.3 带 ANY 关键字的子查询
ANY 关键字表示只要满足内层子查询中的任意一个条件,就返回一个结果作为外层查询条件。
举例:使用带ANY 关键字的查询,查询满足条件的部门。
命令:SELECT * FROM department WHERE did >ANY (SELECT did FROM employee);
结果:
在此命令中,子查询会先将employee表中所有did查询出来,分别是1,1,2,4,然后将 department 中的 did 的值与之比较,只要大于employee.did中的任意一个值,就是符合查询条件的结果。由于employee.did的最小值为1,所以department中只要大于1的did都满足条件,即2,3,5。
5.4 带 ALL 关键字的子查询
ALL关键字类似于ANY ,只是ALL关键字的子查询返回的结果需要同时满足所有内查询条件。
举例:使用带 ALL 关键字的子查询,查询满足条件的部门。
命令:SELECT * FROM department WHERE did > ALL (SELECT did FROM employee);
结果:
在此命令中,子查询会先将employee表中所有did查询出来,分别是1,1,2,4,然后将 department 中的 did 的值与之比较,只有大于employee.did中的所有值,才是符合查询条件的结果。由于employee.did的最大值为4,所以department中只有大于4的did才满足条件,即5。
5.5 带 比较运算符的子查询
举例:使用带比较运算符的子查询,查询赵四属于哪个部门
命令:SELECT did,name FROM department WHERE did = (SELECT did FROM employee WHERE name='赵四');
结果:
MySQL之多表操作的更多相关文章
- mysql 库与表操作
1. 库操作 1.1. 创建数据库 语法规则:create database 库名; CREATE DATABASE dt55; 在创建库时,希望指定编码语法:create database 库名 c ...
- 数据库之 MySQL --- 数据处理 之 表操作、CRUD(六)
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 一. 表操作 创建数据库CREATE DATABASE demo-- 删除数据库DROP DATABAS ...
- python爬取信息到数据库与mysql简单的表操作
python 爬取豆瓣top250并导入到mysql数据库中 import pymysql import requests import re url='https://movie.douban.co ...
- 学习MySQL之单表操作(二)
##单表操作 ##创建表 CREATE TABLE t_employee( empno ), ename ), job ), MGR ), Hiredate DATE DEFAULT '0000-00 ...
- Mysql之数据表操作
数据表操作: 查看当前数据库中所有的表: show tables; 查看当前使用数据库: select database(); 使用数据表: use 表名; 创建数据表: create table 数 ...
- Mysql之库表操作(胖胖老师)
SQL概念:结构化查询语言(SQL = Structured Query Language),也是一种编程语言(数据库查询和程序设计语言),可以用于数据的存取及查询,更新,管理关系型数据库系统ps: ...
- MySQL删除超大表操作
======================================================================== 问题原因 通常情况下,会使用innodb_file_p ...
- 数据库-mysql数据库和表操作
一:数据库查询增加删除 1)mysql数据库查询:show databases MariaDB [mysql]> show databases; +--------------------+ | ...
- MySql数据库多表操作
一.连接查询[连表查询.多表查询] 当查询结果的列来源于多张表时,需要将多张表连接成一个大的数据集,再选择合适的列返回 mysql支持三种类型的连接查询,分别为: 内连接查询(inner join) ...
随机推荐
- java 静态方法分析
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt210 1.大家都以为"实例方法需要先创建实例才可以调用,比较麻烦, ...
- WPF--鼠标右键菜单中的Command命令实现
一个功能,在ListView中的ListBoxItem控件上实现右键菜单关闭选项,将该ListBoxItem从ListView中删除. 利用 RoutedCommand类创建Command命令,MSD ...
- jdk源码研究1-HashMap
今天开始,研读下jdk的常用类的一些源码,下面是jdk中HashMap的研究.诚然,网上已经很多这方面的总结了,但是,个人只是想单纯地把自己的理解过程进行记录,大牛们就绕路吧,当然,欢迎扔砖头.下面是 ...
- 九度OJ 1016 火星A + B 未AC版,整型存储不下
#include <iostream> #include <string.h> #include <sstream> #include <math.h> ...
- 【Beta】 第七次Daily Scrum Meeting
第七次meeting会议 [Beta] 第七次Daily Scrum Meeting 一.本次会议为第七次meeting会议 二.时间:10:00AM-10:20AM 地点:禹州楼 三.会议站立式照片 ...
- 【Alpha】Daily Scrum Meeting——Day2
站立式会议照片 1.本次会议为第二次 Meeting会议: 2.本次会议在中午12:30,在陆大楼召开,本次会议为30分钟讨论昨天的任务完成情况以及接下来的任务安排. 每个人的工作分配 成 员 昨天已 ...
- 201521123121 《Java程序设计》第5周学习总结
1. 本周学习总结 1.1 尝试使用思维导图总结有关多态与接口的知识点. 2. 书面作业 代码阅读:Child压缩包内源代码 1.1 com.parent包中Child.java文件能否编译通过?哪句 ...
- 201521123057 《Java程序设计》第4周学习总结
1. 本周学习总结 1.1 尝试使用思维导图总结有关继承的知识点. 2. 书面作业 注释的应用 使用类的注释与方法的注释为前面编写的类与方法进行注释,并在Eclipse中查看.(截图) 答: 面向对象 ...
- 201521123077 《Java程序设计》第2周学习总结
1. 本周学习总结 动态数组 标识控制符的意义 ArrayList ,BigDecimal,BigInteger 等类的使用 组合,继承,多态等概念的了解 2. 书面作业 Q1.使用Eclipse关联 ...
- Java 第十一周总结
1. 本周学习总结 2. 书面作业 1.互斥访问与同步访问 完成题集4-4(互斥访问)与4-5(同步访问) 1.1 除了使用synchronized修饰方法实现互斥同步访问,还有什么办法实现互斥同步访 ...