
🎬 个人主页 :艾莉丝努力练剑
❄专栏传送门 :《C语言》《数据结构与算法》《C/C++干货分享&学习过程记录》
《Linux操作系统编程详解》《笔试/面试常见算法:从基础到进阶》《Python干货分享》
⭐️为天地立心,为生民立命,为往圣继绝学,为万世开太平
🎬 艾莉丝的简介:

文章目录
- [1 ~> 数据更新操作(UPDATE)](#1 ~> 数据更新操作(UPDATE))
-
- [1.1 基础语法与执行逻辑](#1.1 基础语法与执行逻辑)
- [1.2 使用规范与风险管控](#1.2 使用规范与风险管控)
- [1.3 典型应用场景](#1.3 典型应用场景)
-
- [1.3.1 单条件单列更新](#1.3.1 单条件单列更新)
- [1.3.2 单条件多列更新](#1.3.2 单条件多列更新)
- [1.3.3 排序限量更新](#1.3.3 排序限量更新)
- [1.3.4 全表更新(高危操作)](#1.3.4 全表更新(高危操作))
- [2 ~> 数据删除操作(DELETE & TRUNCATE)](#2 ~> 数据删除操作(DELETE & TRUNCATE))
-
- [2.1 DELETE 语句](#2.1 DELETE 语句)
-
- [2.1.1 基础语法](#2.1.1 基础语法)
- [2.1.2 条件删除](#2.1.2 条件删除)
- [2.1.3 限量删除](#2.1.3 限量删除)
- [2.1.4 全表删除特性](#2.1.4 全表删除特性)
- [2.2 TRUNCATE 截断表](#2.2 TRUNCATE 截断表)
-
- [2.2.1 语法与执行效果](#2.2.1 语法与执行效果)
- [2.2.2 底层原理与特性](#2.2.2 底层原理与特性)
- [2.3 DELETE 与 TRUNCATE 核心对比](#2.3 DELETE 与 TRUNCATE 核心对比)
- [3 ~> 插入查询结果(INSERT ... SELECT)](#3 ~> 插入查询结果(INSERT ... SELECT))
-
- [3.1 语法结构与适用场景](#3.1 语法结构与适用场景)
- [3.2 表数据去重实战](#3.2 表数据去重实战)
-
- [3.2.1 实现思路](#3.2.1 实现思路)
- [3.2.2 执行步骤](#3.2.2 执行步骤)
- [3.2.3 RENAME 原子性原理](#3.2.3 RENAME 原子性原理)
- [4 ~> 聚合函数(聚合统计)](#4 ~> 聚合函数(聚合统计))
-
- [4.1 核心作用](#4.1 核心作用)
- [4.2 五大核心函数详解](#4.2 五大核心函数详解)
-
- [4.2.1 COUNT ():统计行数](#4.2.1 COUNT ():统计行数)
- [4.2.2 SUM ():数值求和](#4.2.2 SUM ():数值求和)
- [4.2.3 AVG ():数值求平均](#4.2.3 AVG ():数值求平均)
- [4.2.4 MAX () / MIN ():求极值](#4.2.4 MAX () / MIN ():求极值)
- [4.3 使用约束与易错点](#4.3 使用约束与易错点)
- [5 ~> 分组查询(GROUP BY)](#5 ~> 分组查询(GROUP BY))
-
- [5.1 分组核心逻辑](#5.1 分组核心逻辑)
- [5.2 分组语法](#5.2 分组语法)
-
- [5.2.1 单字段分组](#5.2.1 单字段分组)
- [5.2.2 多字段分组](#5.2.2 多字段分组)
- [5.3 HAVING 分组后过滤](#5.3 HAVING 分组后过滤)
- [5.4 WHERE 与 HAVING 的本质区别](#5.4 WHERE 与 HAVING 的本质区别)
- [5.5 only_full_group_by 约束规则](#5.5 only_full_group_by 约束规则)
- [6 ~> SQL 执行顺序与实战考点](#6 ~> SQL 执行顺序与实战考点)
-
- [6.1 SQL 关键字执行优先级](#6.1 SQL 关键字执行优先级)
- [6.2 高频面试考点](#6.2 高频面试考点)
- [6.3 实战刷题推荐](#6.3 实战刷题推荐)
- 结尾

1 ~> 数据更新操作(UPDATE)
1.1 基础语法与执行逻辑
UPDATE 属于 DML(数据操作语言),用于修改表中指定行的列值,执行逻辑为先按条件匹配行,再对匹配行执行列更新。 标准语法:
sql
UPDATE table_name
SET column = expr [, column = expr ...]
[WHERE ...] [ORDER BY ...] [LIMIT ...]
SET子句:指定更新列与目标值,右侧支持常量、列运算表达式;MySQL 不支持math += 30这类自增简写,必须写作math = math + 30。WHERE子句:筛选待更新的行,是数据安全的核心屏障。ORDER BY + LIMIT:对匹配结果排序后,仅更新前 N 行。
1.2 使用规范与风险管控
- 先查后改:执行 UPDATE 前,必须先用相同 WHERE 条件执行 SELECT,确认更新范围符合预期。
- 严禁无 WHERE 更新:缺失 WHERE 子句会对全表指定列执行更新,属于数据库高危操作,生产环境禁止手工执行。
- 权限隔离:生产库通常仅开放应用服务的 UPDATE 权限,禁止研发人员直连数据库执行手工数据修改。
1.3 典型应用场景
1.3.1 单条件单列更新
需求:将孙悟空同学的数学成绩变更为 80 分
sql
-- 步骤1:查询验证目标数据
SELECT name, math FROM exam_result WHERE name = '孙悟空';
-- 步骤2:执行数据更新
UPDATE exam_result SET math = 80 WHERE name = '孙悟空';
-- 步骤3:验证更新结果
SELECT name, math FROM exam_result WHERE name = '孙悟空';
1.3.2 单条件多列更新
需求:将曹孟德同学的数学成绩改为 60 分,语文成绩改为 70 分
sql
-- 多列更新用逗号分隔,一次性生效
UPDATE exam_result
SET math = 60, chinese = 70
WHERE name = '曹孟德';
1.3.3 排序限量更新
需求:将总成绩倒数前三的 3 位同学的数学成绩加上 30 分
sql
-- 先查询确认倒数前三的名单
SELECT name, math, chinese + math + english AS 总分
FROM exam_result
ORDER BY 总分 ASC LIMIT 3;
-- 按总分升序排序,取前3行执行更新
UPDATE exam_result
SET math = math + 30
ORDER BY chinese + math + english ASC
LIMIT 3;
注意:更新后学生总分排名可能发生变化,原倒数第三名可能脱离倒数区间。
1.3.4 全表更新(高危操作)
需求:将所有同学的语文成绩更新为原来的 2 倍
sql
-- 无WHERE子句,全表所有行生效,生产环境必须经过审批与备份后方可执行
UPDATE exam_result SET chinese = chinese * 2;
2 ~> 数据删除操作(DELETE & TRUNCATE)
2.1 DELETE 语句
DELETE 用于删除表中的行数据,执行后仅删除数据,保留表结构。
2.1.1 基础语法
sql
DELETE FROM table_name
[WHERE ...] [ORDER BY ...] [LIMIT ...]
- 同 UPDATE 一致,无 WHERE 子句将删除全表所有行数据。
- 支持 ORDER BY 排序后,通过 LIMIT 删除指定数量的行。
2.1.2 条件删除
需求:删除孙悟空同学的考试成绩
sql
-- 先验证目标行
SELECT * FROM exam_result WHERE name = '孙悟空';
-- 执行删除
DELETE FROM exam_result WHERE name = '孙悟空';
2.1.3 限量删除
需求:删除全班总分倒数第一的同学成绩
sql
DELETE FROM exam_result
ORDER BY chinese + math + english ASC
LIMIT 1;
2.1.4 全表删除特性
- 执行
DELETE FROM 表名;会清空全表数据,但不会重置 AUTO_INCREMENT 自增计数器,后续新插入数据的 ID 会在旧最大值基础上继续递增。 - DELETE 是行级操作,走事务流程,支持事务内回滚;会生成完整的 redo/undo 日志,数据可恢复。
2.2 TRUNCATE 截断表
TRUNCATE 属于 DDL(数据定义语言),用于快速清空整表数据。
2.2.1 语法与执行效果
sql
TRUNCATE [TABLE] table_name;
执行效果:清空表中所有数据,保留表结构,同时重置 AUTO_INCREMENT 自增计数器。
2.2.2 底层原理与特性
- 操作粒度:只能对整表操作,无法像 DELETE 一样按条件删除部分数据。
- 执行效率:远高于 DELETE 全表;原理是直接释放表的数据页,而非逐行删除数据。
- 事务与回滚:不经过事务引擎的行级处理,无法通过事务回滚恢复数据。
- 日志特性【审计修正】:原文 "truncate 不记录日志" 表述不严谨。准确表述为:truncate 不产生逐行删除的 undo/redo 行级日志,但会将 DDL 操作记录到 binlog 中,因此主从复制架构下可正常同步。
- 自增特性:会重置 AUTO_INCREMENT 计数器为初始值,新插入数据 ID 从 1 开始计数。
2.3 DELETE 与 TRUNCATE 核心对比
| 对比维度 | DELETE | TRUNCATE |
|---|---|---|
| 语句类型 | DML 数据操作语言 | DDL 数据定义语言 |
| 操作范围 | 支持 WHERE 条件删除部分行 | 只能清空整表 |
| 执行原理 | 逐行删除,记录行级日志 | 直接释放数据页,执行效率极高 |
| 自增计数器 | 不重置,保留原有计数 | 重置为初始值 |
| 事务回滚 | 支持事务内回滚 | 不支持事务回滚 |
| 触发器 | 会触发表的 DELETE 触发器 | 不会触发任何触发器 |
3 ~> 插入查询结果(INSERT ... SELECT)
3.1 语法结构与适用场景
将 SELECT 查询的结果集直接批量插入到目标表中,常用于数据迁移、表汇总、数据去重等场景。
sql
INSERT INTO table_name [(column [, column ...])]
SELECT ...;
- 要求 SELECT 结果的列数量、数据类型与目标表的插入列一一对应。
- 支持全列插入(省略列名)与指定列插入。
3.2 表数据去重实战
需求:删除表中的重复记录,每组重复数据仅保留一份。
3.2.1 实现思路
当表无唯一主键、重复行完全一致时,无法直接通过 DELETE 删除部分重复行(删除会清除所有重复项)。因此采用 "建新表→插入去重数据→原子重命名切换" 的方案,实现无感知去重。
3.2.2 执行步骤
sql
-- 1. 创建与原表结构完全一致的空表
CREATE TABLE no_duplicate_table LIKE duplicate_table;
-- 2. 将原表去重后的数据批量插入新表
INSERT INTO no_duplicate_table
SELECT DISTINCT * FROM duplicate_table;
-- 3. 原子重命名:原表改名备份,新表改为原表名,一步完成切换
RENAME TABLE
duplicate_table TO old_duplicate_table,
no_duplicate_table TO duplicate_table;
-- 4. 验证去重结果
SELECT * FROM duplicate_table;
3.2.3 RENAME 原子性原理
- MySQL 的
RENAME TABLE是原子操作,本质是修改文件系统中表文件的名称与 inode 映射关系,不涉及数据拷贝,执行速度极快(毫秒级)。 - 业务无感知:切换过程中不会出现表不存在的中间状态,是生产环境数据表变更的标准方案。
- 对应 Linux 底层:调用 rename 系统调用,仅修改目录项的文件名映射,不移动磁盘数据块。
4 ~> 聚合函数(聚合统计)
4.1 核心作用
聚合函数对一组行数据进行汇总计算,最终返回单个统计结果,是分组查询的基础能力。
4.2 五大核心函数详解
4.2.1 COUNT ():统计行数
语法:COUNT([DISTINCT] expr)
COUNT(*):统计结果集的总行数,不受 NULL 值影响,是最标准的统计写法。COUNT(列名):统计指定列非 NULL 的行数,列值为 NULL 的行不计入统计。COUNT(DISTINCT 列名):统计指定列去重后的非 NULL 行数。COUNT(1):效果与COUNT(*)在 InnoDB 引擎下性能无显著差异。
示例:
sql
-- 统计班级总人数
SELECT COUNT(*) AS 总人数 FROM exam_result;
-- 统计有数学成绩的学生数
SELECT COUNT(math) FROM exam_result;
-- 统计不重复的数学成绩数量
SELECT COUNT(DISTINCT math) FROM exam_result;
4.2.2 SUM ():数值求和
对数值列进行求和计算,非数值列无意义;无匹配行时返回 NULL。 示例:
sql
-- 统计全班数学成绩总分
SELECT SUM(math) AS 数学总分 FROM exam_result;
-- 统计不及格学生的数学总分
SELECT SUM(math) FROM exam_result WHERE math < 60;
4.2.3 AVG ():数值求平均
对数值列计算平均值,自动忽略 NULL 值行。 示例:
sql
-- 统计全班三科平均总分
SELECT AVG(chinese + math + english) AS 平均总分 FROM exam_result;
4.2.4 MAX () / MIN ():求极值
返回指定列中的最大值 / 最小值,非数值列无统计意义。 示例:
sql
-- 查询英语最高分
SELECT MAX(english) FROM exam_result;
-- 查询70分以上的数学最低分
SELECT MIN(math) FROM exam_result WHERE math > 70;
4.3 使用约束与易错点
- 无 GROUP BY 时,聚合函数对整个结果集计算,SELECT 后只能跟随聚合函数,不能跟随普通列(
only_full_group_by模式下会直接报错)。 - 聚合函数不能直接写在 WHERE 子句中(WHERE 执行顺序早于聚合计算),聚合结果的条件过滤必须使用 HAVING。
5 ~> 分组查询(GROUP BY)
5.1 分组核心逻辑
按照指定列的值,将整张表的数据划分为多个逻辑组,对每个组分别执行聚合统计,最终每组返回一条统计结果。
- 核心价值:实现按维度统计,如 "每个部门的平均工资""每个岗位的人数"。
- 理解模型:分组等价于将一张大表逻辑拆分为多张子表,每张子表独立执行聚合统计。
5.2 分组语法
5.2.1 单字段分组
需求:查询每个部门的平均工资和最高工资
sql
SELECT deptno, AVG(sal) AS 平均工资, MAX(sal) AS 最高工资
FROM emp
GROUP BY deptno;
5.2.2 多字段分组
需求:查询每个部门下每种岗位的平均工资和最低工资
sql
SELECT deptno, job, AVG(sal) AS 平均工资, MIN(sal) AS 最低工资
FROM emp
GROUP BY deptno, job;
- 分组字段越多,分组粒度越细,最终结果的行数越多。
5.3 HAVING 分组后过滤
对分组聚合后的结果进行条件筛选,必须与 GROUP BY 配合使用。 需求:显示平均工资低于 2000 的部门和它的平均工资
sql
SELECT deptno, AVG(sal) AS 平均工资
FROM emp
GROUP BY deptno
HAVING 平均工资 < 2000;
5.4 WHERE 与 HAVING 的本质区别
| 对比维度 | WHERE | HAVING |
|---|---|---|
| 执行阶段 | 分组前过滤,作用于原始表行 | 分组后过滤,作用于聚合结果 |
| 过滤对象 | 原始行数据 | 分组后的统计结果 |
| 聚合函数 | 不能使用聚合函数作为条件 | 可以直接使用聚合结果作为筛选条件 |
| 执行顺序 | 先于 GROUP BY 执行 | 后于 GROUP BY 执行 |
核心结论:WHERE 过滤 "原始数据行",HAVING 过滤 "聚合统计结果",二者应用场景不同,无法完全互相替代。
5.5 only_full_group_by 约束规则
- MySQL 默认开启
sql_mode=only_full_group_by严格模式。 - 规则:SELECT 子句中出现的列,必须是 GROUP BY 后的分组列,或者是聚合函数的计算结果。
- 底层逻辑:非分组列在组内不唯一,无法确定返回组内哪一行的值,属于逻辑不严谨的写法。
- 错误示例:
SELECT ename, deptno, AVG(sal) FROM emp GROUP BY deptno;会触发语法错误,因为ename既不是分组列也不是聚合结果。
6 ~> SQL 执行顺序与实战考点
6.1 SQL 关键字执行优先级
标准 SQL 的执行流程(优先级从高到低):
Plain
FROM > ON > JOIN > WHERE > GROUP BY > WITH > HAVING > SELECT > DISTINCT > ORDER BY > LIMIT
- 核心理解:先确定数据源(FROM/JOIN),再过滤无效行(WHERE),再分组聚合(GROUP BY/HAVING),再筛选输出列(SELECT),最后排序与分页(ORDER BY/LIMIT)。
- 这也是 "WHERE 中不能用 SELECT 别名、不能用聚合函数,而 HAVING 可以用 SELECT 别名" 的根本原因。
6.2 高频面试考点
- DELETE 与 TRUNCATE 的核心区别
- WHERE 与 HAVING 的本质区别与应用场景
- GROUP BY 的执行逻辑与
only_full_group_by约束 - 单条 SQL 的完整执行顺序
- 无主键表的数据去重实现方案
6.3 实战刷题推荐
- 牛客 SQL 篇:批量插入数据、去重薪水查询、最晚入职员工、薪水涨幅统计、部门经理薪资、分组数目统计
- LeetCode:重复邮箱、大的国家、第 N 高的薪水
结尾
uu们,本文的内容到这里就全部结束了,艾莉丝在这里再次感谢您的阅读!
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| ### 艾莉丝努力练剑 C/C++ & Linux 底层探索者 | 一个正在努力练剑的技术博主 *** ** * ** *** 👀 【关注】 跟随我一起深耕技术领域,见证每一次成长。 ❤️ 【点赞】 让优质内容被更多人看见,让知识传递更有力量。 ⭐ 【收藏】 把核心知识点存好,在需要时随时查、随时用。 💬 【评论】 分享你的经验或疑问,评论区一起交流避坑! 不要忘记给博主"一键四连"哦! "今日练剑达成!"
"技术之路难免有困惑,但同行的人会让前进更有方向。" |
结语:希望对学习Linux相关内容的uu有所帮助,不要忘记给博主"一键四连"哦!
往期回顾:
🗡博主在这里放了一只小狗,大家看完了摸摸小狗放松一下吧!🗡 ૮₍ ˶ ˊ ᴥ ˋ˶₎ა
