所有内容均为测试可用,真实
当前位置:绿茶加糖-郭保升 > 数据库资料 > 正文

DELETE数据没有了,看看SQL删除语句执行过程

SQL中删除数据或对象的语句主要有DELETETRUNCATEDROP,三者均可“删除”操作,但作用对象、范围和底层机制不同。我们由简到繁,层层递进对比介绍。简单说:DELETE逻辑删除TRUNCATE物理删除DROP元数据删除。通俗说:DELETE:删除表中符合条件的记录(可删部分或全部),保留表结构,操作可回滚;TRUNCATE:清空表中所有记录,保留表结构,速度快,操作通常不可回滚;DROP:删除整个表(包括结构、数据、索引等),操作不可撤销。专业说:DELETE:属于数据操作语言(DML),作用于表中的“记录”,可通过条件筛选删除部分数据,也可删除全表数据(保留表结构);TRUNCATE:属于数据定义语言(DDL),作用于表的“数据”,仅用于清空全表数据,保留表结构、约束、索引等元数据;DROP

属于数据定义语言(DDL),作用于“整个表”,删除表的所有数据、结构、索引、约束等,是对表对象的彻底移除,此外DROP还可作用于数据库、索引、视图等对象(如:DROP DATABASE db_nameDROP INDEX idx_name)。如果还是很迷糊,那么下面我们一起来仔细拆解:

一、基础语法

1、DELETE语句
DELETE FROM 表名 
[WHERE 条件]; -- 可选,用于指定删除的记录范围

语法解析:

  • DELETE FROM 表名:固定开头,声明要删除数据的表。
  • WHERE 条件:可选子句,通过条件(如:id=1age>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;):

id
name
age
1
Alice
18
3
Charlie
22

示例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;,报错:同上,表结构已删除。

四、DELETETRUNCATEDROP区别

 
DELETE
TRUNCATE
DROP
操作对象
表中的记录
表中的所有数据
整个表(数据+结构)
语言类型
DML
DDL
DDL
事务支持
支持(可回滚)
不支持(不可回滚)
不支持(不可回滚)
触发器触发
自增列重置
否(InnoDB)
无(表已删除)
磁盘空间释放
否(需OPTIMIZE TABLE
执行速度
慢(逐行删除,写日志)
快(直接释放数据页)
快(删除表文件)
条件筛选
支持(WHERE子句)
不支持(只能全表清空)
不支持

说明:TRUNCATE是否可回滚取决于数据库实现,应按具体数据库说明。

五、注意事项

1、DELETE语句注意事项
  • 谨慎省略WHERE:删除全表数据时,DELETETRUNCATE慢(需逐行写回滚日志),且不释放空间,建议优先用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)实现类似功能。

六、不同数据库实现差异

特性
MySQL
Oracle
SQL Server
TRUNCATE回滚
InnoDB不支持
不支持
不支持
DROP回收站
不支持
√ (需PURGE彻底删除)
×
DELETE性能优化
可用LIMIT分批提交
ROWNUM
伪列分批删除
TOP(n)
分批删除
外键约束处理
TRUNCATE需禁用外键约束
同MySQL
级联删除需DROP TABLE CASCADE

说明:SQLite不支持TRUNCATE,SQLite中TRUNCATE实际使用DELETE FROM table实现(自增列不重置)。

七、使用(适用)场景

  • DELETE:适用于需筛选删除部分数据、需事务回滚或触发触发器的场景。
  • TRUNCATE:适用于快速清空全表数据(保留结构)、需释放空间的场景。
  • DROP:适用于彻底删除表(包括结构)的场景,需格外谨慎。
  • 生产环境优先考虑TRUNCATE释放空间与DROP TABLE IF EXISTS防错机制。
  • 跨数据库开发时需特别注意回收站机制、自增列重置、外键约束的差异。

现在的实际场景中,数据库的安全保障与权限管理,都做得非常到位。一般情况下,应用程序连接数据库的账号作为应用角色,仅被授予 SELECTINSERTUPDATEDELETE 等数据操作权限(DML),禁止授予 DROPTRUNCATEALTER 等 DDL 权限。但我们普通打工人,手一滑DELETE数据没有了,也是不可原谅的。数据这东西,安全合规,我们普通分析师,始终要如履薄冰。在实际开发中,我们需根据业务需求(是否保留表结构、是否需要回滚、执行效率要求等)选择合适的语句,并始终做好数据备份,避免误操作导致数据丢失。

版权保护: 本文由 绿茶加糖-郭保升 原创,转载请保留链接: https://www.guobaosheng.com/shujuku/394.html