您好!欢迎访问家园网-www.jy.wang!

家园网

在sql中,TRUNCATE TABLE 和DELETE删除有什么区别呢

网络 作者:本站 点击:

SQL中 TRUNCATE TABLE 和 DELETE 的区别详解

这是一个非常经典的面试题,也是日常开发中容易混淆的地方。让我从多个角度详细对比两者的区别。


一、一图看懂核心区别

text

┌─────────────────────────────────────────────────────────────────────────┐
│                        原表(有100条数据)                               │
│  ┌─────────────────────────────────────────────────────────────────┐    │
│  │  第1行 │ 第2行 │ 第3行 │ ... │ 第100行                         │    │
│  └─────────────────────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────────────────────┘

                    DELETE FROM 表                    TRUNCATE TABLE 表
                           ↓                                    ↓
┌─────────────────────────────────────┐     ┌─────────────────────────────────────┐
│  逐行删除,每删一行都记录日志        │     │  一次性释放整个数据页                │
│  ┌─────────────────────────────┐    │     │  ┌─────────────────────────────┐    │
│  │ 第1行 → 删除 → 记录日志      │    │     │  │ 直接清空,不记录每行日志    │    │
│  │ 第2行 → 删除 → 记录日志      │    │     │  └─────────────────────────────┘    │
│  │ 第3行 → 删除 → 记录日志      │    │     └─────────────────────────────────────┘
│  │ ...                         │    │                       ↓
│  │ 第100行 → 删除 → 记录日志    │    │              表空了,但结构还在
│  └─────────────────────────────┘    │
└─────────────────────────────────────┘


二、词源角度

命令词源含义
DELETE拉丁语 deletus(毁掉、抹去)删除、抹掉(逐条记录)
TRUNCATE拉丁语 truncatus(截断、切掉)截断、砍掉(整块切掉)

词源对比

  • DELETE 来自 deletus,强调"抹掉"(逐条擦除)

  • TRUNCATE 来自 truncatus(同源词:truncate=截断),强调"切掉一端"(整块移除)


三、详细对比表

对比维度DELETETRUNCATE
词源拉丁语 deletus(抹去)拉丁语 truncatus(截断)
操作方式逐行删除一次性释放整个数据页
执行速度慢(需逐行处理)快(瞬间完成)
事务日志记录每一行的删除只记录数据页的释放
WHERE 条件✅ 支持❌ 不支持
触发器✅ 触发❌ 不触发
能否回滚✅ 可以(在事务内)⚠️ 可以(但需谨慎)
重置计数器❌ 不重置(自增列继续)✅ 重置(自增列从1开始)
锁级别行级锁表级锁
释放空间❌ 不释放(保留给后续插入)✅ 释放给操作系统

四、执行速度对比

我们用一个直观的比喻:

命令比喻速度
DELETE像用手一粒一粒捡起米粒非常慢
TRUNCATE像直接把整个碗倒扣在桌上瞬间完成

实际示例

sql

-- 假设表中有 1000 万条数据-- DELETE:可能需要几分钟甚至几十分钟DELETE FROM large_table;-- TRUNCATE:几乎瞬间完成(毫秒级)TRUNCATE TABLE large_table;


五、能否回滚的对比

DELETE 可以回滚

sql

BEGIN TRANSACTION;DELETE FROM employees WHERE dept_id = 10;-- 查看删除的数据还在(事务未提交)SELECT * FROM employees WHERE dept_id = 10;ROLLBACK;  -- 回滚后,数据全部恢复

TRUNCATE 也可以回滚(但容易被误解)

sql

BEGIN TRANSACTION;TRUNCATE TABLE employees;-- 表已经空了SELECT * FROM employees;  -- 返回 0 行ROLLBACK;  -- 回滚后,数据恢复!-- 注意:一旦 COMMIT,就无法恢复


六、使用场景建议

场景推荐命令原因
清空测试数据TRUNCATE速度快,重置自增列
删除部分数据DELETE支持 WHERE 条件
需要触发器执行DELETETRUNCATE 不触发触发器
需要记录每行日志DELETE可审计
重置自增列TRUNCATEDELETE 不会重置
释放磁盘空间TRUNCATEDELETE 不释放空间(SQL Server 需要收缩)

七、各数据库特有行为

数据库DELETETRUNCATE
MySQL正常自动重置自增;InnoDB 可回滚
SQL Server正常记录最少日志;无法触发触发器
Oracle正常不能回滚(除非在事务内);释放空间
PostgreSQL正常可回滚;重置自增;速度快

八、代码示例

DELETE 示例

sql

-- 删除部分数据DELETE FROM products WHERE price < 10;-- 删除所有数据(慢)DELETE FROM products;-- 带条件的删除DELETE FROM orders 
WHERE order_date < '2023-01-01';

TRUNCATE 示例

sql

-- 清空整个表(推荐)TRUNCATE TABLE products;-- 不能加 WHERE 条件TRUNCATE TABLE products WHERE price < 10;  -- ❌ 错误!-- 清空后,自增列重置TRUNCATE TABLE users;INSERT INTO users(name) VALUES('张三');  -- id 从 1 开始


九、总结表

问题DELETETRUNCATE
要删除全部数据吗?✅ 可以✅ 可以(最佳选择)
要删除部分数据吗?✅ 可以❌ 不可以
要速度快吗?❌ 慢✅ 极快
要触发触发器吗?✅ 触发❌ 不触发
要重置自增列吗?❌ 不重置✅ 重置
要释放磁盘空间吗?❌ 不释放✅ 释放
可以回滚吗?✅ 可以⚠️ 可以(在事务内)

一句话总结DELETE 像用手一粒一粒捡米,速度慢但可以按条件只删一部分;TRUNCATE 像直接倒扣碗,瞬间清空整张表。两者词源也印证了这一点:DELETE 来自拉丁语"抹去"(逐条擦除),TRUNCATE 来自拉丁语"截断"(一次性切掉)。日常开发中,如果确定要清空整个表且无需触发触发器,优先用 TRUNCATE;如需按条件删除或保留触发器逻辑,则用 DELETE


标签: