当前位置: 首页 > news >正文

MySQL 核心操作:多表联合查询与数据库备份恢复

MySQL 核心操作:多表联合查询与数据库备份恢复

一、多表联合查询

在关系型数据库中,表与表通过主键 - 外键关联,多表联合查询可同时从 2 个及以上表中提取关联数据。MySQL 中多表查询主要分为交叉连接、内连接、外连接、分组查询、子查询5 类,以下详细说明

1. 交叉连接(CROSS JOIN):笛卡尔积查询

交叉连接是最基础的多表连接,本质是返回两张表的笛卡尔积(即表 1 的每一行与表 2 的每一行组合,结果行数 = 表 1 行数 × 表 2 行数),实际应用中需配合WHERE筛选有效数据,否则结果无意义

核心特性
  • 两种语法:显式(CROSS JOIN)和隐式(逗号分隔表),官方推荐显式语法
  • WHERE时返回全量笛卡尔积,数据量极大(如 1000 行 ×1000 行 = 100 万行),需避免
语法格式
-- 显式语法(推荐)
SELECT <字段名> FROM <1> CROSS JOIN <2> [WHERE 筛选条件];-- 隐式语法(不推荐)
SELECT <字段名> FROM <1>, <2> [WHERE 筛选条件];
实例演示

student(学生表,10 行)和course(课程表,5 行)为例:

全量笛卡尔积(无筛选):返回 10×5=50 行数据

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| shenyi             |
| sy                 |
| sys                |
+--------------------+
6 rows in set (0.01 sec)mysql> use shenyi;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -ADatabase changedmysql> show tables;
+------------------+
| Tables_in_shenyi |
+------------------+
| course           |
| student          |
| student123       |
+------------------+
3 rows in set (0.00 sec)
mysql> select * from student;
+----+-------------+------+
| id | name        | age  |
+----+-------------+------+
|  1 | tom         |   20 |
|  2 | jerry       |   23 |
|  3 | shenyi      |   25 |
|  4 | sean        |   28 |
|  5 | zhangshan   |   26 |
|  7 | lisi        |   50 |
|  8 | chenshuo    |   10 |
|  9 | wangwu      |  100 |
| 10 | qiuyi       |   15 |
| 11 | qiuxiaotian |   20 |
+----+-------------+------+
10 rows in set (0.00 sec)mysql> select* from course;
+----+-------------+
| id | course_name |
+----+-------------+
|  1 | Java        |
|  2 | MySQL       |
|  3 | Python      |
|  4 | Go          |
|  5 | C++         |
+----+-------------+
5 rows in set (0.00 sec)
mysql> select * from course join student123;
+----+-------------+----+--------+------+-------+--------+-----------+
| id | course_name | id | name   | age  | sex   | height | course_id |
+----+-------------+----+--------+------+-------+--------+-----------+
|  1 | Java        |  1 | Dany   |   25 | man   |    160 |         1 |
|  2 | MySQL       |  1 | Dany   |   25 | man   |    160 |         1 |
|  3 | Python      |  1 | Dany   |   25 | man   |    160 |         1 |
|  4 | Go          |  1 | Dany   |   25 | man   |    160 |         1 |
|  5 | C++         |  1 | Dany   |   25 | man   |    160 |         1 |
|  1 | Java        |  2 | Green  |   23 | man   |    158 |         2 |
|  2 | MySQL       |  2 | Green  |   23 | man   |    158 |         2 |
|  3 | Python      |  2 | Green  |   23 | man   |    158 |         2 |
|  4 | Go          |  2 | Green  |   23 | man   |    158 |         2 |
|  5 | C++         |  2 | Green  |   23 | man   |    158 |         2 |
|  1 | Java        |  3 | Henry  |   23 | woman |    185 |         1 |
|  2 | MySQL       |  3 | Henry  |   23 | woman |    185 |         1 |
|  3 | Python      |  3 | Henry  |   23 | woman |    185 |         1 |
|  4 | Go          |  3 | Henry  |   23 | woman |    185 |         1 |
|  5 | C++         |  3 | Henry  |   23 | woman |    185 |         1 |
|  1 | Java        |  4 | Jane   |   22 | man   |    162 |         3 |
|  2 | MySQL       |  4 | Jane   |   22 | man   |    162 |         3 |
|  3 | Python      |  4 | Jane   |   22 | man   |    162 |         3 |
|  4 | Go          |  4 | Jane   |   22 | man   |    162 |         3 |
|  5 | C++         |  4 | Jane   |   22 | man   |    162 |         3 |
|  1 | Java        |  5 | Jim    |   24 | woman |    175 |         2 |
|  2 | MySQL       |  5 | Jim    |   24 | woman |    175 |         2 |
|  3 | Python      |  5 | Jim    |   24 | woman |    175 |         2 |
|  4 | Go          |  5 | Jim    |   24 | woman |    175 |         2 |
|  5 | C++         |  5 | Jim    |   24 | woman |    175 |         2 |
|  1 | Java        |  6 | John   |   21 | woman |    172 |         4 |
|  2 | MySQL       |  6 | John   |   21 | woman |    172 |         4 |
|  3 | Python      |  6 | John   |   21 | woman |    172 |         4 |
|  4 | Go          |  6 | John   |   21 | woman |    172 |         4 |
|  5 | C++         |  6 | John   |   21 | woman |    172 |         4 |
|  1 | Java        |  7 | Lily   |   22 | man   |    165 |         4 |
|  2 | MySQL       |  7 | Lily   |   22 | man   |    165 |         4 |
|  3 | Python      |  7 | Lily   |   22 | man   |    165 |         4 |
|  4 | Go          |  7 | Lily   |   22 | man   |    165 |         4 |
|  5 | C++         |  7 | Lily   |   22 | man   |    165 |         4 |
|  1 | Java        |  8 | Susan  |   23 | man   |    170 |         5 |
|  2 | MySQL       |  8 | Susan  |   23 | man   |    170 |         5 |
|  3 | Python      |  8 | Susan  |   23 | man   |    170 |         5 |
|  4 | Go          |  8 | Susan  |   23 | man   |    170 |         5 |
|  5 | C++         |  8 | Susan  |   23 | man   |    170 |         5 |
|  1 | Java        |  9 | Thomas |   22 | woman |    178 |         5 |
|  2 | MySQL       |  9 | Thomas |   22 | woman |    178 |         5 |
|  3 | Python      |  9 | Thomas |   22 | woman |    178 |         5 |
|  4 | Go          |  9 | Thomas |   22 | woman |    178 |         5 |
|  5 | C++         |  9 | Thomas |   22 | woman |    178 |         5 |
|  1 | Java        | 10 | Tom    |   23 | woman |    165 |         5 |
|  2 | MySQL       | 10 | Tom    |   23 | woman |    165 |         5 |
|  3 | Python      | 10 | Tom    |   23 | woman |    165 |         5 |
|  4 | Go          | 10 | Tom    |   23 | woman |    165 |         5 |
|  5 | C++         | 10 | Tom    |   23 | woman |    165 |         5 |
+----+-------------+----+--------+------+-------+--------+-----------+
50 rows in set (0.00 sec)

结果示例:每个学生与所有课程组合,如Dany对应Java、MySQL、Python、Go、C++5 条记录

筛选有效数据(按外键关联):通过course_id(学生表外键)与id(课程表主键)匹配,返回学生与对应课程的关联数据(10 行,与学生数一致)

mysql> select* from course;
+----+-------------+
| id | course_name |
+----+-------------+
|  1 | Java        |
|  2 | MySQL       |
|  3 | Python      |
|  4 | Go          |
|  5 | C++         |
+----+-------------+
5 rows in set (0.00 sec)mysql> select * from student123;
+----+--------+------+-------+--------+-----------+
| id | name   | age  | sex   | height | course_id |
+----+--------+------+-------+--------+-----------+
|  1 | Dany   |   25 | man   |    160 |         1 |
|  2 | Green  |   23 | man   |    158 |         2 |
|  3 | Henry  |   23 | woman |    185 |         1 |
|  4 | Jane   |   22 | man   |    162 |         3 |
|  5 | Jim    |   24 | woman |    175 |         2 |
|  6 | John   |   21 | woman |    172 |         4 |
|  7 | Lily   |   22 | man   |    165 |         4 |
|  8 | Susan  |   23 | man   |    170 |         5 |
|  9 | Thomas |   22 | woman |    178 |         5 |
| 10 | Tom    |   23 | woman |    165 |         5 |
+----+--------+------+-------+--------+-----------+
10 rows in set (0.00 sec)
mysql> select * from student123 cross join course where course.id=student123.course_id;
+----+--------+------+-------+--------+-----------+----+-------------+
| id | name   | age  | sex   | height | course_id | id | course_name |
+----+--------+------+-------+--------+-----------+----+-------------+
|  1 | Dany   |   25 | man   |    160 |         1 |  1 | Java        |
|  2 | Green  |   23 | man   |    158 |         2 |  2 | MySQL       |
|  3 | Henry  |   23 | woman |    185 |         1 |  1 | Java        |
|  4 | Jane   |   22 | man   |    162 |         3 |  3 | Python      |
|  5 | Jim    |   24 | woman |    175 |         2 |  2 | MySQL       |
|  6 | John   |   21 | woman |    172 |         4 |  4 | Go          |
|  7 | Lily   |   22 | man   |    165 |         4 |  4 | Go          |
|  8 | Susan  |   23 | man   |    170 |         5 |  5 | C++         |
|  9 | Thomas |   22 | woman |    178 |         5 |  5 | C++         |
| 10 | Tom    |   23 | woman |    165 |         5 |  5 | C++         |
+----+--------+------+-------+--------+-----------+----+-------------+
10 rows in set (0.00 sec)

2. 内连接(INNER JOIN):匹配有效关联数据

内连接是实际开发中最常用的连接方式,只返回两张表中满足连接条件的记录,自动过滤无关联的无效数据(避免笛卡尔积冗余)

核心特性
  • 可省略INNER,仅用JOIN
  • 必须通过ON子句指定连接条件(比WHERE更规范,性能更优)
语法格式
SELECT <字段名> FROM <1> [INNER] JOIN <2> ON <连接条件>;
实例演示

查询学生姓名与对应课程名称(通过course_id = id关联):

mysql> select s.id,s.name,c.course_name from student123 s join course c on
s.course_id=c.id;
+----+--------+-------------+
| id | name   | course_name |
+----+--------+-------------+
|  1 | Dany   | Java        |
|  3 | Henry  | Java        |
|  2 | Green  | MySQL       |
|  5 | Jim    | MySQL       |
|  4 | Jane   | Python      |
|  6 | John   | Go          |
|  7 | Lily   | Go          |
|  8 | Susan  | C++         |
|  9 | Thomas | C++         |
| 10 | Tom    | C++         |
+----+--------+-------------+
10 rows in set (0.00 sec)

3. 外连接:保留基表所有数据(左 / 右连接)

内连接仅返回匹配数据,外连接则保留 “基表” 的所有记录,参考表中无匹配时字段值为NULL。分为左外连接和右外连接,核心是 “基表” 的选择

3.1 左外连接(LEFT JOIN):保留左表所有数据
  • 基表:LEFT JOIN左侧的表(表 1)
  • 结果:表 1 的所有记录 + 表 2 中匹配的记录;表 2 无匹配时,表 2 字段为NULL
语法格式
SELECT <字段名> FROM <1> LEFT [OUTER] JOIN <2> ON <连接条件>;
实例演示

查询所有学生(包括无课程的学生)及其课程,学生表student123新增lqcourse_id=NULL,课程表无id=6的课程):

mysql> select * from student123;
+----+--------+------+-------+--------+-----------+
| id | name   | age  | sex   | height | course_id |
+----+--------+------+-------+--------+-----------+
|  1 | Dany   |   25 | man   |    160 |         1 |
|  2 | Green  |   23 | man   |    158 |         2 |
|  3 | Henry  |   23 | woman |    185 |         1 |
|  4 | Jane   |   22 | man   |    162 |         3 |
|  5 | Jim    |   24 | woman |    175 |         2 |
|  6 | John   |   21 | woman |    172 |         4 |
|  7 | Lily   |   22 | man   |    165 |         4 |
|  8 | Susan  |   23 | man   |    170 |         5 |
|  9 | Thomas |   22 | woman |    178 |         5 |
| 10 | Tom    |   23 | woman |    165 |         5 |
+----+--------+------+-------+--------+-----------+
10 rows in set (0.01 sec)mysql> insert into student123(id,name,age,sex,height) values(11,'lq',25,'man',175);
Query OK, 1 row affected (0.00 sec)mysql> select * from student123;
+----+--------+------+-------+--------+-----------+
| id | name   | age  | sex   | height | course_id |
+----+--------+------+-------+--------+-----------+
|  1 | Dany   |   25 | man   |    160 |         1 |
|  2 | Green  |   23 | man   |    158 |         2 |
|  3 | Henry  |   23 | woman |    185 |         1 |
|  4 | Jane   |   22 | man   |    162 |         3 |
|  5 | Jim    |   24 | woman |    175 |         2 |
|  6 | John   |   21 | woman |    172 |         4 |
|  7 | Lily   |   22 | man   |    165 |         4 |
|  8 | Susan  |   23 | man   |    170 |         5 |
|  9 | Thomas |   22 | woman |    178 |         5 |
| 10 | Tom    |   23 | woman |    165 |         5 |
| 11 | lq     |   25 | man   |    175 |      NULL |
+----+--------+------+-------+--------+-----------+
11 rows in set (0.00 sec)
mysql> select s.id,s.name,c.course_name from student123 s join course c on
s.course_id=c.id;
+----+--------+-------------+
| id | name   | course_name |
+----+--------+-------------+
|  1 | Dany   | Java        |
|  3 | Henry  | Java        |
|  2 | Green  | MySQL       |
|  5 | Jim    | MySQL       |
|  4 | Jane   | Python      |
|  6 | John   | Go          |
|  7 | Lily   | Go          |
|  8 | Susan  | C++         |
|  9 | Thomas | C++         |
| 10 | Tom    | C++         |
+----+--------+-------------+
10 rows in set (0.00 sec)
mysql> select s.id,s.name,c.course_name from student123 s left join course
c on s.course_id=c.id;
+----+--------+-------------+
| id | name   | course_name |
+----+--------+-------------+
|  1 | Dany   | Java        |
|  3 | Henry  | Java        |
|  2 | Green  | MySQL       |
|  5 | Jim    | MySQL       |
|  4 | Jane   | Python      |
|  6 | John   | Go          |
|  7 | Lily   | Go          |
|  8 | Susan  | C++         |
|  9 | Thomas | C++         |
| 10 | Tom    | C++         |
| 11 | lq     | NULL        |
+----+--------+-------------+
11 rows in set (0.00 sec)

结果示例:lqcourse_nameNULL,其余学生显示对应课程。

3.2 右外连接(RIGHT JOIN):保留右表所有数据
  • 基表:RIGHT JOIN右侧的表(表 2)
  • 结果:表 2 的所有记录 + 表 1 中匹配的记录;表 1 无匹配时,表 1 字段为NULL
语法格式
SELECT <字段名> FROM <1> RIGHT [OUTER] JOIN <2> ON <连接条件>;
实例演示

查询所有课程(包括无学生的课程)及其学生,课程表course新增HTMLid=6,学生表无course_id=6的学生):

mysql> insert into course values(6,'HTML');
Query OK, 1 row affected (0.00 sec)mysql> select s.id,s.name,c.course_name from student123 s right join course c on s.course_id=c.id;
+------+--------+-------------+
| id   | name   | course_name |
+------+--------+-------------+
|    1 | Dany   | Java        |
|    2 | Green  | MySQL       |
|    3 | Henry  | Java        |
|    4 | Jane   | Python      |
|    5 | Jim    | MySQL       |
|    6 | John   | Go          |
|    7 | Lily   | Go          |
|    8 | Susan  | C++         |
|    9 | Thomas | C++         |
|   10 | Tom    | C++         |
| NULL | NULL   | HTML        |
+------+--------+-------------+
11 rows in set (0.00 sec)

结果示例:HTMLnameNULL,其余课程显示对应学生

4. 分组查询(GROUP BY):按字段聚合数据

GROUP BY可按 1 个或多个字段对查询结果分组,常与聚合函数COUNTSUMAVG等)或GROUP_CONCAT配合,实现数据统计

核心用法
用法说明
GROUP BY 字段单独分组,仅显示每组第一条记录(需配合聚合函数才有用)
GROUP_CONCAT(字段)显示每组内指定字段的所有值(用逗号分隔)
聚合函数 +GROUP BY统计每组数据(如COUNT(*)统计每组行数、AVG(age)计算每组平均年龄)
WITH ROLLUP在所有分组后追加一行 “总计”(聚合函数的总和)
实例演示

student123(学生表)为例:

统计人数:

mysql> select count(*) from student123;
+----------+
| count(*) |
+----------+
|       11 |
+----------+
1 row in set (0.00 sec)mysql> select count(name) from student123;
+-------------+
| count(name) |
+-------------+
|          11 |
+-------------+
1 row in set (0.00 sec)mysql> select count(course_id) from student123;
+------------------+
| count(course_id) |
+------------------+
|               10 |
+------------------+
1 row in set (0.00 sec)

按性别分组,统计每组人数

mysql> select sex,count(*) from student123 group by sex;
+-------+----------+
| sex   | count(*) |
+-------+----------+
| man   |        6 |
| woman |        5 |
+-------+----------+
2 rows in set (0.00 sec)

对student123表中age字段的平均值计算

mysql> select avg(age) from student123;
+----------+
| avg(age) |
+----------+
|  23.0000 |
+----------+
1 row in set (0.00 sec)

student123表中age字段的最大值和最小值查询

mysql> select max(age) from student123;
+----------+
| max(age) |
+----------+
|       25 |
+----------+
1 row in set (0.01 sec)mysql> select min(age) from student123;
+----------+
| min(age) |
+----------+
|       21 |
+----------+
1 row in set (0.00 sec)

按性别分组,显示每组学生姓名

mysql> select sex,group_concat(name) from student123 group by sex;
+-------+-------------------------------+
| sex   | group_concat(name)            |
+-------+-------------------------------+
| man   | Dany,Green,Jane,Lily,Susan,lq |
| woman | Henry,Jim,John,Thomas,Tom     |
+-------+-------------------------------+
2 rows in set (0.00 sec)

按年龄 + 性别分组,显示总计

mysql> select age,sex,count(*) from student123 group by age,sex;
+------+-------+----------+
| age  | sex   | count(*) |
+------+-------+----------+
|   21 | woman |        1 |
|   22 | man   |        2 |
|   22 | woman |        1 |
|   23 | man   |        2 |
|   23 | woman |        2 |
|   24 | woman |        1 |
|   25 | man   |        2 |
+------+-------+----------+
7 rows in set (0.00 sec)
mysql> select age,sex,count(*) from student123 group by sex,age;
+------+-------+----------+
| age  | sex   | count(*) |
+------+-------+----------+
|   22 | man   |        2 |
|   23 | man   |        2 |
|   25 | man   |        2 |
|   21 | woman |        1 |
|   22 | woman |        1 |
|   23 | woman |        2 |
|   24 | woman |        1 |
+------+-------+----------+
7 rows in set (0.00 sec)

分组聚合查询

mysql> select age,sex,group_concat(name) from student123 group by sex,age;
+------+-------+--------------------+
| age  | sex   | group_concat(name) |
+------+-------+--------------------+
|   22 | man   | Jane,Lily          |
|   23 | man   | Green,Susan        |
|   25 | man   | Dany,lq            |
|   21 | woman | John               |
|   22 | woman | Thomas             |
|   23 | woman | Henry,Tom          |
|   24 | woman | Jim                |
+------+-------+--------------------+
7 rows in set (0.01 sec)

分组聚合的基础上生成汇总行

mysql> select sex,group_concat(name) from student123 group by sex with rollup;
+-------+---------------------------------------------------------+
| sex   | group_concat(name)                                      |
+-------+---------------------------------------------------------+
| man   | Dany,Green,Jane,Lily,Susan,lq                           |
| woman | Henry,Jim,John,Thomas,Tom                               |
| NULL  | Dany,Green,Jane,Lily,Susan,lq,Henry,Jim,John,Thomas,Tom |
+-------+---------------------------------------------------------+
3 rows in set (0.00 sec)

5. 子查询:嵌套查询(内层结果作为外层条件)

子查询是 “查询中的查询”,将内层查询(子查询)的结果作为外层查询(父查询)的筛选条件,常用于复杂筛选。子查询需用括号包裹,支持多层嵌套

核心操作符
操作符说明
IN / NOT IN外层字段值在 / 不在子查询结果集中。
= / <>外层字段值等于 / 不等于子查询结果(子查询需返回单个值)。
EXISTS子查询结果集非空则返回TRUE(仅判断 “是否存在”,不关心具体值)。
实例演示

以 “查询学习 Python 课程的学生姓名” 为例:

mysql> select id,name,age,sex from student123 where course_id=((select id from course where course_name='Python');
+----+------+------+------+
| id | name | age  | sex  |
+----+------+------+------+
|  4 | Jane |   22 | man  |
+----+------+------+------+
1 row in set (0.01 sec)
mysql> select * from student123;
+----+--------+------+-------+--------+-----------+
| id | name   | age  | sex   | height | course_id |
+----+--------+------+-------+--------+-----------+
|  1 | Dany   |   25 | man   |    160 |         1 |
|  2 | Green  |   23 | man   |    158 |         2 |
|  3 | Henry  |   23 | woman |    185 |         1 |
|  4 | Jane   |   22 | man   |    162 |         3 |
|  5 | Jim    |   24 | woman |    175 |         2 |
|  6 | John   |   21 | woman |    172 |         4 |
|  7 | Lily   |   22 | man   |    165 |         4 |
|  8 | Susan  |   23 | man   |    170 |         5 |
|  9 | Thomas |   22 | woman |    178 |         5 |
| 10 | Tom    |   23 | woman |    165 |         5 |
| 11 | lq     |   25 | man   |    175 |      NULL |
+----+--------+------+-------+--------+-----------+
11 rows in set (0.00 sec)mysql> select * from course;
+----+-------------+
| id | course_name |
+----+-------------+
|  1 | Java        |
|  2 | MySQL       |
|  3 | Python      |
|  4 | Go          |
|  5 | C++         |
|  6 | HTML        |
+----+-------------+
6 rows in set (0.00 sec)

筛选出 “选修了不存在的课程” 的学生(即学生的course_id对应的值,在course表中没有匹配的课程记录)

mysql> select name from student123 where course_id not in(select id from course);
Empty set (0.00 sec)

使用<>运算符,在 course 表和 student123表中查询出没有学习 Python 课程的学生姓名,SQL 语句和运行结果如下:

mysql> select name from student123 where course_id <> (selectid from course where course_name = 'Python');
+--------+
| name   |
+--------+
| Dany   |
| Green  |
| Henry  |
| Jim    |
| John   |
| Lily   |
| Susan  |
| Thomas |
| Tom    |
+--------+
9 rows in set (0.00 sec)

查询 course 表中是否存在 id=1 的课程,如果存在,就查询出 student123 表中的记录,SQL 语句和运行结果如下:

mysql> select * from student123-> where exists(select course_name from course where id=1);
+----+--------+------+-------+--------+-----------+
| id | name   | age  | sex   | height | course_id |
+----+--------+------+-------+--------+-----------+
|  1 | Dany   |   25 | man   |    160 |         1 |
|  2 | Green  |   23 | man   |    158 |         2 |
|  3 | Henry  |   23 | woman |    185 |         1 |
|  4 | Jane   |   22 | man   |    162 |         3 |
|  5 | Jim    |   24 | woman |    175 |         2 |
|  6 | John   |   21 | woman |    172 |         4 |
|  7 | Lily   |   22 | man   |    165 |         4 |
|  8 | Susan  |   23 | man   |    170 |         5 |
|  9 | Thomas |   22 | woman |    178 |         5 |
| 10 | Tom    |   23 | woman |    165 |         5 |
| 11 | lq     |   25 | man   |    175 |      NULL |
+----+--------+------+-------+--------+-----------+
11 rows in set (0.00 sec)

course 表中存在 id=1 的记录,因此 EXISTS 表达式返回 TRUE,外层查询语句接收 TRUE 之后对表 student123 进行查询,返回所有的记录

mysql> select * from student123-> where age>24 and exists(select course_name from coursewhere id=1);
+----+------+------+------+--------+-----------+
| id | name | age  | sex  | height | course_id |
+----+------+------+------+--------+-----------+
|  1 | Dany |   25 | man  |    160 |         1 |
| 11 | lq   |   25 | man  |    175 |      NULL |
+----+------+------+------+--------+-----------+
2 rows in set (0.00 sec)

结果显示,从 tb_students_info 表中查询出了一条记录,这条记录的 age 字段取值为 25。内层查询语句从 course 表中查询到记录,返回 TRUE。外层查询语句开始进行查询。根据查询条件,从 student123 表中查询 age 大于 24 的记录
子查询的功能也可以通过表连接完成,但是子查询会使 SQL 语句更容易阅读和编写。
一般来说,表连接(内连接和外连接等)都可以用子查询替换,但反过来却不一定,有的子查询不能用表连接来替换。子查询比较灵活、方便、形式多样,适合作为查询的筛选条件,而表连接更适合于查看连接表的数据

二、MySQL 数据库备份与恢复

数据库备份是保障数据安全的核心手段,MySQL 常用备份方案包括全量备份、增量备份、差异备份,配合mysqldump工具和二进制日志实现完整的数据恢复

1. 常用备份方案对比

备份类型核心特点恢复效率备份时间适用场景
全量备份备份某一时间点的所有数据(如整个数据库、所有表)快(仅需全量文件)数据量小、需快速恢复场景
增量备份仅备份上一次备份后新增 / 修改的数据(依赖二进制日志)慢(需全量 + 所有增量)数据量大、高频更新场景
差异备份仅备份上一次全量备份后新增 / 修改的数据(依赖二进制日志)中(需全量 + 最后一次差异)数据量较大、更新频率中等

2. 备份工具:mysqldump(全量备份核心工具)

mysqldump是 MySQL 官方提供的命令行工具,支持备份单个数据库、多个数据库、指定表,备份文件为 SQL 脚本(文本格式,可直接执行恢复)

备份整个数据库(全备):

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| shenyi             |
| sy                 |
| sys                |
+--------------------+
6 rows in set (0.00 sec)mysql> use shenyi;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -ADatabase changed
mysql> show tables;
+------------------+
| Tables_in_shenyi |
+------------------+
| course           |
| student          |
| student123       |
+------------------+
3 rows in set (0.00 sec)
[root@syf ~]# ls
anaconda-ks.cfg
[root@syf ~]# mysqldump -uroot -p --all-databases > all-202509171919.sql
Enter password: 
[root@syf ~]# ls
all-202509171919.sql
anaconda-ks.cfg
mysql> show tables;
+------------------+
| Tables_in_shenyi |
+------------------+
| course           |
| student          |
| student123       |
+------------------+
3 rows in set (0.00 sec)mysql> drop table student;
Query OK, 0 rows affected (0.01 sec)
[root@syf ~]# mysql -uroot -predhat
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 5
Server version: 5.7.37 MySQL Community Server (GPL)Copyright (c) 2000, 2022, Oracle and/or its affiliates.Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql> select * from shenyi.student;
ERROR 1146 (42S02): Table 'shenyi.student' doesn't exist
mysql> source /root/all-202509171919.sql;
....
mysql> use shenyi;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -ADatabase changed
mysql> show tables;
+------------------+
| Tables_in_shenyi |
+------------------+
| course           |
| student          |
| student123       |
+------------------+
3 rows in set (0.00 sec)mysql> select * from student;
+----+-------------+------+
| id | name        | age  |
+----+-------------+------+
|  1 | tom         |   20 |
|  2 | jerry       |   23 |
|  3 | shenyi      |   25 |
|  4 | sean        |   28 |
|  5 | zhangshan   |   26 |
|  7 | lisi        |   50 |
|  8 | chenshuo    |   10 |
|  9 | wangwu      |  100 |
| 10 | qiuyi       |   15 |
| 11 | qiuxiaotian |   20 |
+----+-------------+------+
10 rows in set (0.00 sec)

备份shenyi库的student123表和student表

[root@syf ~]# mysqldump -uroot -p shenyi student123 student > table-20250917.sql
Enter password: 
[root@syf ~]# ls
table-20250917.sql
mysql> drop table student;
Query OK, 0 rows affected (0.01 sec)mysql> drop table student123;
Query OK, 0 rows affected (0.00 sec)mysql> show tables;
+------------------+
| Tables_in_shenyi |
+------------------+
| course           |
+------------------+
1 row in set (0.00 sec)mysql> source /root/table-20250917.sql
.....
mysql> show tables;
+------------------+
| Tables_in_shenyi |
+------------------+
| course           |
| student          |
| student123       |
+------------------+
3 rows in set (0.00 sec)mysql> select * from student;
+----+-------------+------+
| id | name        | age  |
+----+-------------+------+
|  1 | tom         |   20 |
|  2 | jerry       |   23 |
|  3 | shenyi      |   25 |
|  4 | sean        |   28 |
|  5 | zhangshan   |   26 |
|  7 | lisi        |   50 |
|  8 | chenshuo    |   10 |
|  9 | wangwu      |  100 |
| 10 | qiuyi       |   15 |
| 11 | qiuxiaotian |   20 |
+----+-------------+------+
10 rows in set (0.00 sec)mysql> select * from student123;
+----+--------+------+-------+--------+-----------+
| id | name   | age  | sex   | height | course_id |
+----+--------+------+-------+--------+-----------+
|  1 | Dany   |   25 | man   |    160 |         1 |
|  2 | Green  |   23 | man   |    158 |         2 |
|  3 | Henry  |   23 | woman |    185 |         1 |
|  4 | Jane   |   22 | man   |    162 |         3 |
|  5 | Jim    |   24 | woman |    175 |         2 |
|  6 | John   |   21 | woman |    172 |         4 |
|  7 | Lily   |   22 | man   |    165 |         4 |
|  8 | Susan  |   23 | man   |    170 |         5 |
|  9 | Thomas |   22 | woman |    178 |         5 |
| 10 | Tom    |   23 | woman |    165 |         5 |
| 11 | lq     |   25 | man   |    175 |      NULL |
+----+--------+------+-------+--------+-----------+
11 rows in set (0.00 sec)

差异备份与恢复
mysql差异备份
开启MySQL服务器的二进制日志功能

[root@syf ~]# vim /etc/my.cnf
[mysqld]
basedir = /usr/local/mysql
datadir = /opt/data
socket = /tmp/mysql.sock
port = 3306
pid-file = /opt/data/mysql.pid
user = mysql
skip-name-resolveserver-id = 1   //设置服务器标识符
log-bin = mysql_bin    //开启二进制日志功能
~  
[root@syf ~]# systemctl restart mysqld

完全备份:

[root@syf ~]# mysqldump -uroot -predhat --single-transaction --flush-logs --master-data=2 --all-databases --delete-master-logs > all-20250917.sql
mysqldump: [Warning] Using a password on the command line interface can be insecure.
[root@syf ~]# ll /root/all-20250917.sql anaconda-ks.cfg 
-rw-------. 1 root root   2028 Jul 23 11:40 anaconda-ks.cfg
-rw-r--r--  1 root root 880912 Sep 17 20:31 /root/all-20250917.sql

增加新内容:

mysql> insert into shenyi values(8,'hehe',20),(9,'xixi',50);
Query OK, 2 rows affected (0.01 sec)
Records: 2  Duplicates: 0  Warnings: 0mysql> select * from shenyi;
+----+-----------+------+
| id | name      | age  |
+----+-----------+------+
|  1 | tom       |   20 |
|  2 | jerry     |   23 |
|  3 | shenyi    |   25 |
|  4 | sean      |   28 |
|  5 | zhangshan |   26 |
|  6 | zhangshan |   20 |
|  7 | lisi      | NULL |
|  8 | hehe      |   20 |
|  9 | xixi      |   50 |
+----+-----------+------+
9 rows in set (0.00 sec)mysql> update shenyi set age=40 where id=8;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0mysql> select * from shenyi;
+----+-----------+------+
| id | name      | age  |
+----+-----------+------+
|  1 | tom       |   20 |
|  2 | jerry     |   23 |
|  3 | shenyi    |   25 |
|  4 | sean      |   28 |
|  5 | zhangshan |   26 |
|  6 | zhangshan |   20 |
|  7 | lisi      | NULL |
|  8 | hehe      |   40 |
|  9 | xixi      |   50 |
+----+-----------+------+
9 rows in set (0.00 sec)

mysql差异备份恢复
模拟误删数据

[root@syf ~]# mysql -uroot -predhat -e 'drop database shenyi;'mysql: [Warning] Using a password on the command line interface can be insecure.
[root@syf ~]# mysql -uroot -predhat -e 'show databases;'
mysql: [Warning] Using a password on the command line interface can be insecure.
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sy                 |
| sys                |
+--------------------+
由上可以看到chenyu这个数据库已被删除
[root@syf ~]# ll /opt/data
total 123012
-rw-r----- 1 mysql mysql       56 Sep 15 20:46 auto.cnf
-rw------- 1 mysql mysql     1680 Sep 15 20:46 ca-key.pem
-rw-r--r-- 1 mysql mysql     1112 Sep 15 20:46 ca.pem
-rw-r--r-- 1 mysql mysql     1112 Sep 15 20:46 client-cert.pem
-rw------- 1 mysql mysql     1676 Sep 15 20:46 client-key.pem
-rw-r----- 1 mysql mysql     1097 Sep 17 20:19 ib_buffer_pool
-rw-r----- 1 mysql mysql 12582912 Sep 17 20:42 ibdata1
-rw-r----- 1 mysql mysql 50331648 Sep 17 20:43 ib_logfile0
-rw-r----- 1 mysql mysql 50331648 Sep 15 20:46 ib_logfile1
-rw-r----- 1 mysql mysql 12582912 Sep 17 20:31 ibtmp1
drwxr-x--- 2 mysql mysql     4096 Sep 17 19:49 mysql
-rw-r----- 1 mysql mysql      878 Sep 17 20:42 mysql_bin.000002   ////////
-rw-r----- 1 mysql mysql       19 Sep 17 20:31 mysql_bin.index
-rw-r----- 1 mysql mysql        6 Sep 17 20:19 mysql.pid
drwxr-x--- 2 mysql mysql     8192 Sep 15 20:46 performance_schema
-rw------- 1 mysql mysql     1676 Sep 15 20:46 private_key.pem
-rw-r--r-- 1 mysql mysql      452 Sep 15 20:46 public_key.pem
-rw-r--r-- 1 mysql mysql     1112 Sep 15 20:46 server-cert.pem
-rw------- 1 mysql mysql     1680 Sep 15 20:46 server-key.pem
drwxr-x--- 2 mysql mysql       56 Sep 17 19:49 sy
-rw-r----- 1 mysql mysql    53098 Sep 17 20:19 syf.example.com.err
drwxr-x--- 2 mysql mysql     8192 Sep 15 20:46 sys

刷新创建新的二进制日志

[root@syf ~]# mysqladmin -uroot -predhat flush-logs
mysqladmin: [Warning] Using a password on the command line interface can be insecure.
[root@syf ~]# ll /opt/data/
total 123016
-rw-r----- 1 mysql mysql       56 Sep 15 20:46 auto.cnf
-rw------- 1 mysql mysql     1680 Sep 15 20:46 ca-key.pem
-rw-r--r-- 1 mysql mysql     1112 Sep 15 20:46 ca.pem
-rw-r--r-- 1 mysql mysql     1112 Sep 15 20:46 client-cert.pem
-rw------- 1 mysql mysql     1676 Sep 15 20:46 client-key.pem
-rw-r----- 1 mysql mysql     1097 Sep 17 20:19 ib_buffer_pool
-rw-r----- 1 mysql mysql 12582912 Sep 17 20:45 ibdata1
-rw-r----- 1 mysql mysql 50331648 Sep 17 20:45 ib_logfile0
-rw-r----- 1 mysql mysql 50331648 Sep 15 20:46 ib_logfile1
-rw-r----- 1 mysql mysql 12582912 Sep 17 20:31 ibtmp1
drwxr-x--- 2 mysql mysql     4096 Sep 17 19:49 mysql
-rw-r----- 1 mysql mysql      925 Sep 17 20:45 mysql_bin.000002
-rw-r----- 1 mysql mysql      154 Sep 17 20:45 mysql_bin.000003
-rw-r----- 1 mysql mysql       38 Sep 17 20:45 mysql_bin.index
-rw-r----- 1 mysql mysql        6 Sep 17 20:19 mysql.pid
drwxr-x--- 2 mysql mysql     8192 Sep 15 20:46 performance_schema
-rw------- 1 mysql mysql     1676 Sep 15 20:46 private_key.pem
-rw-r--r-- 1 mysql mysql      452 Sep 15 20:46 public_key.pem
-rw-r--r-- 1 mysql mysql     1112 Sep 15 20:46 server-cert.pem
-rw------- 1 mysql mysql     1680 Sep 15 20:46 server-key.pem
drwxr-x--- 2 mysql mysql       56 Sep 17 19:49 sy
-rw-r----- 1 mysql mysql    53098 Sep 17 20:19 syf.example.com.err
drwxr-x--- 2 mysql mysql     8192 Sep 15 20:46 sys

恢复完全备份

[root@syf ~]# mysql -uroot -predhat < all-20250917.sql
mysql: [Warning] Using a password on the command line interface can be insecure.
[root@syf ~]# mysql -uroot -predhat -e 'show databases;'
mysql: [Warning] Using a password on the command line interface can be insecure.
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| shenyi             |
| sy                 |
| sys                |
+--------------------+
[root@syf ~]# mysql -uroot -predhat -e 'show tables from shenyi;'
mysql: [Warning] Using a password on the command line interface can be insecure.
+------------------+
| Tables_in_shenyi |
+------------------+
| course           |
| student          |
| student123       |
+------------------+
[root@syf ~]# mysql -uroot -predhat -e 'select * from shenyi.student;'
mysql: [Warning] Using a password on the command line interface can be insecure.
+----+-------------+------+
| id | name        | age  |
+----+-------------+------+
|  1 | tom         |   20 |
|  2 | jerry       |   23 |
|  3 | shenyi      |   25 |
|  4 | sean        |   28 |
|  5 | zhangshan   |   26 |
|  7 | lisi        |   50 |
|  8 | chenshuo    |   10 |
|  9 | wangwu      |  100 |
| 10 | qiuyi       |   15 |
| 11 | qiuxiaotian |   20 |
+----+-------------+------+
[root@syf ~]# mysql -uroot -predhat -e 'select * from shenyi.student123;'
mysql: [Warning] Using a password on the command line interface can be insecure.
+----+--------+------+-------+--------+-----------+
| id | name   | age  | sex   | height | course_id |
+----+--------+------+-------+--------+-----------+
|  1 | Dany   |   25 | man   |    160 |         1 |
|  2 | Green  |   23 | man   |    158 |         2 |
|  3 | Henry  |   23 | woman |    185 |         1 |
|  4 | Jane   |   22 | man   |    162 |         3 |
|  5 | Jim    |   24 | woman |    175 |         2 |
|  6 | John   |   21 | woman |    172 |         4 |
|  7 | Lily   |   22 | man   |    165 |         4 |
|  8 | Susan  |   23 | man   |    170 |         5 |
|  9 | Thomas |   22 | woman |    178 |         5 |
| 10 | Tom    |   23 | woman |    165 |         5 |
| 11 | lq     |   25 | man   |    175 |      NULL |
+----+--------+------+-------+--------+-----------+

恢复差异备份

[root@syf ~]# ll /opt/data/
total 124036
-rw-r----- 1 mysql mysql       56 Sep 15 20:46 auto.cnf
-rw------- 1 mysql mysql     1680 Sep 15 20:46 ca-key.pem
-rw-r--r-- 1 mysql mysql     1112 Sep 15 20:46 ca.pem
-rw-r--r-- 1 mysql mysql     1112 Sep 15 20:46 client-cert.pem
-rw------- 1 mysql mysql     1676 Sep 15 20:46 client-key.pem
-rw-r----- 1 mysql mysql     1097 Sep 17 20:19 ib_buffer_pool
-rw-r----- 1 mysql mysql 12582912 Sep 17 20:54 ibdata1
-rw-r----- 1 mysql mysql 50331648 Sep 17 20:54 ib_logfile0
-rw-r----- 1 mysql mysql 50331648 Sep 15 20:46 ib_logfile1
-rw-r----- 1 mysql mysql 12582912 Sep 17 20:31 ibtmp1
drwxr-x--- 2 mysql mysql     4096 Sep 17 20:52 mysql
-rw-r----- 1 mysql mysql      925 Sep 17 20:45 mysql_bin.000002
-rw-r----- 1 mysql mysql   861912 Sep 17 20:52 mysql_bin.000003
-rw-r----- 1 mysql mysql       38 Sep 17 20:45 mysql_bin.index
-rw-r----- 1 mysql mysql        6 Sep 17 20:19 mysql.pid
drwxr-x--- 2 mysql mysql     8192 Sep 15 20:46 performance_schema
-rw------- 1 mysql mysql     1676 Sep 15 20:46 private_key.pem
-rw-r--r-- 1 mysql mysql      452 Sep 15 20:46 public_key.pem
-rw-r--r-- 1 mysql mysql     1112 Sep 15 20:46 server-cert.pem
-rw------- 1 mysql mysql     1680 Sep 15 20:46 server-key.pem
drwxr-x--- 2 mysql mysql      138 Sep 17 20:52 shenyi
drwxr-x--- 2 mysql mysql       56 Sep 17 20:52 sy
-rw-r----- 1 mysql mysql    53098 Sep 17 20:19 syf.example.com.err
drwxr-x--- 2 mysql mysql     8192 Sep 15 20:46 sys

检查误删数据库的位置在什么地方

mysql> show binlog events in 'mysql_bin.000002';
+------------------+-----+----------------+-----------+-------------+---------------------------------------+
| Log_name         | Pos | Event_type     | Server_id | End_log_pos | Info                                  |
+------------------+-----+----------------+-----------+-------------+---------------------------------------+
| mysql_bin.000002 |   4 | Format_desc    |         1 |         123 | Server ver: 5.7.37-log, Binlog ver: 4 |
| mysql_bin.000002 | 123 | Previous_gtids |         1 |         154 |                                       |
| mysql_bin.000002 | 154 | Anonymous_Gtid |         1 |         219 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'  |
| mysql_bin.000002 | 219 | Query          |         1 |         289 | BEGIN                                 |
| mysql_bin.000002 | 289 | Table_map      |         1 |         340 | table_id: 143 (sy.shenyi)             |
| mysql_bin.000002 | 340 | Write_rows     |         1 |         403 | table_id: 143 flags: STMT_END_F       |
| mysql_bin.000002 | 403 | Xid            |         1 |         434 | COMMIT /* xid=524 */                  |
| mysql_bin.000002 | 434 | Anonymous_Gtid |         1 |         499 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'  |
| mysql_bin.000002 | 499 | Query          |         1 |         569 | BEGIN                                 |
| mysql_bin.000002 | 569 | Table_map      |         1 |         620 | table_id: 143 (sy.shenyi)             |
| mysql_bin.000002 | 620 | Update_rows    |         1 |         684 | table_id: 143 flags: STMT_END_F       |
| mysql_bin.000002 | 684 | Xid            |         1 |         715 | COMMIT /* xid=526 */                  |
| mysql_bin.000002 | 715 | Anonymous_Gtid |         1 |         780 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'  |
| mysql_bin.000002 | 780 | Query          |         1 |         878 | drop database shenyi                  |
| mysql_bin.000002 | 878 | Rotate         |         1 |         925 | mysql_bin.000003;pos=4                |
+------------------+-----+----------------+-----------+-------------+---------------------------------------+
15 rows in set (0.01 sec)

使用mysqlbinlog恢复差异备份

[root@syf ~]# mysqlbinlog --stop-position=780 /opt/data/mysql_bin.000002 |mysql -uroot -predhat
mysql: [Warning] Using a password on the command line interface can be insecure.
[root@syf ~]# mysql -uroot -predhat -e 'select * from sy.shenyi;'
mysql: [Warning] Using a password on the command line interface can be insecure.
+----+-----------+------+
| id | name      | age  |
+----+-----------+------+
|  1 | tom       |   20 |
|  2 | jerry     |   23 |
|  3 | shenyi    |   25 |
|  4 | sean      |   28 |
|  5 | zhangshan |   26 |
|  6 | zhangshan |   20 |
|  7 | lisi      | NULL |
|  8 | hehe      |   40 |
|  9 | xixi      |   50 |
+----+-----------+------+

文章转载自:

http://FdVvNgfq.njftk.cn
http://xI6GTWvj.njftk.cn
http://6csiZRUC.njftk.cn
http://msZazujs.njftk.cn
http://Ou87HaZg.njftk.cn
http://6Wu9WPFL.njftk.cn
http://NPrvqmvL.njftk.cn
http://txt4Z9h9.njftk.cn
http://Gt37IS7U.njftk.cn
http://d94B41MN.njftk.cn
http://Mbzpjisa.njftk.cn
http://Aonk1pPP.njftk.cn
http://6IQLUG04.njftk.cn
http://Vk329Apg.njftk.cn
http://mX3LyKK4.njftk.cn
http://wlFlK366.njftk.cn
http://Oa2KbryK.njftk.cn
http://26GsLnls.njftk.cn
http://IVJC2gtF.njftk.cn
http://qi2A12xk.njftk.cn
http://BPIVHBjV.njftk.cn
http://shZni68P.njftk.cn
http://6MJjg4Do.njftk.cn
http://P9vaTVbF.njftk.cn
http://4zSPQVNy.njftk.cn
http://aycxdpvl.njftk.cn
http://7z5JO3I4.njftk.cn
http://mwI9YvdP.njftk.cn
http://3gETMHwh.njftk.cn
http://IIAUX1tM.njftk.cn
http://www.dtcms.com/a/388625.html

相关文章:

  • vue3学习日记(十四):两大API选型指南
  • 微信支付回调成功通知到本地
  • 量化交易 - Simple Regression 简单线性回归(机器学习)
  • Kubernetes控制器详解:从Deployment到CronJob
  • python 架构技术50
  • 第九周文件上传
  • MCP大白话理解
  • 【Qt】QJsonValue存储 int64 类型的大整数时,数值出现莫名其妙的变化
  • 【C语言】冒泡排序算法解析与实现
  • [GESP202309 三级] 进制判断
  • 【C++】const和static的用法
  • 箭头函数{}规则,以及隐式返回
  • brain.js构建训练神经网络
  • 开学季高效学习与知识管理技术
  • C++STL与字符串探秘
  • 【面试题】- 使用CompletableFuture实现多线程统计策略工厂模式
  • 打工人日报#20250917
  • LeetCode:12.最小覆盖字串
  • 【C++】 深入理解C++虚函数表与对象析构机制
  • C++ 中 ->和 . 操作符的区别
  • SQL CTE (Common Table Expression) 详解
  • 解决windows更新之后亮度条消失无法调节的问题
  • FPGA学习篇——Verilog学习译码器的实现
  • JavaScript Promise 终极指南 解决回调地狱的异步神器 99% 开发者都在用
  • AI智能体开发实战:从提示工程转向上下文工程的完整指南
  • jtag协议处理流程
  • 【LeetCode 每日一题】2749. 得到整数零需要执行的最少操作数
  • 《饿殍:明末千里行》Switch版试玩发布 3月13日发售
  • LeetCode:9.找到字符串中所有的字母异位词
  • Java获取淘宝商品详情数据的详细说明