- 多表查询
- 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脚本路径