深入理解 DML 和 DQL:SQL 数据操作与查询全解析
深入理解 DML 和 DQL:SQL 数据操作与查询全解析
在数据库管理中,SQL(结构化查询语言)是操作和查询数据的核心工具。其中,DML(Data Manipulation Language,数据操作语言) 和 DQL(Data Query Language,数据查询语言) 是最常用的子集。DML 负责数据的插入、更新和删除,而 DQL 专注于数据查询。本文将详细讲解 DML 和 DQL 的核心操作,包括 UPDATE
、DELETE
、TRUNCATE
、SELECT
,以及相关函数和子句,结合示例帮助你快速上手。
一、DML:数据操作语言
DML 用于操作数据库中的数据,主要包括以下操作:
- 插入(INSERT):向表中添加新记录。
- 更新(UPDATE):修改表中已有记录。
- 删除(DELETE):移除表中记录。
以下重点讲解 UPDATE
和 DELETE
,并深入分析 TRUNCATE
与 DELETE
的区别。
1. UPDATE:修改数据
UPDATE
用于修改表中符合条件的记录,语法如下:
UPDATE table_name
SET column1 = value1, column2 = value2, ...
WHERE condition;
- 作用:更新指定列的值。
- 注意:
WHERE
子句指定更新的范围,未指定会导致全表更新。
示例
假设有一个 student
表:
id | name | age |
---|---|---|
1 | Alice | 20 |
2 | Bob | 22 |
3 | Charlie | 20 |
需求:将年龄为 20 的学生年龄改为 21。
UPDATE student
SET age = 21
WHERE age = 20;
结果:
id | name | age |
---|---|---|
1 | Alice | 21 |
2 | Bob | 22 |
3 | Charlie | 21 |
注意:
- 没有
WHERE
子句时,UPDATE student SET age = 21;
会将所有记录的age
改为 21。 - 建议先用
SELECT
查询确认受影响的记录。
2. DELETE:删除数据
DELETE
用于删除表中符合条件的记录,语法如下:
DELETE FROM table_name
WHERE condition;
- 作用:移除满足条件的记录。
- 注意:不带
WHERE
会删除表中所有记录。
示例
需求:删除年龄小于 22 的学生。
DELETE FROM student
WHERE age < 22;
结果:
id | name | age |
---|---|---|
2 | Bob | 22 |
注意:
- 删除后,表结构和索引保留,数据可通过事务回滚(如果在事务中)。
- 自增列计数器行为因存储引擎不同而异(详见下文)。
3. TRUNCATE:清空表
TRUNCATE
用于完全清空表中的数据,语法如下:
TRUNCATE TABLE table_name;
- 作用:删除表中所有记录,重置表到初始状态。
- 注意:无法指定条件,总是清空整个表。
示例
需求:清空 student
表。
TRUNCATE TABLE student;
结果:
- 表变为空,结构保留。
- 自增列计数器重置为 1。
二、TRUNCATE 与 DELETE 的区别
TRUNCATE
和 DELETE
都可以删除数据,但有显著差异。以下是详细对比:
特性 | DELETE | TRUNCATE |
---|---|---|
删除范围 | 可通过 WHERE 删除部分记录 | 删除整个表,无条件 |
速度 | 较慢,逐行删除,记录日志 | 更快,直接重建表结构 |
事务支持 | 支持事务,可回滚 | 不影响事务,无法回滚 |
自增列计数器 | 不重置,保留上次值 | 重置为 1 |
触发器 | 触发 DELETE 触发器 | 不触发触发器 |
外键约束 | 支持(受外键限制) | 不支持(表有外键时无法使用) |
日志记录 | 记录每行操作,占用日志空间 | 仅记录表结构变更,日志少 |
TRUNCATE 的优势
- 速度快:
TRUNCATE
直接重建表结构,效率高于逐行删除的DELETE
。 - 重置自增列:适合需要重置主键计数器的场景(如测试环境清空数据)。
- 不影响事务:执行后不记录逐行日志,节省日志空间。
- 低资源占用:适合快速清空大表。
DELETE 删除后的行为(重启数据库)
DELETE
删除数据后,自增列计数器的行为因存储引擎不同而异:
-
InnoDB
:
-
自增计数器存储在内存中。
-
重启数据库后,计数器从 1 重新开始。
-
示例:
CREATE TABLE test (id INT AUTO_INCREMENT PRIMARY KEY); INSERT INTO test VALUES (1), (2), (3); DELETE FROM test; INSERT INTO test VALUES (NULL); -- id = 1(重启后)
-
-
MyISAM
:
-
自增计数器存储在文件中,持久化。
-
重启数据库后,从上一个最大值继续。
-
示例:
DELETE FROM test; INSERT INTO test VALUES (NULL); -- id = 4(继续上一个值)
-
示例:DELETE vs TRUNCATE
-- 创建表
CREATE TABLE student (id INT AUTO_INCREMENT PRIMARY KEY,name VARCHAR(50),age INT
);
INSERT INTO student (name, age) VALUES ('Alice', 20), ('Bob', 22);-- DELETE
DELETE FROM student;
INSERT INTO student (name, age) VALUES ('Charlie', 21);
-- InnoDB 重启后:id = 1;MyISAM:id = 3-- TRUNCATE
TRUNCATE TABLE student;
INSERT INTO student (name, age) VALUES ('Charlie', 21);
-- 无论引擎:id = 1
三、DQL:数据查询语言
DQL 用于从数据库中检索数据,主要通过 SELECT
语句实现。以下讲解 SELECT
的核心用法,包括简单查询、特定字段查询、别名、去重和条件查询。
1. 简单单表查询
查询整个表
SELECT * FROM student;
-
作用:返回
student
表的所有列和记录。 -
示例输出
(假设表如上):
id | name | age 1 | Alice | 20 2 | Bob | 22
注意:*
适合快速查看,但生产环境中建议明确指定列以提高性能。
查询特定字段
SELECT name, age FROM student;
-
作用:只返回
name
和age
列。 -
示例输出
:
name | age Alice | 20 Bob | 22
给结果起别名
使用 AS
关键字为列或表达式指定别名:
SELECT name AS student_name, age AS student_age FROM student;
-
输出
:
student_name | student_age Alice | 20 Bob | 22
别名提高可读性,常用在复杂查询或报表生成中。
2. 函数:CONCAT
CONCAT
函数用于拼接字符串,语法如下:
SELECT CONCAT(column1, ' ', column2) AS result FROM table_name;
示例
需求:将学生的姓名和年龄拼接为一个字符串。
SELECT CONCAT(name, ' is ', age, ' years old') AS info FROM student;
输出:
info
Alice is 20 years old
Bob is 22 years old
注意:
- 不同数据库对
CONCAT
的支持略有差异(如 MySQL 支持多参数,SQL Server 使用+
)。 - 可结合其他函数(如
CAST
)处理非字符串类型。
3. 去重:DISTINCT
DISTINCT
用于去除查询结果中的重复行,语法如下:
SELECT DISTINCT column1, column2 FROM table_name;
示例
需求:查询所有不同的年龄。
SELECT DISTINCT age FROM student;
假设数据:
id | name | age |
---|---|---|
1 | Alice | 20 |
2 | Bob | 22 |
3 | Charlie | 20 |
输出:
age
20
22
注意:
DISTINCT
作用于整行(多列时考虑组合)。- 对性能有一定影响,尽量在必要时使用。
4. WHERE 条件子句
WHERE
用于过滤满足条件的记录,语法如下:
SELECT column1, column2
FROM table_name
WHERE condition;
示例
需求:查询年龄大于 20 的学生。
SELECT name, age
FROM student
WHERE age > 20;
输出:
name | age
Bob | 22
常见条件:
- 比较:
=
,>
,<
,>=
,<=
,!=
。 - 逻辑:
AND
,OR
,NOT
。 - 范围:
BETWEEN ... AND ...
。 - 集合:
IN (value1, value2)
。 - 模糊匹配:
LIKE '%pattern%'
。
综合示例
需求:查询年龄为 20 或 22 的学生,拼接姓名和年龄,去重后显示。
SELECT DISTINCT CONCAT(name, ' is ', age) AS info
FROM student
WHERE age IN (20, 22);
输出:
info
Alice is 20
Bob is 22
Charlie is 20
四、实际应用场景
- 数据清理:
- 使用
DELETE
移除无效记录(如WHERE created_date < '2020-01-01'
)。 - 使用
TRUNCATE
重置测试环境数据。
- 使用
- 数据更新:
UPDATE
批量修改用户信息(如SET status = 'active' WHERE last_login > '2023-01-01'
)。
- 报表生成:
SELECT
结合CONCAT
和DISTINCT
生成用户统计报表。- 使用
WHERE
过滤特定条件的数据。
五、注意事项与优化技巧
- DML 操作:
- 事务管理:
DELETE
和UPDATE
应在事务中执行,确保可回滚。 - 日志监控:
DELETE
操作可能导致日志文件过大,定期清理。 - 备份:执行
TRUNCATE
前备份数据,因无法回滚。
- 事务管理:
- DQL 查询:
- 索引优化:为
WHERE
条件中的列建立索引,提高查询效率。 - 避免
SELECT \*
:明确指定列,减少不必要的数据传输。 - 去重性能:
DISTINCT
可能影响性能,优先考虑业务逻辑去重。
- 索引优化:为
- 存储引擎选择:
- InnoDB:适合事务密集场景,自增列需注意重启行为。
- MyISAM:适合读多写少场景,自增列更稳定。
六、总结
DML 和 DQL 是数据库操作的核心组成部分:
- DML(
UPDATE
,DELETE
,TRUNCATE
)用于修改和删除数据,TRUNCATE
适合快速清空表,DELETE
提供更灵活的条件删除。 - DQL(
SELECT
)通过WHERE
、DISTINCT
、CONCAT
等功能实现精确查询,满足多样化需求。
通过本文的讲解和示例,你应该能熟练掌握这些操作,并在实际项目中灵活运用。如果有更多疑问或高级用法需求,欢迎在评论区交流!