DELETE数据没有了,看看SQL删除语句执行过程
SQL中删除数据或对象的语句主要有DELETE、TRUNCATE和DROP,三者均可“删除”操作,但作用对象、范围和底层机制不同。我们由简到繁,层层递进对比介绍。简单说:DELETE是逻辑删除,TRUNCATE是物理删除,DROP是元数据删除。通俗说:DELETE:删除表中符合条件的记录(可删部分或全部),保留表结构,操作可回滚;TRUNCATE:清空表中所有记录,保留表结构,速度快,操作通常不可回滚;DROP:删除整个表(包括结构、数据、索引等),操作不可撤销。专业说:DELETE:属于数据操作语言(DML),作用于表中的“记录”,可通过条件筛选删除部分数据,也可删除全表数据(保留表结构);TRUNCATE:属于数据定义语言(DDL),作用于表的“数据”,仅用于清空全表数据,保留表结构、约束、索引等元数据;DROP:
属于数据定义语言(DDL),作用于“整个表”,删除表的所有数据、结构、索引、约束等,是对表对象的彻底移除,此外DROP还可作用于数据库、索引、视图等对象(如:DROP DATABASE db_name,DROP INDEX idx_name)。如果还是很迷糊,那么下面我们一起来仔细拆解:
一、基础语法
1、DELETE语句
DELETE FROM 表名
[WHERE 条件]; -- 可选,用于指定删除的记录范围
语法解析:
-
DELETE FROM 表名:固定开头,声明要删除数据的表。 -
WHERE 条件:可选子句,通过条件(如:id=1、age>30)筛选需删除的记录。若省略,将删除表中所有记录。
扩展语法:
(1)多表删除
-- 多表删除
DELETE 表1别名, 表2别名
FROM 表1 表1别名
JOIN 表2 表2别名 ON 连接条件
WHERE 筛选条件; -- 同时删除多表中满足条件的记录
(2)行数限制
-- 行数限制
DELETE FROM 表名
ORDER BY 字段 [ASC/DESC] -- 按排序删除(如:限制删除行数)
LIMIT 行数; -- MySQL/SQLite限制删除行数
2、TRUNCATE语句
TRUNCATE TABLE 表名; -- 必须指定TABLE关键字(部分数据库可省略,但建议保留)
语法解析:
-
TRUNCATE TABLE:固定开头,声明要清空数据的表。 -
无 WHERE子句,只能清空全表数据,无法筛选部分记录。
3、DROP语句
DROP TABLE 表名; -- 删除指定表
语法解析:
-
DROP TABLE:固定开头,声明要删除的表对象。 -
执行后表的所有元数据(结构、索引等)和数据均被删除。
扩展语法:
(1)删除多个表
DROP TABLE 表1, 表2, ...; -- 同时删除多个表,用逗号分隔
(2)防错机制
DROP TABLE [IF EXISTS] 表名; -- 防止表不存在时报错(MySQL/PostgreSQL等支持)
二、执行过程
1、DELETE语句执行过程
(1)解析条件:数据库引擎先解析WHERE子句(若有),确定需删除的记录行。
(2)事务准备:开启事务(隐式或显式),将待删除记录的旧值写入回滚日志(用于事务回滚)。
(3)标记删除:对于InnoDB引擎,并非直接物理删除数据,而是在记录上标记“删除标识”(逻辑删除),使其在查询时被过滤。
(4)索引维护:DELETE会逐行删除并维护索引(如:B + 树索引),因此删除大量数据时可能导致索引碎片;而TRUNCATE直接清空表,索引会被重置(无碎片),这也是TRUNCATE速度更快的原因之一。
(5)触发触发器:若表上定义了DELETE触发器(如:删除前记录日志),会自动执行触发器逻辑。
(6)事务提交/回滚:若执行COMMIT,删除生效;若执行ROLLBACK,回滚日志恢复数据。
2、TRUNCATE语句执行过程
(1)元数据锁定:锁定表的元数据,阻止其他会话对表进行读写操作。
(2)跳过事务逻辑:不写入回滚日志,直接释放数据页(物理删除数据)。
(3)重置存储结构:
-
MyISAM引擎:重置自增列( AUTO_INCREMENT)为1,释放表空间。 -
InnoDB引擎:保留表结构,重置自增列,释放数据页(表空间大小变为初始值)。注意:若表中存在外键约束, TRUNCATE会失败(需先删除外键或使用CASCADE),此时自增列不会被重置。
(4)立即生效:操作不可逆,无事务提交/回滚环节。
3、DROP语句执行过程
(1)依赖检查:检查是否有视图、外键等依赖该表,部分数据库(如:MySQL)允许强制删除(需加CASCADE)。
(2)元数据删除:从系统表中移除该表的元数据(表结构、索引信息等)。
(3)物理空间释放:删除表对应的磁盘文件(如:InnoDB的 .ibd 文件、MyISAM的 .MYD 和 .MYI 文件)。
(4)依赖失效:依赖该表的存储过程、函数等保留但变为无效状态。
三、模拟示例
环境说明:
-
数据库:MySQL 8.0 -
表名: students(InnoDB引擎) -
初始数据: id(自增) name age 1 Alice 18 2 Bob 20 3 Charlie 22
1、DELETE语句示例
示例1:删除指定条件的记录
-- 删除age=20的记录
DELETE FROM students
WHERE age = 20;
执行后查询结果(SELECT * FROM students;):
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
示例2:删除全表数据(保留结构)
-- 省略WHERE子句,删除所有记录
DELETE FROM students;
执行后查询结果:表中无数据,但表结构仍存在(可通过DESC students;查看结构)。
-
自增列 id:下次插入数据时从4开始(因InnoDB中DELETE不重置自增)。
示例3:分批删除(避免大事务锁表)
-- 每次删除1000条,直到完成
DELETE FROM students
WHERE id < 100000
LIMIT 1000; -- MySQL分批删除
2、TRUNCATE语句示例
-- 清空students表数据
TRUNCATE TABLE students;
执行后查询结果:表中无数据,表结构保留。
-
自增列 id:下次插入数据时从1开始(InnoDB中TRUNCATE重置自增)。 -
磁盘空间:表文件大小显著减小(释放原数据占用的空间)。
3、DROP语句示例
-- 删除students表
DROP TABLE students;
执行后结果:
-
执行 SELECT * FROM students;,报错:Table 'test.students' doesn't exist(表已不存在)。 -
执行 DESC students;,报错:同上,表结构已删除。
四、DELETE、TRUNCATE和DROP区别
|
|
|
|
|
|---|---|---|---|
| 操作对象 |
|
|
|
| 语言类型 |
|
|
|
| 事务支持 |
|
|
|
| 触发器触发 |
|
|
|
| 自增列重置 |
|
|
|
| 磁盘空间释放 |
OPTIMIZE TABLE) |
|
|
| 执行速度 |
|
|
|
| 条件筛选 |
|
|
|
说明:TRUNCATE是否可回滚取决于数据库实现,应按具体数据库说明。
五、注意事项
1、DELETE语句注意事项
-
谨慎省略WHERE:删除全表数据时, DELETE比TRUNCATE慢(需逐行写回滚日志),且不释放空间,建议优先用TRUNCATE。 -
事务隔离:在高并发场景, DELETE可能导致行级锁长时间持有,引发性能问题,需合理控制事务范围。 -
触发器影响:若表有 DELETE触发器,需确认触发器逻辑是否会导致意外结果(如:级联删除其他表数据)。 -
大表删除性能:删除海量数据时,建议分批次执行(如: DELETE ... WHERE id<1000 LIMIT 1000)避免长事务锁表。 -
主从复制:若启用主从复制, WHERE条件中避免非确定性函数(如:RAND())。
2、TRUNCATE语句注意事项
-
权限要求:需 DROP权限(因本质是DDL操作),普通用户可能无权限执行。 -
外键约束:若表被其他表通过外键引用, TRUNCATE会失败(需先删除外键或禁用约束)。 -
数据恢复:操作不可逆,需提前备份重要数据(可通过 mysqldump等工具备份)。 -
Oracle差异:Oracle中 TRUNCATE会立即释放空间(MySQL InnoDB需重启后释放)。 -
权限细化:SQL Server要求 ALTER TABLE权限而非DROP。注意:SQL Server中,若表被外键引用,TRUNCATE会失败(即使有ALTER TABLE权限),需先删除外键约束或使用DROP TABLE CASCADE(SQL Server 2016+)。
3、DROP语句注意事项
-
依赖检查:删除表前需确认是否有视图、存储过程依赖该表,避免导致依赖对象失效。 -
生产环境谨慎操作:建议先执行 SELECT COUNT(*)确认表数据,或通过RENAME TABLE临时重命名表(验证无问题后再删除)。 -
分区表处理:删除分区表时, DROP TABLE会删除所有分区及数据,若需保留部分分区,应使用ALTER TABLE DROP PARTITION。 -
存储过程失效:依赖该表的存储过程/函数将变为 INVALID状态(需重新编译)。 -
回收站机制: -
Oracle: DROP TABLE默认进入回收站(RECYCLEBIN),可用FLASHBACK TABLE恢复。 -
SQL Server:无原生回收站,需依赖备份恢复。SQL Server可通过备份恢复或使用时态表( Temporal Tables)实现类似功能。
-
六、不同数据库实现差异
|
|
|
|
|
|---|---|---|---|
| TRUNCATE回滚 |
|
|
|
| DROP回收站 |
|
PURGE彻底删除) |
|
| DELETE性能优化 |
LIMIT分批提交 |
ROWNUM
|
TOP(n)
|
| 外键约束处理 |
|
|
DROP TABLE CASCADE |
说明:SQLite不支持
TRUNCATE,SQLite中TRUNCATE实际使用DELETE FROM table实现(自增列不重置)。
七、使用(适用)场景
-
DELETE:适用于需筛选删除部分数据、需事务回滚或触发触发器的场景。 -
TRUNCATE:适用于快速清空全表数据(保留结构)、需释放空间的场景。 -
DROP:适用于彻底删除表(包括结构)的场景,需格外谨慎。 -
生产环境优先考虑 TRUNCATE释放空间与DROP TABLE IF EXISTS防错机制。 -
跨数据库开发时需特别注意回收站机制、自增列重置、外键约束的差异。
现在的实际场景中,数据库的安全保障与权限管理,都做得非常到位。一般情况下,应用程序连接数据库的账号作为应用角色,仅被授予 SELECT、INSERT、UPDATE、DELETE 等数据操作权限(DML),禁止授予 DROP、TRUNCATE、ALTER 等 DDL 权限。但我们普通打工人,手一滑DELETE数据没有了,也是不可原谅的。数据这东西,安全与合规,我们普通分析师,始终要如履薄冰。在实际开发中,我们需根据业务需求(是否保留表结构、是否需要回滚、执行效率要求等)选择合适的语句,并始终做好数据备份,避免误操作导致数据丢失。
版权保护: 本文由 绿茶加糖-郭保升 原创,转载请保留链接: https://www.guobaosheng.com/shujuku/394.html
