学习自测与解析:MySQL 系列第三期与第四期

学习自测与解析:MySQL 系列第三期与第四期

本笔记为第三期(DML 与单表查询)和第四期(多表查询与外键)的配套自测题解析。共十题,每题包含:题目回顾、考查知识点、详细解答与分析。


题目一:INSERT 语句的多种形式

题目 :请写出下列三种 INSERT 操作的 SQL 语句(假设表 stu 已存在,字段为 id(自增主键)、nameagegender):

  1. 插入一条完整记录(id 指定为 10,name='张三', age=20, gender='M')。
  2. 插入两条记录,只提供 name 和 age,gender 使用默认值(默认为 'M')。
  3. 从另一张表 tmp_stu 中复制所有年龄大于 18 岁的学生信息到 stu 表中(字段完全匹配)。

考查知识点

  • INSERT 插入单条/多条记录(第三期 §1.1)
  • 指定字段与默认值
  • INSERT ... SELECT 复制数据

详细解答

sql

复制代码
-- 1. 插入完整记录
INSERT INTO stu (id, name, age, gender) VALUES (10, '张三', 20, 'M');
-- 或按表顺序(如果字段完全匹配)
INSERT INTO stu VALUES (10, '张三', 20, 'M', DEFAULT);  -- 假设还有 is_del 等字段

-- 2. 插入两条记录,使用默认值
INSERT INTO stu (name, age) VALUES ('李四', 22), ('王五', 19);

-- 3. 从另一张表复制数据
INSERT INTO stu (name, age, gender)
SELECT name, age, gender FROM tmp_stu WHERE age > 18;

题目二:UPDATE 的安全更新模式

题目 :MySQL 中的安全更新模式(--safe-updates)有什么作用?当启用该模式后,以下哪些 UPDATE 语句会被拒绝?为什么?

  • A. UPDATE stu SET age = 25;
  • B. UPDATE stu SET age = 25 WHERE name = '张三';(name 字段无索引)
  • C. UPDATE stu SET age = 25 WHERE id = 10;(id 是主键)

考查知识点

  • 安全更新模式的作用与限制(第三期 §1.2)
  • 索引列在 WHERE 条件中的必要性

详细解答

安全更新模式的作用:防止因忘记添加 WHERE 条件而误更新或删除全表数据。它要求 UPDATE 和 DELETE 语句的 WHERE 条件必须使用索引列(或加上 LIMIT 限制)。

  • 语句 A :无条件更新全表 → 被拒绝
  • 语句 B :WHERE 条件使用了 name 字段,但该字段没有索引 → 被拒绝
  • 语句 C :WHERE 条件使用了主键 id(主键自动有索引) → 允许执行

启用方式 :命令行 mysql -U 或在配置文件中添加 safe-updates


题目三:逻辑删除与物理删除的区别

题目:在生产环境中为什么通常推荐使用"逻辑删除"而不是"物理删除"?请给出实现逻辑删除的 SQL 示例,并说明查询时如何过滤掉已删除的数据。

考查知识点

  • 逻辑删除与物理删除的概念(第三期 §1.3)
  • 实际业务场景的数据保留策略

详细解答

区别

  • 物理删除 :使用 DELETE 语句,数据从磁盘中移除,不可恢复(除非从备份中还原)。
  • 逻辑删除 :使用 UPDATE 语句,将某标记字段(如 is_del)设为 1,数据仍保留在表中,只是被标记为"已删除"。

推荐理由

  • 数据可恢复:误删除时可以快速将标记改回 0。
  • 保留历史记录:便于审计和追溯。
  • 避免级联影响:保留外键关联的完整性。

实现示例

sql

复制代码
-- 添加删除标记字段
ALTER TABLE stu ADD is_del BOOLEAN DEFAULT FALSE;

-- 逻辑删除 id=11 的记录
UPDATE stu SET is_del = 1 WHERE id = 11;

-- 查询时过滤未删除的数据
SELECT * FROM stu WHERE is_del = 0;

题目四:聚合函数与 GROUP BY 的使用

题目 :现有订单表 orders(字段:order_id, customer_id, amount, order_date)。请写出 SQL 语句完成以下查询:

  1. 统计总订单数、总金额、平均金额、最大金额、最小金额。
  2. 按客户(customer_id)分组,统计每个客户的订单数量及总金额,并只显示订单数量大于等于 2 的客户。

考查知识点

  • 聚合函数 COUNT, SUM, AVG, MAX, MIN(第三期 §2.3)
  • GROUP BY 分组与 HAVING 过滤

详细解答

sql

复制代码
-- 1. 全表统计
SELECT 
    COUNT(*) AS 总订单数,
    SUM(amount) AS 总金额,
    AVG(amount) AS 平均金额,
    MAX(amount) AS 最大金额,
    MIN(amount) AS 最小金额
FROM orders;

-- 2. 分组统计并过滤
SELECT 
    customer_id,
    COUNT(*) AS 订单数量,
    SUM(amount) AS 总金额
FROM orders
GROUP BY customer_id
HAVING COUNT(*) >= 2;

注意HAVING 用于分组后过滤,WHERE 用于分组前过滤。


题目五:多表查询中的 NULL 处理

题目 :在左外连接中,如果右表没有匹配的行,右表的字段会显示为 NULL。如果需要筛选出"没有匹配"的行(例如,查询没有选课的学生),应该如何写 WHERE 条件?请以学生表 student 和选课表 sc 为例,写出 SQL。

考查知识点

  • 左外连接产生的 NULL 值(第四期 §2.3)
  • IS NULL 条件的应用

详细解答

查询没有选课的学生:学生左连接选课表,匹配不上的选课表字段为 NULL。筛选这些 NULL 即可。

sql

复制代码
SELECT s.*
FROM student s
LEFT JOIN sc ON s.stu_id = sc.stu_id
WHERE sc.course_id IS NULL;

原理 :如果学生有选课记录,sc.course_id 非空;如果没有选课,sc.course_id 为 NULL。因此用 IS NULL 找出未选课学生。


题目六:内连接与外连接的区别

题目:解释 INNER JOIN、LEFT JOIN 和 RIGHT JOIN 的区别。以下查询结果有何不同?

  • 查询 A:SELECT * FROM A INNER JOIN B ON A.id = B.a_id;
  • 查询 B:SELECT * FROM A LEFT JOIN B ON A.id = B.a_id;

假设 A 表有 3 行(id=1,2,3),B 表有 2 行(a_id=1, a_id=1),请分别写出结果的行数(非具体数据)。

考查知识点

  • 内连接、左外连接的定义与结果集范围(第四期 §2.2~2.4)
  • 连接的行数估算

详细解答

区别

  • INNER JOIN:只返回两表连接条件匹配的行。如果 A 的一行在 B 中匹配到多行,结果会重复该 A 行。
  • LEFT JOIN:返回左表(A)的所有行,右表(B)匹配不上的填充 NULL。A 中的每一行至少出现一次,即使没有匹配。
  • RIGHT JOIN:与 LEFT 相反,返回右表的所有行。

本例数据

A 表:id=1,2,3

B 表:a_id=1, a_id=1(两条记录,都指向 A.id=1)

  • 查询 A(INNER JOIN):A.id=1 在 B 中有 2 条匹配,所以结果包含 2 行(A.id=1 重复出现两次);A.id=2 和 3 无匹配,不出现。总行数 = 2
  • 查询 B(LEFT JOIN):A.id=1 匹配 2 行 → 2 行;A.id=2 无匹配 → 1 行(B 部分为 NULL);A.id=3 无匹配 → 1 行。总行数 = 4

题目七:自连接的应用场景

题目 :有一张员工表 emp,包含字段 emp_id(员工ID)、name(姓名)、manager_id(上级的员工ID,若为 NULL 表示无上级)。请写出 SQL 查询每个员工的姓名及其上级的姓名(没有上级的上级姓名显示为 NULL)。

考查知识点

  • 自连接(SELF JOIN)的用法(第四期 §2.6)
  • 左连接保留所有员工

详细解答

sql

复制代码
SELECT 
    e.name AS 员工姓名,
    m.name AS 上级姓名
FROM emp e
LEFT JOIN emp m ON e.manager_id = m.emp_id;

使用 LEFT JOIN 确保没有上级的员工(manager_id 为 NULL)也被包含在结果中,且上级姓名为 NULL。


题目八:UNION 与 UNION ALL 的区别

题目UNIONUNION ALL 有何区别?在什么情况下应优先使用 UNION ALL?请举例说明。

考查知识点

  • 联合查询的去重行为(第四期 §2.7)
  • 性能考量

详细解答

区别

  • UNION:对合并后的结果集进行去重 (类似 SELECT DISTINCT),需要排序和比较,性能较低。
  • UNION ALL:直接合并所有结果集,不去重,性能更高。

优先使用 UNION ALL 的场景

  • 确认两个子查询的结果集不会有重复行时(如按不同维度统计,或子查询条件互斥)。
  • 即使有重复,但业务上允许或不需要去重时。

示例 :查询"胜率高于 70% 的英雄"和"胜率低于 45% 的英雄",这两个集合不可能有交集,应使用 UNION ALL

sql

复制代码
SELECT name, 'high' AS type FROM heroes WHERE win_rate > 70
UNION ALL
SELECT name, 'low' AS type FROM heroes WHERE win_rate < 45;

题目九:外键约束的级联操作

题目 :在 MySQL 中,创建外键时可以指定 ON DELETE CASCADEON DELETE SET NULL。请解释这两种模式的含义,并各举一个适合使用的业务场景。

考查知识点

  • 外键约束模式(第四期 §3.3)
  • 级联删除与置空的适用场景

详细解答

  • ON DELETE CASCADE(级联删除) :当主表中的记录被删除时,自动删除所有引用该记录的从表记录。
    场景:订单与订单明细。删除订单时,订单明细应同时删除,否则会遗留孤儿明细数据。
  • ON DELETE SET NULL(删除置空) :当主表记录被删除时,将从表中的外键字段设为 NULL(该字段必须允许 NULL)。
    场景:部门与员工。删除部门后,希望员工记录保留,但部门字段设为 NULL,表示员工当前无归属部门。

示例 SQL

sql

复制代码
-- 级联删除
CREATE TABLE order_detail (
    ...,
    FOREIGN KEY (order_id) REFERENCES orders(order_id) ON DELETE CASCADE
);

-- 删除置空
CREATE TABLE employee (
    ...,
    dept_id INT NULL,
    FOREIGN KEY (dept_id) REFERENCES department(dept_id) ON DELETE SET NULL
);

题目十:综合多表查询实战

题目 :基于第四期的王者荣耀数据库(表:wanjiayingxiongzhanji),请写出 SQL 查询"每个玩家的昵称、使用的英雄名、该英雄的胜率、以及该英雄皮肤的平均价格(假设皮肤表 pifu 通过 yingxiong_id 关联)"。要求包含所有至少有一条战绩记录的玩家,并按胜率降序排列。

考查知识点

  • 多表连接(INNER JOIN + 子查询或聚合)
  • 关联字段的层级(wanjia → zhanji → yingxiong → pifu)
  • ORDER BY 排序

详细解答

sql

复制代码
SELECT 
    w.wanjia_nicheng AS 玩家昵称,
    y.yingxiong_ming AS 英雄名,
    z.shenglv AS 胜率,
    COALESCE(AVG(p.jiage), 0) AS 皮肤平均价格   -- 没有皮肤的显示 0
FROM wanjia w
INNER JOIN zhanji z ON w.wanjia_id = z.wanjia_id
INNER JOIN yingxiong y ON z.yingxiong_id = y.yingxiong_id
LEFT JOIN pifu p ON y.yingxiong_id = p.yingxiong_id
GROUP BY w.wanjia_nicheng, y.yingxiong_ming, z.shenglv
ORDER BY z.shenglv DESC;

说明 :使用 LEFT JOIN pifu 确保即使英雄没有皮肤(如新英雄)也能显示 NULL 并被 COALESCE 转换为 0。GROUP BY 按玩家+英雄分组,因为一个玩家可能多次使用同一英雄(实际 zhanji 表中一个玩家一个英雄只有一条记录,此处分组不影响,但规范写法需要列出所有非聚合字段)。


附:知识点对应总表

题号 主要考查知识点(对应笔记章节)
1 第三期 §1.1 INSERT 插入数据(多种形式)
2 第三期 §1.2 UPDATE 安全更新模式
3 第三期 §1.3 逻辑删除 vs 物理删除
4 第三期 §2.3 聚合函数与 GROUP BY / HAVING
5 第四期 §2.3 左外连接与 NULL 过滤
6 第四期 §2.2~2.4 内连接与外连接的区别
7 第四期 §2.6 自连接
8 第四期 §2.7 UNION 与 UNION ALL
9 第四期 §3.3 外键级联操作
10 第四期 §四 综合多表查询实战

学习建议:对于答错的题目,请回看第三期或第四期对应章节,并动手在 MySQL 环境中执行代码。熟练掌握多表查询是进阶 MySQL 高可用架构的基础。

相关推荐
就叫_这个吧1 小时前
IDEA Mybatis xml文件,实现sql语句联想,自动填入补充
xml·mysql·intellij-idea·mybatis
AOwhisky1 小时前
Redis 学习笔记(第四期):高可用与集群(哨兵 + Cluster + 容器化)
linux·运维·数据库·redis·笔记·学习·缓存
零陵上将军_xdr1 小时前
Shell脚本入门:从Hello World到变量的灵活运用
linux
skywalk81631 小时前
言知项目后续方向建议
开发语言·学习·编程
努力写A题的小菜鸡1 小时前
PyTorch 图像预处理 transforms 与 TensorBoard 可视化 (自己学习记录)
人工智能·pytorch·学习
一尘之中1 小时前
从概念到实践:软件架构核心知识梳理
学习·ai写作
猫猫聚会Ing1 小时前
数据库设计 Prompt 提示词 - 构建与迭代
数据库
上海云盾-小余1 小时前
源站隐藏实战:规避裸 IP 被直接攻击的完整方案
数据库·网络协议·tcp/ip
C语言小火车1 小时前
嵌入式Linux应用开发技术栈完全指南
linux·运维·服务器
IT WorryFree2 小时前
FortiGate 排错常用OID速查表(含Trap OID+轮询OID)
运维·网络