首页 / MySQL 入门教程 / 删除数据 DELETE 与 TRUNCATE

MySQL 入门教程

删除数据 DELETE 与 TRUNCATE

本教程共 46 篇 · 第 18 篇 · 更新于 2026-07-30 · 约 10 分钟阅读

MySQLMySQL 入门教程DELETETRUNCATEDMLDELETE JOIN级联删除数据删除

18. 删除数据 DELETE 与 TRUNCATE

本节目标:学会删除表中的数据,掌握 DELETE 按条件删、DELETE JOIN 跨表删、TRUNCATE 清空整表三种方式,理解它们的核心区别和各自适用场景,并了解外键级联删除的工作原理。

18.1 DELETE:按条件删除

DELETE 用来删除表中的行。基本语法:

DELETE FROM 表名
WHERE 条件;

比如删除 id 为 5 的用户:

DELETE FROM users
WHERE id = 5;

执行后返回:

Query OK, 1 row affected (0.01 sec)

跟 UPDATE 一样,WHERE 是关键。忘了写 WHERE,整张表的数据全删光:

-- 危险!删除 users 表所有数据
DELETE FROM users;
Warning

和 UPDATE 一样,DELETE 不写 WHERE 就是全表删除。建议开启 --safe-updates 模式,强制要求 WHERE 条件。我之前见过一个同事在生产环境执行了无 WHERE 的 DELETE,几百万条数据瞬间清空,幸好有备份。

用 LIMIT 限制删除量

大批量删除时,可以分批删,避免长时间锁表:

-- 每次删 1000 条
DELETE FROM orders
WHERE status = 'expired'
LIMIT 1000;

反复执行直到返回 0 行即可。也可以配合 ORDER BY 控制删除顺序:

DELETE FROM orders
WHERE status = 'expired'
ORDER BY created_at ASC
LIMIT 1000;
Tip

删大表数据时,千万别一条 DELETE 删几十万行。分批删,每批 1000-5000 行,中间加个短暂 sleep,给数据库喘口气。

18.2 DELETE JOIN:跨表删除

跟 UPDATE JOIN 类似,DELETE 也能配合 JOIN,根据另一张表的条件来删除。

语法上需要指定从哪个表删:

DELETE o
FROM orders o
INNER JOIN users u ON o.user_id = u.id
WHERE u.age < 18;

这句话的意思是:删除所有”用户年龄小于 18”的订单。

注意 DELETE 后面的 o—它指定只删 orders 表的行,不删 users 表。

同时删多张表的行

如果你想在一次操作中同时删两张表的行,把两个表别名都写在 DELETE 后面:

DELETE o, u
FROM orders o
INNER JOIN users u ON o.user_id = u.id
WHERE u.username = '测试用户';

这会同时删掉”测试用户”的订单记录和用户记录。

Note

同时删多表时,JOIN 条件决定哪些行匹配。匹配到的行从各自表里删除,没匹配到的不受影响。用之前务必 SELECT 验证一下匹配结果,确认要删的就是这些。

18.3 TRUNCATE:清空整表

TRUNCATE 用来一次性删除表中的所有数据,速度比 DELETE FROM 表名 快得多:

TRUNCATE TABLE orders;

执行后,orders 表里的数据全部消失,但表结构(列、索引、约束)都还在。

为什么 TRUNCATE 比 DELETE 快?原理不同:

  • DELETE 逐行删除,每删一行都要记日志、检查约束,相当于逐行操作
  • TRUNCATE 直接释放数据页,不逐行操作,日志只记一条”清空了这张表”
Tip

清空测试数据时,用 TRUNCATE 比 DELETE 快几十倍。但记住,TRUNCATE 只能清整张表,不能加 WHERE 条件。

18.4 DELETE vs TRUNCATE 核心区别

这是面试常考的知识点,也是实际操作中必须分清的:

对比项DELETETRUNCATE
删除方式逐行删除直接释放数据页
速度慢(逐行记日志)快(只记一条日志)
WHERE 条件支持不支持
事务回滚可以回滚(在事务中)不可回滚(隐式提交)
自增计数器不重置重置为初始值
触发器触发(AFTER/BEFORE DELETE)不触发
返回删除行数返回 affected rows返回 0(不统计)
外键约束受外键约束检查若被外键引用则拒绝执行
权限需要 DELETE 权限需要 DROP 权限

几个关键点展开说明:

事务和回滚

DELETE 在事务中可以回滚:

BEGIN;
DELETE FROM users WHERE id = 1;
-- 发现删错了,回滚
ROLLBACK;
-- 数据又回来了

TRUNCATE 是隐式提交(auto-commit)的,执行后无法回滚:

BEGIN;
TRUNCATE TABLE orders;
ROLLBACK;
-- 数据回不来了!TRUNCATE 已经提交了
Warning

不要指望用事务来保护 TRUNCATE 操作。一旦执行,数据就真没了。用 TRUNCATE 前务必确认。

自增计数器

DELETE 删完数据后,自增列的计数器不会变。比如自增到 100,删了所有行,下次插入还是从 101 开始。

TRUNCATE 会把自增计数器重置回初始值(通常是 1):

-- DELETE 删完后
DELETE FROM users;
INSERT INTO users (username, email, age) VALUES ('新用户', 'new@example.com', 20);
-- 新行 id = 101(继续之前的计数)

-- TRUNCATE 清空后
TRUNCATE TABLE users;
INSERT INTO users (username, email, age) VALUES ('新用户', 'new@example.com', 20);
-- 新行 id = 1(重新开始)

外键约束

如果 orders 表有外键引用 users 表,对 users 表执行 TRUNCATE 会被拒绝:

ERROR 1701: Cannot truncate a table referenced in a foreign key constraint

这时候只能用 DELETE,或者先临时关闭外键检查(后面约束章节会讲)。

18.5 ON DELETE CASCADE:级联删除

建外键时可以指定 ON DELETE CASCADE,意思是”主表行被删时,自动删掉从表中关联的行”。

假设 orders 表的外键定义如下:

CREATE TABLE orders (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT,
    amount DECIMAL(10, 2),
    status VARCHAR(20),
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB;

加了 ON DELETE CASCADE 后,删 users 表的某个用户时,orders 表里该用户的所有订单会自动删除:

-- 删用户 id=3
DELETE FROM users WHERE id = 3;
-- orders 表中 user_id=3 的行也会自动被删掉
Note

级联删除很方便,但也有风险。删一个用户可能连锁删掉大量关联数据,有时这不是你想要的。如果只想保留订单但断开关联,用 ON DELETE SET NULL(把外键设为 NULL)更合适。外键策略的选择在约束章节会详细讲。

18.6 删除操作的常见陷阱

删了数据但空间没释放

InnoDB 存储引擎下,DELETE 删掉数据后,磁盘空间不会立即还给操作系统。数据页被标记为可复用,但文件大小不变。想要真正回收空间,可以执行:

OPTIMIZE TABLE orders;

但这会锁表一段时间,生产环境慎用。

删数据 vs 删表

别混淆 DELETE 和 DROP:

  • DELETE FROM 表名 — 删数据,表还在
  • DROP TABLE 表名 — 表结构和数据一起删,表没了
-- 只清空数据,表结构保留
DELETE FROM orders;

-- 连表带数据一起删
DROP TABLE orders;

软删除 vs 硬删除

实际开发中,很多场景不用真的 DELETE,而是”软删除”—加一个 deleted_at 列标记删除时间:

-- 软删除:标记为已删除
UPDATE users
SET deleted_at = NOW()
WHERE id = 5;

-- 查询时排除已删除的
SELECT * FROM users
WHERE deleted_at IS NULL;

软删除的好处是数据可以恢复,还能做审计追踪。代价是查询时总得记得加 WHERE deleted_at IS NULL

Tip

关键业务数据(用户、订单)建议软删除。日志、临时数据可以硬删除。根据业务场景选择,别一刀切。

18.7 小结

删除数据有三个工具:DELETE 按条件删、DELETE JOIN 跨表删、TRUNCATE 清空整表。记住 DELETE 可回滚可加条件但慢,TRUNCATE 快但不可回滚不可加条件。外键级联删除(ON DELETE CASCADE)能自动处理关联数据,但要谨慎使用。不管用哪种方式,删之前先 SELECT 确认,删之后有备份兜底。下一章开始进入查询主题,先从最基础的 SELECT 学起。