• 多表查询
  • 1.表与表的关系
  • 2.合并结果集
  • 3.连接查询
  • 3.1 内连接
  • 3.2 外连接
  • 4.子查询
  • 数据库备份与恢复
  • 1.备份
  • 2.恢复


多表查询

1.表与表的关系

  • 一对一
  • 一对多(多对一)
  • 多对多(需要创建中间表)

2.合并结果集

作用:就是将两个select语句的查询结果合并到一起

两种方式:

- union:联合之后会去除重复的结果

- union all:获取所有的结果
演示:

mysql> create table X(
    -> name varchar(30),
    -> age int);
Query OK, 0 rows affected (0.02 sec)

mysql> create table Y(
    -> name varchar(30),
    -> age int);
Query OK, 0 rows affected (0.01 sec)

mysql> insert into X values('张三',18),('李四',16),('王五',20);
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> insert into Y values('张三',18),('李四',15),('赵六',20);
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select * from X union select * from Y;
+------+------+
| name | age  |
+------+------+
| 张三 |   18 |
| 李四 |   16 |
| 王五 |   20 |
| 李四 |   15 |
| 赵六 |   20 |
+------+------+
5 rows in set (0.00 sec)

mysql> select * from X union all select * from Y;
+------+------+
| name | age  |
+------+------+
| 张三 |   18 |
| 李四 |   16 |
| 王五 |   20 |
| 张三 |   18 |
| 李四 |   15 |
| 赵六 |   20 |
+------+------+
6 rows in set (0.00 sec)

注意:被合并的两个结果,列数、列类型必须相同

如果遇到列数不相同的情况,就要使它们的字段在查询的时候相同,如:

mysql> create table Z(
    -> name varchar(30),
    -> age int,
    -> sex varchar(10));
Query OK, 0 rows affected (0.01 sec)

mysql> insert into Z values('小花',18,'女'),('小明',15,'男'),('小红',20,'女');
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select * from X union all select * from Z;
ERROR 1222 (21000): The used SELECT statements have a different number of columns
mysql> select * from X union all select name,age from Z;
+------+------+
| name | age  |
+------+------+
| 张三 |   18 |
| 李四 |   16 |
| 王五 |   20 |
| 小花 |   18 |
| 小明 |   15 |
| 小红 |   20 |
+------+------+
6 rows in set (0.00 sec)

3.连接查询

作用:求出多个表的乘积,例如x1和x2,如果采用了连接查询,得到的结果是x1*x2,是一个笛卡尔积
笛卡尔积:两个集合相乘的结果,假设集合A={a,b},集合B={0,1,2},则笛卡尔积的结果{(a,0),(a,1),(a,2),(b,0),(b,1),(b,2)}
演示:

mysql> select * from X,Y;
+------+------+------+------+
| name | age  | name | age  |
+------+------+------+------+
| 张三 |   18 | 张三 |   18 |
| 李四 |   16 | 张三 |   18 |
| 王五 |   20 | 张三 |   18 |
| 张三 |   18 | 李四 |   15 |
| 李四 |   16 | 李四 |   15 |
| 王五 |   20 | 李四 |   15 |
| 张三 |   18 | 赵六 |   20 |
| 李四 |   16 | 赵六 |   20 |
| 王五 |   20 | 赵六 |   20 |
+------+------+------+------+
9 rows in set (0.00 sec)

3.1 内连接

table1 inner join table2 on
inner可以省略

-- 创建表
-- 学生表
create table student(
	stuid varchar(10) primary key,
	stuname varchar(50)
);

-- 成绩表
create table score(
	stuid varchar(10),
	score int,
	courseid int
);
   
#插入数据
insert into student values('1001','zhangsan');
insert into student values('1002','xiaoming');
insert into student values('1003','jack');
insert into student values('1004','tom');

insert into score values('1001',98,1);
insert into score values('1002',95,1);
insert into score values('1003',67,2);
insert into score values('1004',83,2);
insert into score values('1004',70,1);

1 查询所有学生的学号、名字、分数还有课程名

mysql> select s.stuid,s.stuname,c.score,c.courseid  from student s join score c on s.stuid=c.stuid;
+-------+----------+-------+----------+
| stuid | stuname  | score | courseid |
+-------+----------+-------+----------+
| 1001  | zhangsan |    98 |        1 |
| 1002  | xiaoming |    95 |        1 |
| 1003  | jack     |    67 |        2 |
| 1004  | tom      |    83 |        2 |
| 1004  | tom      |    70 |        1 |
+-------+----------+-------+----------+
5 rows in set (0.00 sec)

上面的语句可等价于如下语句:

mysql> select s.stuid,s.stuname,c.score,c.courseid from student s,score c where s.stuid=c.stuid;
+-------+----------+-------+----------+
| stuid | stuname  | score | courseid |
+-------+----------+-------+----------+
| 1001  | zhangsan |    98 |        1 |
| 1002  | xiaoming |    95 |        1 |
| 1003  | jack     |    67 |        2 |
| 1004  | tom      |    83 |        2 |
| 1004  | tom      |    70 |        1 |
+-------+----------+-------+----------+
5 rows in set (0.00 sec)

3.2 外连接

分为左外连接和右外连接

  • 左外连接: table1 left join table2 on
  • 右外连接:table1 right join table2 on

左外连接是以table1作参照连接table2,右外连接则相反
这里我们插入一个score表没有的stuid,这样更好理解
再插入一个student表没有的stuid
左外连接:

mysql> insert into student values('1005','xiaohua');
Query OK, 1 row affected (0.01 sec)

mysql> insert into score values('1006',70,1);
Query OK, 1 row affected (0.00 sec)

mysql>  select s.stuid,s.stuname,c.score,c.courseid  from student s left join score c on s.stuid=c.stuid;
+-------+----------+-------+----------+
| stuid | stuname  | score | courseid |
+-------+----------+-------+----------+
| 1001  | zhangsan |    98 |        1 |
| 1002  | xiaoming |    95 |        1 |
| 1003  | jack     |    67 |        2 |
| 1004  | tom      |    83 |        2 |
| 1004  | tom      |    70 |        1 |
| 1005  | xiaohua  |  NULL |     NULL |
+-------+----------+-------+----------+
6 rows in set (0.00 sec)

右外连接:

mysql> select s.stuid,s.stuname,c.score,c.courseid  from student s right join score c on s.stuid=c.stuid;
+-------+----------+-------+----------+
| stuid | stuname  | score | courseid |
+-------+----------+-------+----------+
| 1001  | zhangsan |    98 |        1 |
| 1002  | xiaoming |    95 |        1 |
| 1003  | jack     |    67 |        2 |
| 1004  | tom      |    83 |        2 |
| 1004  | tom      |    70 |        1 |
| NULL  | NULL     |    70 |        1 |
+-------+----------+-------+----------+
6 rows in set (0.00 sec)

4.子查询

无非就是select语句里嵌套select语句
注意:
a.子查询出现的位置:

  • from后
  • where子句的后面,作为条件的一部分被查询

b.当子查询出现在where后面作为条件时,可以使用关键字:any、all

c.子查询结果集的形式

  • 单行单列
  • 单行多列
  • 多行多列
  • 多行单列

演示:

# 员工表
create table emp(empno int primary key, enname varchar(20), 
	job varchar(20), 
	mgr int, 
	hiredate date, 
	sal double, 
	comm double, 
	deptno int
);

# 添加数据
insert into emp values(7369,'smith','clark',7902,'1980-12-17',800,null,20);
insert into emp values(7499,'allen','salesman',7698,'1981-02-20',1600,300,30);
insert into emp values(7521,'ward','salesman',7698,'1981-02-22',1250,500,30);
insert into emp values(7566,'jones','managen',7839,'1981-04-02',2975,null,30);
insert into emp values(7654,'martin','salesman',7698,'1981-09-28',1250,1400,30);
insert into emp values(7698,'blake','manager',7839,'1981-05-01',2850,null,30);
insert into emp values(7782,'clark','manageer',7839,'1980-06-17',2450,null,10);
insert into emp values(7788,'scott','analyst',7566,'1987-02-20',3000,null,20);
insert into emp values(7839,'king','president',null,'1987-02-20',5000,null,10);

1 查询所和smith同部门的员工的信息

mysql> select * from emp where deptno=(select deptno from emp where enname='smith') and enname!='smith';
+-------+--------+---------+------+------------+------+------+--------+
| empno | enname | job     | mgr  | hiredate   | sal  | comm | deptno |
+-------+--------+---------+------+------------+------+------+--------+
|  7788 | scott  | analyst | 7566 | 1987-02-20 | 3000 | NULL |     20 |
+-------+--------+---------+------+------------+------+------+--------+
1 row in set (0.00 sec)

2 查询工资高于blake的所有员工信息

mysql> select * from emp where sal>(select sal from emp where enname='blake');
+-------+--------+-----------+------+------------+------+------+--------+
| empno | enname | job       | mgr  | hiredate   | sal  | comm | deptno |
+-------+--------+-----------+------+------------+------+------+--------+
|  7566 | jones  | managen   | 7839 | 1981-04-02 | 2975 | NULL |     30 |
|  7788 | scott  | analyst   | 7566 | 1987-02-20 | 3000 | NULL |     20 |
|  7839 | king   | president | NULL | 1987-02-20 | 5000 | NULL |     10 |
+-------+--------+-----------+------+------------+------+------+--------+
3 rows in set (0.00 sec)

3 查询工资高于30号部门所有人的员工信息

mysql> select * from emp where sal>(select max(sal) from emp where deptno=30);
+-------+--------+-----------+------+------------+------+------+--------+
| empno | enname | job       | mgr  | hiredate   | sal  | comm | deptno |
+-------+--------+-----------+------+------------+------+------+--------+
|  7788 | scott  | analyst   | 7566 | 1987-02-20 | 3000 | NULL |     20 |
|  7839 | king   | president | NULL | 1987-02-20 | 5000 | NULL |     10 |
+-------+--------+-----------+------+------------+------+------+--------+
2 rows in set (0.00 sec)

4 查询工作类型和工资与martin完全相同的员工信息

mysql> select * from emp where (job,sal) in(select job,sal from emp where enname='martin');
+-------+--------+----------+------+------------+------+------+--------+
| empno | enname | job      | mgr  | hiredate   | sal  | comm | deptno |
+-------+--------+----------+------+------------+------+------+--------+
|  7521 | ward   | salesman | 7698 | 1981-02-22 | 1250 |  500 |     30 |
|  7654 | martin | salesman | 7698 | 1981-09-28 | 1250 | 1400 |     30 |
+-------+--------+----------+------+------------+------+------+--------+
2 rows in set (0.00 sec)

数据库备份与恢复

1.备份

生成SQL脚本,导出数据,命令:mysqldump -u root -p 数据库名>生成sql脚本的路径
注意:

  • 可以不需要登录数据库
  • windows系统: 使用管理员权限打开cmd
  • mydb.sql不需要先创建(名字可以随便取)
mysqldump -u root -p 需要备份的数据库名 > 保存路径/mydb.sql
Enter password:

2.恢复

执行sql脚本,恢复数据
前提:必须先创建数据库【空的】
注意:需要先登录数据库,然后进入指定的数据库,执行sql脚本

mysql> source 生成的那个sql脚本路径