前言:之前已经针对数据库的单表查询进行了详细的介绍: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之多表操作的更多相关文章

  1. mysql 库与表操作

    1. 库操作 1.1. 创建数据库 语法规则:create database 库名; CREATE DATABASE dt55; 在创建库时,希望指定编码语法:create database 库名 c ...

  2. 数据库之 MySQL --- 数据处理 之 表操作、CRUD(六)

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 一. 表操作 创建数据库CREATE DATABASE demo-- 删除数据库DROP DATABAS ...

  3. python爬取信息到数据库与mysql简单的表操作

    python 爬取豆瓣top250并导入到mysql数据库中 import pymysql import requests import re url='https://movie.douban.co ...

  4. 学习MySQL之单表操作(二)

    ##单表操作 ##创建表 CREATE TABLE t_employee( empno ), ename ), job ), MGR ), Hiredate DATE DEFAULT '0000-00 ...

  5. Mysql之数据表操作

    数据表操作: 查看当前数据库中所有的表: show tables; 查看当前使用数据库: select database(); 使用数据表: use 表名; 创建数据表: create table 数 ...

  6. Mysql之库表操作(胖胖老师)

    SQL概念:结构化查询语言(SQL = Structured Query Language),也是一种编程语言(数据库查询和程序设计语言),可以用于数据的存取及查询,更新,管理关系型数据库系统ps: ...

  7. MySQL删除超大表操作

    ======================================================================== 问题原因 通常情况下,会使用innodb_file_p ...

  8. 数据库-mysql数据库和表操作

    一:数据库查询增加删除 1)mysql数据库查询:show databases MariaDB [mysql]> show databases; +--------------------+ | ...

  9. MySql数据库多表操作

    一.连接查询[连表查询.多表查询] 当查询结果的列来源于多张表时,需要将多张表连接成一个大的数据集,再选择合适的列返回 mysql支持三种类型的连接查询,分别为: 内连接查询(inner join) ...

随机推荐

  1. C++中值传递、指针传递、引用传递的总结

    C++中值传递.指针传递.引用传递的总结   指针传递和引用传递一般适用于:函数内部修改参数并且希望改动影响调用者.对比值传递,指针/引用传递可以将改变由形参"传给"实参(实际上就 ...

  2. json对象和json字符串之间的转化

    json对象和json字符串之间的转化 json字符串----->json对象 使用JSON.parse()函数 var jsonStr = '{"name":"z ...

  3. 实现CA证书创建及客户端申请证书

    author:JevonWei 版权声明:原创作品 CA证书的相关文件路径 openssl配置文件/etc/pki/tls/openssl.cnf /etc/pki/tls/openssl.cnf C ...

  4. 第1阶段——uboot分析之通过nand命令读内核(8)

    本节主要学习: 详细分析UBOOT中"bootcmd=nand read.jffs2 0x30007FC0 kernel;bootm 0x30007FC0" 怎么实现nand命令读 ...

  5. Spring集成RabbitMQ-连接和消息模板

    ConnectionFactory ConnectionFactory是RabbitMQ服务掌握连接Connection生杀大权的重要组件 有了它,就可以创建Connection(org.spring ...

  6. 前端js优化方案(连续更新)

    最近在读<高性能javascript>,在这里记录一下读后的一些感受,顺便加上自己的一些理解,如果有兴趣的话可以关注的我的博客http://www.bloggeng.com/,我会不定期发 ...

  7. my new day in CNblog

    感谢大家 今天正式在博客园平台开启我的第三个技术面博客 之前一直坚持在csdn平台撰文(http://blog.csdn.net/github_38885296)欢迎参观:) 因为觉得博客园知名度虽不 ...

  8. 1~N任意三个数最大的最小公倍数(Java版)

    最大最小公倍数 如题 话不多说,直接上代码 public class MaxCommonMultiple{ public static void main(String[] args) { Scann ...

  9. 个人作业1——四则运算题目生成程序(基于C++)

    题目描述: 从<构建之法>第一章的 "程序" 例子出发,像阿超那样,花二十分钟写一个能自动生成小学四则运算题目的命令行 "软件",满足以下需求: 1 ...

  10. 201521123019 《Java程序设计》第5周学习总结

    1. 本章学习总结 2. 书面作业 一.代码阅读:Child压缩包内源代码 1.1 com.parent包中Child.java文件能否编译通过?哪句会出现错误?试改正该错误.并分析输出结果. Ans ...