MySQL DML 操作(CRUD)总结

本文基于 MySQL 8.0 编写,全面讲解数据表增(Create)、查(Retrieve)、改(Update)、删(Delete) 核心语法、实战案例、易错点、执行顺序。

一、前言:什么是 CRUD

数据库最核心的四大操作简称 CRUD,对应日常数据管理所有场景:

英文 中文 对应 SQL 操作
Create 新增数据 INSERT
Retrieve 查询数据 SELECT(使用频率最高)
Update 修改数据 UPDATE
Delete 删除数据 DELETE / TRUNCATE

前置准备:本文所有案例统一使用两张测试表,先执行建表语句,后续案例均基于此表操作。

sql 复制代码
-- 学生表:存储学生基础信息
CREATE TABLE students (
    id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID,自增',
    sn INT NOT NULL UNIQUE COMMENT '学号,唯一约束',
    name VARCHAR(20) NOT NULL COMMENT '姓名',
    qq VARCHAR(20) COMMENT 'QQ号,允许为空'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 成绩表:存储学生考试成绩(核心查询案例表)
CREATE TABLE exam_result (
    id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID',
    name VARCHAR(20) NOT NULL COMMENT '学生姓名',
    chinese FLOAT DEFAULT 0.0 COMMENT '语文成绩',
    math FLOAT DEFAULT 0.0 COMMENT '数学成绩',
    english FLOAT DEFAULT 0.0 COMMENT '英语成绩'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 给成绩表插入测试数据
INSERT INTO exam_result (name, chinese, math, english)
VALUES 
('张三', 67, 98, 56),
('李四', 87, 78, 77),
('王五', 88, 98, 90),
('赵六', 82, 84, 67),
('钱七', 55, 85, 45),
('孙八', 70, 73, 78),
('周九', 75, 65, 30);

二、数据新增:INSERT(Create)

2.1 基础语法

sql 复制代码
-- 标准语法,INTO 可省略
INSERT [INTO] 表名 
[(字段1, 字段2, ...)] 
VALUES (值1, 值2, ...), (值1, 值2, ...);

规则:

  1. 字段列表 和 VALUES 值列表 数量、顺序、数据类型必须一一对应
  2. 自增主键、默认值字段可省略不写,MySQL 自动填充;
  3. 支持单行插入多行批量插入(多行插入效率远高于多次单行插入)。

2.2 分类实战案例

2.2.1 全列插入(不指定字段)

不写字段列表,代表给表中所有字段按顺序赋值,自增主键也需要手动指定值。

sql 复制代码
-- 单行全列插入
INSERT INTO students VALUES (1, 1001, '张三', '123456');
-- 多行全列插入
INSERT INTO students VALUES 
(2, 1002, '李四', '654321'),
(3, 1003, '王五', NULL); -- QQ为空,使用 NULL

2.2.2 指定列插入(推荐用法)

只给部分字段赋值,未指定字段会使用默认值/自增规则,日常开发最常用。

sql 复制代码
-- 仅插入学号、姓名,id自增、qq默认为NULL
INSERT INTO students (sn, name) 
VALUES (1004, '赵六'), (1005, '钱七');

2.2.3 插入冲突处理(主键/唯一键重复)

主键(PRIMARY KEY)唯一键(UNIQUE) 重复时,直接插入会报错 Duplicate entry,MySQL 提供两种解决方案。

方案1:存在则更新 ON DUPLICATE KEY UPDATE

逻辑:键重复时,更新指定字段;无重复则正常插入。

sql 复制代码
-- id=1 已存在,触发更新;不存在则新增
INSERT INTO students (id, sn, name) 
VALUES (1, 1009, '小张')
ON DUPLICATE KEY UPDATE sn = 1009, name = '小张';

返回行数说明(易错点)

  • 1 row affected:无冲突,数据新增成功;
  • 2 row affected:存在冲突,数据更新成功;
  • 0 row affected:存在冲突,但新旧数据完全一致,无变更。
方案2:存在则替换 REPLACE INTO

逻辑:键重复时,先删除原数据,再插入新数据;无重复则直接插入。

sql 复制代码
-- 学号sn是唯一键,重复则删除旧数据、插入新数据
REPLACE INTO students (sn, name, qq) VALUES (1001, '新张三', '999999');

区别总结

  • ON DUPLICATE KEY UPDATE:原地更新,保留原数据主键;
  • REPLACE:删旧插新,自增主键会重新生成,慎用。

2.3 拓展:插入查询结果

一张表的查询结果直接插入另一张表,常用于数据备份、去重、数据迁移。

sql 复制代码
-- 语法:INSERT ... SELECT
INSERT INTO 目标表(字段1,字段2) SELECT 字段1,字段2 FROM 源表 [条件];

-- 示例:将成绩表中数学>80的学生姓名、成绩插入新表
CREATE TABLE temp_result (name VARCHAR(20), math FLOAT);
INSERT INTO temp_result (name, math) 
SELECT name, math FROM exam_result WHERE math > 80;

三、数据查询:SELECT(Retrieve)【重点】

SELECT 是 MySQL 使用率最高的语句,支持字段筛选、条件过滤、排序、分页、聚合、分组等功能。

3.1 完整语法框架

sql 复制代码
SELECT [DISTINCT] 字段列表
FROM 表名
[WHERE 条件]          -- 行过滤
[GROUP BY 分组字段]   -- 分组
[HAVING 分组后条件]   -- 分组过滤
[ORDER BY 排序字段]   -- 结果排序
[LIMIT 分页限制];     -- 分页

3.2 基础查询

3.2.1 全列查询 *

* 代表查询表中所有字段

sql 复制代码
SELECT * FROM exam_result;

⚠️ 开发易错点

禁止在生产环境随意使用 SELECT *

  1. 传输大量无用数据,影响性能;
  2. 无法使用索引,查询效率降低;
  3. 表结构变更后,查询结果列会错乱。

3.2.2 指定列查询(推荐)

手动指定需要查询的字段,字段顺序可自定义,和表结构顺序无关。

sql 复制代码
-- 只查询姓名、语文、数学成绩
SELECT name, chinese, math FROM exam_result;

3.2.3 查询表达式 & 字段别名

查询列可以是算术表达式 (加减乘除),使用 AS 给列起别名(AS 可省略)。

sql 复制代码
-- 1. 计算总分,并设置别名 总分
SELECT 
    name,
    chinese,
    math,
    english,
    chinese + math + english AS total_score -- 别名
FROM exam_result;

-- 2. AS 可省略,简写形式
SELECT name, chinese + math + english total FROM exam_result;

⚠️ 易错点WHERE 子句不能使用字段别名 (执行顺序问题),ORDER BY 可以使用别名。

3.2.4 结果去重 DISTINCT

去除查询结果中完全重复的行 ,写在 SELECT 之后。

sql 复制代码
-- 查询所有不重复的数学成绩
SELECT DISTINCT math FROM exam_result;

3.3 条件过滤:WHERE 子句

WHERE 用于筛选符合条件的行 ,支持比较运算符、逻辑运算符、模糊查询、空值判断

3.3.1 常用运算符汇总

1)比较运算符
运算符 作用 备注
> >= < <= 大小比较 常规数值判断
= 等于 对 NULL 无效NULL = NULL 结果仍为 NULL
<=> 安全等于 支持 NULL 比较,NULL <=> NULL 结果为真
!= / <> 不等于 两种写法等价
BETWEEN a AND b 区间匹配 闭区间 [a,b],包含两端值
IN(值1,值2...) 枚举匹配 匹配括号内任意一个值
2)空值判断

MySQL 中 NULL 不等于任何值,必须使用专用关键字

  • IS NULL:判断字段为空
  • IS NOT NULL:判断字段不为空
3)逻辑运算符
  • AND:并且(所有条件同时成立)
  • OR:或者(任意一个条件成立)
  • NOT:取反(条件不成立)
4)模糊查询 LIKE

搭配通配符使用,常用于搜索场景:

  • %:匹配任意长度字符(包含 0 个字符)
  • _:匹配单个字符

3.3.2 实战案例

sql 复制代码
-- 1. 英语成绩低于60分的学生(比较运算)
SELECT name, english FROM exam_result WHERE english < 60;

-- 2. 语文成绩在 [80,90] 区间(两种写法等价)
SELECT name, chinese FROM exam_result WHERE chinese >=80 AND chinese <=90;
SELECT name, chinese FROM exam_result WHERE chinese BETWEEN 80 AND 90;

-- 3. 数学成绩为 78、84、98 之一(IN 枚举)
SELECT name, math FROM exam_result WHERE math IN(78,84,98);

-- 4. 模糊查询:姓"张"的学生(% 通配)
SELECT name FROM exam_result WHERE name LIKE '张%';
-- 名字第二个字为"五"(_ 单个字符)
SELECT name FROM exam_result WHERE name LIKE '_五';

-- 5. 判断空值:查询QQ号为空的学生
SELECT name FROM students WHERE qq IS NULL;

-- 6. 多条件组合:语文>80 并且 不姓王
SELECT name, chinese FROM exam_result 
WHERE chinese > 80 AND NOT name LIKE '王%';

3.4 结果排序:ORDER BY

对查询结果排序,默认升序(ASC)

语法:ORDER BY 字段 [ASC|DESC]

  • ASC:升序(从小到大,默认可省略)
  • DESC:降序(从大到小)

3.4.1 单字段排序

sql 复制代码
-- 数学成绩升序(默认ASC)
SELECT name, math FROM exam_result ORDER BY math;
-- 数学成绩降序
SELECT name, math FROM exam_result ORDER BY math DESC;

3.4.2 多字段排序(优先级从左到右)

先按第一个字段排序,值相同时再按第二个字段排序。

sql 复制代码
-- 先数学降序,数学相同则英语升序
SELECT name, math, english FROM exam_result
ORDER BY math DESC, english ASC;

3.4.3 排序规则补充(易错点)

  1. NULL 在排序中视为最小值:升序时 NULL 排在最前,降序时排在最后;
  2. ORDER BY 支持表达式、字段别名
  3. ORDER BY 时,查询结果顺序无定义,不要依赖默认顺序。

3.5 分页查询:LIMIT

分页是项目必备功能,用于限制返回数据行数,语法两种写法:

sql 复制代码
-- 写法1:LIMIT 行数 (从第0条开始,取N条)
SELECT 字段 FROM 表 LIMIT N;

-- 写法2:LIMIT 偏移量, 行数 (偏移量从0开始)
SELECT 字段 FROM 表 LIMIT offset, N;

-- 写法3(推荐,语义清晰):LIMIT 行数 OFFSET 偏移量
SELECT 字段 FROM 表 LIMIT N OFFSET offset;

分页实战(每页3条数据)

sql 复制代码
-- 第1页:偏移0,取3条
SELECT * FROM exam_result ORDER BY id LIMIT 3 OFFSET 0;
-- 第2页:偏移3,取3条
SELECT * FROM exam_result ORDER BY id LIMIT 3 OFFSET 3;
-- 第3页:偏移6,取3条(不足3条则返回剩余数据)
SELECT * FROM exam_result ORDER BY id LIMIT 3 OFFSET 6;

开发建议 :查询未知大表时,强制加 LIMIT 1,避免全表查询导致数据库卡死。

3.6 聚合函数

聚合函数用于统计计算,作用于一组数据,返回一个结果。常用 5 大聚合函数:

函数 作用 特性
COUNT(字段/*) 统计行数 COUNT(*) 统计所有行;COUNT(字段) 忽略 NULL
SUM(字段) 求和 仅对数值有效,无数据返回 NULL
AVG(字段) 求平均值 忽略 NULL
MAX(字段) 求最大值 支持数值、字符串
MIN(字段) 求最小值 支持数值、字符串

聚合函数案例

sql 复制代码
-- 1. 统计总人数(COUNT(*) 统计所有行)
SELECT COUNT(*) AS total_student FROM exam_result;

-- 2. 统计有QQ号的学生数(COUNT(字段) 忽略NULL)
SELECT COUNT(qq) AS have_qq FROM students;

-- 3. 数学成绩总分、平均分
SELECT SUM(math) AS math_sum, AVG(math) AS math_avg FROM exam_result;

-- 4. 英语最高分、最低分
SELECT MAX(english) AS max_en, MIN(english) AS min_en FROM exam_result;

-- 5. 去重统计:不重复的数学成绩数量
SELECT COUNT(DISTINCT math) FROM exam_result;

3.7 分组查询:GROUP BY + HAVING

GROUP BY:按照指定字段分组 ,配合聚合函数做分组统计;

HAVING:对分组后的结果 再次过滤(区别于 WHERE)。

核心区别(高频面试题)

  1. WHERE分组前过滤原始数据,不能使用聚合函数;
  2. HAVING分组后过滤分组结果,可以使用聚合函数。

分组案例

sql 复制代码
-- 模拟场景:新增班级字段,按班级分组统计
ALTER TABLE exam_result ADD class VARCHAR(10) COMMENT '班级';
UPDATE exam_result SET class = '一班' WHERE id <=4;
UPDATE exam_result SET class = '二班' WHERE id >4;

-- 1. 按班级分组,统计每个班级人数、语文平均分
SELECT class, COUNT(*) AS num, AVG(chinese) AS avg_ch
FROM exam_result
GROUP BY class;

-- 2. 分组后过滤:只显示平均分大于70的班级(HAVING)
SELECT class, AVG(chinese) AS avg_ch
FROM exam_result
GROUP BY class
HAVING avg_ch > 70;

四、数据修改:UPDATE

4.1 基础语法

sql 复制代码
UPDATE 表名 
SET 字段1 = 值1, 字段2 = 值2, ...
[WHERE 条件] 
[ORDER BY 排序]
[LIMIT 行数];

⚠️ 高危警告 :省略 WHERE更新全表所有数据 ,生产环境严禁裸写 UPDATE 表名 SET ...

4.2 实战案例

sql 复制代码
-- 1. 单字段更新:将张三的数学成绩改为80
UPDATE exam_result SET math = 80 WHERE name = '张三';

-- 2. 多字段更新:同时修改语文、英语成绩
UPDATE exam_result 
SET chinese = 70, english = 60 
WHERE name = '李四';

-- 3. 基于原数据更新(字段自增/自减)
UPDATE exam_result SET math = math + 10 WHERE math < 80;

-- 4. 结合排序+分页更新:成绩倒数3名,数学+20分
UPDATE exam_result 
SET math = math + 20
ORDER BY chinese + math + english ASC
LIMIT 3;

五、数据删除:DELETE & TRUNCATE

5.1 DELETE 语句(删除行数据)

5.1.1 基础语法

sql 复制代码
-- 删除符合条件的行
DELETE FROM 表名 [WHERE 条件] [LIMIT 行数];

案例

sql 复制代码
-- 1. 删除指定学生数据(推荐,带WHERE)
DELETE FROM exam_result WHERE name = '李四';

-- 2. 删除全表数据(高危!)
DELETE FROM students;

DELETE 特性

  1. 只删除数据,保留表结构;
  2. 支持事务,可以回滚;
  3. 自增主键 AUTO_INCREMENT 不会重置,再次插入会延续之前的ID。

5.2 TRUNCATE 语句(截断表)

语法

sql 复制代码
TRUNCATE [TABLE] 表名;

TRUNCATE 特性(和 DELETE 核心区别,面试重点)

  1. 只能清空整张表,无法按条件删除单行;
  2. 不触发事务、无法回滚,执行速度远快于 DELETE
  3. 清空后重置自增主键,新数据ID从1重新开始;
  4. 属于 DDL 语句(数据定义),DELETE 属于 DML 语句(数据操作)。

适用场景

仅用于整表数据清空(测试环境、数据初始化),生产环境谨慎使用。

5.3 DELETE vs TRUNCATE 对比表

特性 DELETE TRUNCATE
操作范围 可按条件删除单行/多行 只能清空全表
事务支持 支持事务、可回滚 不支持事务、不可回滚
自增ID 不重置 重置为初始值
执行速度 较慢 极快
语句类型 DML(数据操作) DDL(数据定义)

六、高频考点:SQL 关键字执行顺序(面试必背)

完整执行顺序(从先到后):

复制代码
FROM → ON → JOIN → WHERE → GROUP BY → HAVING → SELECT → DISTINCT → ORDER BY → LIMIT

顺序解读(解释易错点)

  1. 先通过 FROM 找到表,WHERE 过滤原始数据;
  2. GROUP BY 分组,HAVING 过滤分组结果;
  3. 再执行 SELECT 生成字段别名 → 去重 DISTINCT
  4. 最后 ORDER BY 排序、LIMIT 分页。

对应易错点解释

  • WHERE 不能使用 SELECT 定义的别名:别名是 WHERE 执行完后才生成;
  • HAVINGORDER BY 可以使用别名:执行顺序在 SELECT 之后。

七、全局易错点总结(避坑指南)

  1. NULL 相关= NULL 永远查不到数据,必须用 IS NULL / IS NOT NULLNULL <=> NULL 才会判定为真。
  2. 全表操作UPDATEDELETE 不加 WHERE 会操作全表,生产环境禁止使用。
  3. 别名使用WHERE 不能用字段别名,ORDER BY/HAVING 可以。
  4. DISTINCT :针对整行去重,不是单个字段。
  5. LIMIT 偏移量 :偏移量从 0 开始,分页公式:偏移量 = (页码 - 1) * 每页条数
  6. TRUNCATE:不可逆、不支持事务,正式环境严禁随意执行。
  7. INSERT 多行 :优先使用多行 VALUES 批量插入,性能远高于多次单行插入。

八、总结

本文覆盖 MySQL CRUD 全部核心语法、实战案例、易错点、面试考点,是 MySQL 入门的核心内容:

  1. 新增INSERT 分单行/多行、指定列/全列,冲突处理用 ON DUPLICATE KEY / REPLACE
  2. 查询SELECT 是核心,掌握条件、排序、分页、聚合、分组五大功能;
  3. 修改UPDATE 务必加 WHERE,避免全表更新;
  4. 删除 :区分 DELETE(灵活、可回滚)和 TRUNCATE(极速、清空全表);
  5. 执行顺序:理解关键字执行顺序,就能规避 90% 的语法报错。
相关推荐
数据库小学妹2 小时前
SQL Server数据库同步工具怎么选?6款方案对比+信创迁移避坑清单
数据库·经验分享·sqlserver·dba
不剪发的Tony老师2 小时前
国产数据库之GaussDB:固若金汤
数据库·gaussdb
雨辰AI2 小时前
生产级实测:SpringBoot3 + 达梦数据库接口从 200ms 优化至 20ms 完整调优指南
java·数据库·spring boot·后端·政务
凡人叶枫3 小时前
Effective C++ 条款39:明智而审慎地使用 private 继承
java·数据库·c++·嵌入式开发
基德爆肝c语言3 小时前
MySQL表的操作
前端·数据库·mysql
GreatSQL3 小时前
gt-checksum v4.0.0 新功能解读系列文章(1):断点续传——大任务中断不再从头跑
mysql
TDengine (老段)3 小时前
TDengine 连接算子 — Inner/Outer/ASOF/Window Join 的实现与使用
大数据·数据库·物联网·哈希算法·时序数据库·tdengine·涛思数据
Keano Reurink3 小时前
搜索API与GSC数据对比:发现数据盲区
数据库·python·数据挖掘
shushangyun_3 小时前
汽车服务行业B2B平台+AI解决方案哪家专业:2026年最新测评
java·运维·网络·数据库·人工智能·汽车