从零起步学习MySQL 第三章:DML语句定义及常见用法示例

从零起步学习MySQL 第三章:DML语句定义及常见用法示例

上一章我们学习了DDL语句,掌握了数据库和表的“创建、修改、删除”等结构定义操作,相当于搭建好了数据存储的“容器”。今天我们进入更核心的学习——DML语句,它是操作“容器”中数据的关键,学会DML,你才能真正实现数据的增、删、改、查,解锁MySQL的核心使用场景。

一、什么是DML?新手必懂的核心定义

DML 的全称是 Data Manipulation Language(数据操作语言),它与上一章的DDL(数据定义语言)核心区别在于:DDL操作的是“数据库对象的结构”,而DML操作的是“表中的数据”,不改变表的结构本身。

简单来说,DDL是“建房子”(搭建表结构),DML就是“住人、装修”(操作表中数据)。在MySQL中,DML语句的核心作用是对表中的数据进行增、删、改、查,也是我们日常开发中使用频率最高的SQL语句。

这里有一个新手容易混淆的知识点:严格来说,“查询数据”的SELECT语句属于DQL(Data Query Language,数据查询语言),但在很多书籍、教程以及面试中,SELECT语句通常会被包含在DML的范畴中,我们今天也统一按这个习惯讲解,更贴合实际开发场景。

常见的DML操作及对应SQL语句,用表格总结更清晰,新手建议收藏:

操作类型

SQL语句

说明

插入数据

INSERT

向表中新增一条或多条数据记录

更新数据

UPDATE

修改表中已存在的数据记录

删除数据

DELETE

删除表中已有的数据记录

查询数据

SELECT

检索表中的数据(严格来说属于DQL)

✨ 新手注意:DML语句与DDL语句的核心区别——DML语句执行后不会自动提交事务(可回滚),而DDL语句会自动提交事务(不可回滚),这个区别我们在后面会详细讲解。

二、INSERT:插入数据(新增记录)

INSERT语句是向表中添加新数据的核心语句,语法简单但有很多细节需要注意,尤其是“列和值的匹配”,新手很容易在这里踩坑。下面我们结合实例,从基础到进阶,一步步掌握INSERT的用法。

1. 基本语法(推荐用法)

最规范、最推荐的插入语法,明确指定要插入的列名和对应的值,避免因表结构变更导致插入失败:

-- 基本语法:INSERT INTO 表名 (列1, 列2, 列3, ...) VALUES (值1, 值2, 值3, ...); -- 注意:列名和值的顺序必须一一对应,数据类型也要匹配

2. 基础示例

我们以上一章创建的“学生表(student)”为例(先创建表,新手可直接复制执行):

-- 先创建student表(若已存在可跳过) CREATE TABLE IF NOT EXISTS student ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50) NOT NULL, age INT CHECK(age >= 0), major VARCHAR(100) NOT NULL ); -- 插入一条学生数据 INSERT INTO student (id, name, age, major) VALUES (1, '张三', 20, '计算机科学'); -- 插入成功后,可通过SELECT查询验证(后面会详细讲SELECT) SELECT * FROM student;

✨ 新手注意:如果表的主键设置了AUTO_INCREMENT(自动增长),插入时可以不指定id列,MySQL会自动生成递增的主键值,更便捷:

-- 不指定id(自动增长),仅插入name、age、major INSERT INTO student (name, age, major) VALUES ('张三', 20, '计算机科学');

3. 一次插入多条数据(高效用法)

如果需要插入多条数据,无需多次执行INSERT语句,可在VALUES后拼接多个值列表,执行效率更高,语法如下:

-- 一次插入多条数据,用逗号分隔多个值列表 INSERT INTO student (name, age, major) VALUES (2, '李四', 21, '软件工程'), -- 第一条 (3, '王五', 19, '人工智能'), -- 第二条 (4, '赵六', 22, '网络工程'); -- 第三条

✅ 优势:减少与数据库的交互次数,提升插入效率,尤其适合批量插入少量数据(大批量数据建议用LOAD DATA INFILE等方式)。

4. 插入全部列(不推荐用法)

如果要给表中的所有字段都插入值,可以省略列名,但这种方式不推荐,因为一旦表结构发生变更(如新增、删除列),插入语句就会报错:

-- 省略列名,必须按表中字段的顺序插入所有值 INSERT INTO student VALUES (5, '孙七', 20, '信息安全'); -- 错误示例:如果表新增了gender列,省略列名插入就会报错 -- INSERT INTO student VALUES (6, '周八', 21, '大数据'); -- 字段数量不匹配,报错

⚠️ 警告:日常开发中,尽量不要省略列名,避免因表结构变更导致插入失败,提升代码的可维护性。

三、UPDATE:更新数据(修改记录)

UPDATE语句用于修改表中已存在的数据,是日常开发中高频使用的语句,但也是新手最容易踩坑的语句——忘记写WHERE条件,会导致整张表的数据被修改,造成不可逆的损失,一定要格外谨慎!

1. 基本语法(必记)

-- 基本语法:UPDATE 表名 SET 列1 = 值1, 列2 = 值2, ... WHERE 条件; -- 核心:WHERE条件用于指定要修改的记录,缺一不可!

2. 基础示例

修改student表中“张三”的年龄和专业,明确指定WHERE条件,确保只修改目标记录:

-- 修改张三的年龄为22,专业改为大数据技术 UPDATE student SET age = 22, major = '大数据技术' WHERE name = '张三'; -- 验证修改结果 SELECT name, age, major FROM student WHERE name = '张三';

3. 增加条件过滤(多条件修改)

实际开发中,常常需要根据多个条件筛选要修改的记录,可使用AND、OR等逻辑运算符拼接条件:

-- 修改年龄大于20且专业为计算机科学的学生,将专业改为人工智能 UPDATE student SET major = '人工智能' WHERE age > 20 AND major = '计算机科学'; -- 说明:AND表示“同时满足两个条件”,OR表示“满足任意一个条件”

4. 新手必踩坑点(重点警告)

⚠️ 绝对禁止:在没有WHERE条件的情况下执行UPDATE语句!会修改表中所有记录,比如下面这句:

-- 错误示例:没有WHERE条件,会将所有学生的年龄改为20 UPDATE student SET age = 20; -- 后果:整张表的age字段全部被修改,无法撤销(除非有备份或事务回滚)

✅ 建议:执行UPDATE语句前,先执行对应的SELECT语句,验证筛选的记录是否正确,再执行UPDATE,比如:

-- 先验证:查询年龄大于20且专业为计算机科学的学生 SELECT * FROM student WHERE age > 20 AND major = '计算机科学'; -- 确认记录正确后,再执行UPDATE语句 UPDATE student SET major = '人工智能' WHERE age > 20 AND major = '计算机科学';

四、DELETE:删除数据(移除记录)

DELETE语句用于删除表中已存在的记录,与UPDATE类似,忘记写WHERE条件会删除表中所有数据,且删除后的数据若未备份,很难恢复,一定要谨慎操作。

1. 基本语法

-- 基本语法:DELETE FROM 表名 WHERE 条件; -- 核心:WHERE条件用于指定要删除的记录,不可省略(除非确实要删除所有数据)

2. 基础示例

删除student表中id为3的学生记录(精准删除,风险最低):

-- 删除student表中所有数据(表结构保留) DELETE FROM student; -- 注意:删除后,表结构仍然存在,可重新插入数据

3. 删除所有数据(谨慎使用)

如果确实需要删除表中所有数据,可省略WHERE条件,但一定要确认无误后再执行:

-- 删除student表中所有数据(表结构保留) DELETE FROM student; -- 注意:删除后,表结构仍然存在,可重新插入数据

4. 对比TRUNCATE(与DDL的区别)

上一章我们学习了TRUNCATE语句,它也能清空表数据,很多新手会把它和DELETE混淆,这里用表格明确两者的区别,面试常考,一定要记牢:

对比维度

DELETE(DML语句)

TRUNCATE(DDL语句)

所属类别

DML(数据操作语言)

DDL(数据定义语言)

执行速度

较慢(逐行删除,记录日志,可回滚)

非常快(直接清空表数据,不记录日志)

是否可回滚

✅ 可回滚(事务内执行时,未提交可撤销)

❌ 不可回滚(执行即生效,自动提交事务)

是否重置自增

❌ 不重置(删除后,自增主键继续从之前的最大值递增)

✅ 重置(清空后,自增主键重新从1开始)

✅ 总结:日常开发中,若需要清空数据且可能需要回滚,用DELETE;若确定不需要回滚、追求效率,用TRUNCATE(但要格外谨慎)。

五、SELECT:查询数据(检索记录)

SELECT语句是MySQL中使用频率最高的语句,没有之一。它的功能非常灵活,可实现简单的全表查询,也能实现复杂的条件筛选、排序、分页、分组统计等操作。下面我们从基础到进阶,逐步掌握SELECT的核心用法。

1. 基本语法(通用模板)

SELECT语句的语法可灵活组合,核心模板如下,后续所有用法都是基于这个模板扩展:

-- 基本语法模板 SELECT 列1, 列2, ... -- 要查询的列(*表示查询所有列) FROM 表名 -- 要查询的表 WHERE 条件 -- 筛选条件(可选) ORDER BY 排序列 -- 排序(可选,ASC升序,DESC降序) LIMIT 限制条数; -- 限制查询结果条数(可选,用于分页)

2. 基础示例(简单查询)

最常用的两种简单查询,适合快速检索数据:

-- 1. 查询指定列:查询所有学生的姓名和年龄(只返回需要的列,提升效率) SELECT name, age FROM student; -- 2. 查询所有列:查询所有学生的全部信息(*表示所有列,不推荐在生产环境使用) SELECT * FROM student;

✨ 建议:生产环境中,尽量不要用*查询所有列,只查询需要的列,可减少数据传输量,提升查询效率。

3. 条件过滤(WHERE子句)

通过WHERE子句筛选符合条件的记录,常用的条件运算符有:>(大于)、<(小于)、=(等于)、>=(大于等于)、<=(小于等于)、<>(不等于),以及AND、OR逻辑运算符:

-- 示例1:查询年龄大于20的学生 SELECT * FROM student WHERE age > 20; -- 示例2:查询年龄大于等于20且专业为人工智能的学生 SELECT * FROM student WHERE age >= 20 AND major = '人工智能'; -- 示例3:查询年龄小于19或专业为软件工程的学生 SELECT * FROM student WHERE age < 19 OR major = '软件工程';

4. 模糊查询(LIKE子句)

当不知道具体的查询值,只知道部分内容时,可用LIKE进行模糊查询,常用通配符:%(表示任意长度的字符序列,包括0个字符)、_(表示单个字符):

-- 示例1:查询姓名以“张”开头的学生(%匹配“张”后面的任意字符) SELECT * FROM student WHERE name LIKE '张%'; -- 示例2:查询姓名包含“李”字的学生(%匹配“李”前后的任意字符) SELECT * FROM student WHERE name LIKE '%李%'; -- 示例3:查询姓名第二个字是“四”的学生(_匹配单个字符) SELECT * FROM student WHERE name LIKE '_四%';

5. 排序(ORDER BY子句)

查询结果默认是无序的,可通过ORDER BY子句对结果进行排序,ASC表示升序(默认,可省略),DESC表示降序:

-- 示例1:按年龄升序排序(从大到小,默认ASC,可省略) SELECT * FROM student ORDER BY age; -- 等价于:SELECT * FROM student ORDER BY age ASC; -- 示例2:按年龄降序排序(从小到大) SELECT * FROM student ORDER BY age DESC; -- 示例3:多列排序:先按专业升序,再按年龄降序 SELECT * FROM student ORDER BY major ASC, age DESC;

6. 限制条数(LIMIT子句,分页查询)

当查询结果较多时,可用LIMIT限制返回的条数,常用于分页查询(比如每页显示5条数据),语法有两种:

-- 语法1:LIMIT 条数(返回前N条记录) SELECT * FROM student LIMIT 5; -- 返回前5条学生记录 -- 语法2:LIMIT 偏移量, 条数(从第N+1条开始,返回M条记录) SELECT * FROM student LIMIT 5, 5; -- 从第6条开始,返回5条(第6-10条) -- 分页场景示例:第1页(1-5条)、第2页(6-10条)、第3页(11-15条) -- 第1页:LIMIT 0, 5(偏移量0,返回5条) -- 第2页:LIMIT 5, 5(偏移量5,返回5条) -- 第3页:LIMIT 10, 5(偏移量10,返回5条)

7. 聚合函数(统计查询)

聚合函数用于对数据进行统计计算,常用的聚合函数有:COUNT(统计条数)、AVG(求平均值)、SUM(求和)、MAX(求最大值)、MIN(求最小值),通常与AS配合使用,给统计结果起别名:

-- 示例1:统计学生总人数(COUNT(*) 统计所有记录,包括NULL值) SELECT COUNT(*) AS 总人数 FROM student; -- 示例2:统计学生的平均年龄(AVG(列名) 求指定列的平均值) SELECT AVG(age) AS 平均年龄 FROM student; -- 示例3:统计学生的最大年龄和最小年龄 SELECT MAX(age) AS 最大年龄, MIN(age) AS 最小年龄 FROM student; -- 示例4:统计某专业的学生总人数 SELECT COUNT(*) AS 计算机专业人数 FROM student WHERE major = '计算机科学';

8. 分组查询(GROUP BY + HAVING)

当需要按某个字段分组统计时,可用GROUP BY子句,搭配HAVING子句过滤分组后的结果(注意:HAVING用于过滤分组,WHERE用于过滤行):

-- 示例:按专业分组,统计每个专业的学生人数,且只显示人数大于2的专业 SELECT major, COUNT(*) AS 人数 FROM student GROUP BY major -- 按major字段分组 HAVING 人数 > 2; -- 过滤分组结果,只保留人数>2的专业 -- 注意:WHERE和HAVING的区别: -- WHERE:分组前过滤行(比如先过滤年龄>20的学生,再分组) -- HAVING:分组后过滤分组(比如先分组,再过滤人数>2的分组)

六、DML操作与事务(Transaction)

在Java后端开发中,事务控制是非常关键的知识点,尤其是DML语句(INSERT、UPDATE、DELETE)会改变数据,必须通过事务保证数据的一致性(比如转账操作,扣款和到账必须同时成功或同时失败)。

核心原则:DML语句执行后,不会自动提交事务,需手动执行COMMIT提交;若执行过程中出现错误,可执行ROLLBACK回滚,撤销所有未提交的修改。

1. 开启与提交事务(基础用法)

通过START TRANSACTION开启事务,执行完所有DML操作后,用COMMIT提交事务,事务提交后,修改会永久生效:

-- 示例:模拟转账操作(id=1的账户扣款100,id=2的账户到账100) START TRANSACTION; -- 开启事务 UPDATE account SET balance = balance - 100 WHERE id = 1; -- 扣款 UPDATE account SET balance = balance + 100 WHERE id = 2; -- 到账 COMMIT; -- 提交事务,所有修改永久生效

2. 回滚事务(撤销修改)

若执行DML操作后发现错误,在未提交事务前,可执行ROLLBACK回滚,撤销所有未提交的修改,数据恢复到事务开启前的状态:

START TRANSACTION; UPDATE account SET balance = balance - 100 WHERE id = 1; -- 假设这里出现错误(比如id=2不存在),执行回滚 ROLLBACK; -- 撤销扣款操作,id=1的账户余额恢复原样

3. 与Java结合(实战场景)

实际Java后端开发中,很少直接手动执行事务相关的SQL语句,通常通过Spring框架的@Transactional注解控制事务,简化开发:

import org.springframework.transaction.annotation.Transactional; // 转账服务类 public class TransferService { // 注入账户Mapper(用于操作数据库) private AccountMapper accountMapper; // @Transactional注解:开启事务,方法内所有DML操作要么同时成功,要么同时失败 @Transactional public void transfer(int fromId, int toId, int amount) { // 扣款:从fromId账户减去amount accountMapper.decreaseBalance(fromId, amount); // 到账:给toId账户增加amount accountMapper.increaseBalance(toId, amount); } } // 说明:如果方法执行过程中出现异常(比如SQL错误、业务异常),Spring会自动执行ROLLBACK // 如果方法正常执行完毕,Spring会自动执行COMMIT

七、DML语句的执行顺序(面试常问)

很多新手会疑惑:SQL语句的书写顺序和执行顺序不一样,为什么?其实SQL是声明式语言,我们只需要告诉MySQL“要查什么”,MySQL会按照内部逻辑顺序执行,这个顺序也是面试高频考点,一定要记牢:

-- 书写顺序(我们写SQL的顺序) SELECT 列名 FROM 表名 WHERE 条件 GROUP BY 列名 HAVING 条件 ORDER BY 列名 LIMIT 条数; -- 执行顺序(MySQL内部实际执行顺序) FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT

✅ 简单理解:先找到要查询的表(FROM),再筛选符合条件的行(WHERE),然后分组(GROUP BY),过滤分组结果(HAVING),再选择要返回的列(SELECT),接着排序(ORDER BY),最后限制返回条数(LIMIT)。

✅ 本章总结(新手必背)

本章我们掌握了DML语句的核心用法,重点记住“增、删、改、查”四大操作,以及事务控制和执行顺序,用表格快速回顾核心要点:

操作类型

核心SQL语句

关键注意点

插入

INSERT INTO ... VALUES ...

列和值的顺序、类型要匹配,推荐指定列名

更新

UPDATE ... SET ... WHERE ...

必写WHERE条件,避免修改整张表

删除

DELETE FROM ... WHERE ...

谨慎省略WHERE,删除前建议先查询验证

查询

SELECT ... FROM ...

支持条件、分组、排序、分页,避免用*查询所有列

事务

START TRANSACTION / COMMIT / ROLLBACK

保证DML操作的一致性,未提交可回滚

最后提醒:DML语句是日常开发的核心,建议大家多敲代码练习,尤其是SELECT语句的复杂用法(分组、聚合、分页),以及事务的控制,这些都是面试和工作中的重点。下一章我们将学习DCL语句,掌握数据库的权限管理,继续加油!

Read more

【OpenClaw从入门到精通】第10篇:OpenClaw生产环境部署全攻略:性能优化+安全加固+监控运维(2026实测版)

【OpenClaw从入门到精通】第10篇:OpenClaw生产环境部署全攻略:性能优化+安全加固+监控运维(2026实测版)

摘要:本文聚焦OpenClaw从测试环境走向生产环境的核心痛点,围绕“性能优化、安全加固、监控运维”三大维度展开实操讲解。先明确生产环境硬件/系统选型标准,再通过硬件层资源管控、模型调度策略、缓存优化等手段提升响应速度(实测响应效率提升50%+);接着从网络、权限、数据三层构建安全防护体系,集成火山引擎安全方案拦截高危操作;最后落地TenacitOS可视化监控与Prometheus告警体系,配套完整故障排查清单和虚拟实战案例。全文所有配置、代码均经实测验证,兼顾新手入门实操性和进阶读者的生产级部署需求,帮助开发者真正实现OpenClaw从“能用”到“放心用”的跨越。 优质专栏欢迎订阅! 【DeepSeek深度应用】【Python高阶开发:AI自动化与数据工程实战】【YOLOv11工业级实战】 【机器视觉:C# + HALCON】【大模型微调实战:平民级微调技术全解】 【人工智能之深度学习】【AI 赋能:Python 人工智能应用实战】【数字孪生与仿真技术实战指南】 【AI工程化落地与YOLOv8/v9实战】【C#工业上位机高级应用:高并发通信+性能优化】 【Java生产级避坑指南:

By Ne0inhk
ARM Linux 驱动开发篇--- Linux 并发与竞争实验(互斥体实现 LED 设备互斥访问)--- Ubuntu20.04互斥体实验

ARM Linux 驱动开发篇--- Linux 并发与竞争实验(互斥体实现 LED 设备互斥访问)--- Ubuntu20.04互斥体实验

🎬 渡水无言:个人主页渡水无言 ❄专栏传送门: 《linux专栏》《嵌入式linux驱动开发》《linux系统移植专栏》 ❄专栏传送门: 《freertos专栏》《STM32 HAL库专栏》 ⭐️流水不争先,争的是滔滔不绝  📚博主简介:第二十届中国研究生电子设计竞赛全国二等奖 |国家奖学金 | 省级三好学生 | 省级优秀毕业生获得者 | ZEEKLOG新星杯TOP18 | 半导纵横专栏博主 | 211在读研究生 在这里主要分享自己学习的linux嵌入式领域知识;有分享错误或者不足的地方欢迎大佬指导,也欢迎各位大佬互相三连 目录 前言  一、实验基础说明 1.1、互斥体简介 1.2 本次实验设计思路 二、硬件原理分析(看过之前博客的可以忽略) 三、实验程序编写 3.1 互斥体 LED 驱动代码(mutex.c) 3.2.1、设备结构体定义(28-39

By Ne0inhk
Flutter for OpenHarmony:swagger_dart_code_generator 接口代码自动化生成的救星(OpenAPI/Swagger) 深度解析与鸿蒙适配指南

Flutter for OpenHarmony:swagger_dart_code_generator 接口代码自动化生成的救星(OpenAPI/Swagger) 深度解析与鸿蒙适配指南

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net 前言 后端工程师扔给你一个 Swagger (OpenAPI) 文档地址,你会怎么做? 1. 对着文档,手写 Dart Model 类(容易写错字段类型)。 2. 手写 Retrofit/Dio 的 API 接口定义(容易拼错 URL)。 3. 当后端修改了字段名,你对着报错修半天。 这是重复劳动的地狱。 swagger_dart_code_generator 可以将 Swagger (JSON/YAML) 文件直接转换为高质量的 Dart 代码,包括: * Model 类:支持 json_serializable,带 fromJson/

By Ne0inhk
Linux 开发别再卡壳!makefile/git/gdb 全流程实操 + 作业解析,新手看完直接用----《Hello Linux!》(5)

Linux 开发别再卡壳!makefile/git/gdb 全流程实操 + 作业解析,新手看完直接用----《Hello Linux!》(5)

文章目录 * 前言 * make/makefile * 文件的三个时间 * Linux第一个小程序-进度条 * 回车和换行 * 缓冲区 * 程序的代码展示 * git指令 * 关于gitee * Linux调试器-gdb使用 * 作业部分 前言 做 Linux 开发时,你是不是也遇到过这些 “卡脖子” 时刻?写 makefile 时,明明语法没错却报错,最后发现是依赖方法行没加 Tab;想提交代码到 gitee,记不清 git add/commit/push 的 “三板斧”,还得反复搜教程;用 gdb 调试程序,输了命令没反应,才想起编译时没加-g生成 debug 版本;甚至连写个进度条,都搞不懂\r和\n的区别,导致进度条乱跳…… 其实这些问题,

By Ne0inhk