DELETE 删除数据
DELETE 语句用于从表中删除行。本章将详细介绍 DELETE 语句的各种用法。
基本语法
sql
DELETE FROM table_name
WHERE condition;删除单行数据
sql
-- 根据 ID 删除用户
DELETE FROM users
WHERE id = 1;删除多行数据
sql
-- 删除所有非活跃用户
DELETE FROM users
WHERE status = 'inactive';使用子查询删除
sql
-- 删除没有订单的用户
DELETE FROM users
WHERE id NOT IN (
SELECT DISTINCT user_id FROM orders
);使用 JOIN 删除
sql
-- MySQL 语法
DELETE u
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE o.id IS NULL;删除所有行
sql
-- 删除所有数据(保留表结构)
DELETE FROM users;
-- 更快的替代方案:TRUNCATE
TRUNCATE TABLE users;TRUNCATE vs DELETE
| 特性 | DELETE | TRUNCATE |
|---|---|---|
| 速度 | 较慢 | 较快 |
| WHERE 子句 | 支持 | 不支持 |
| 回滚 | 可以 | 不可以(大多数数据库) |
| 触发器 | 触发 | 不触发 |
| 自增值 | 保持 | 重置为 1 |
实战示例
删除旧记录
sql
-- 删除 1 年前的订单
DELETE FROM orders
WHERE order_date < DATE_SUB(NOW(), INTERVAL 1 YEAR);批量删除
sql
-- 分批删除避免锁表
DELETE FROM logs
WHERE created_at < '2023-01-01'
LIMIT 1000;使用事务删除
sql
START TRANSACTION;
-- 删除用户
DELETE FROM users WHERE id = 1;
-- 删除相关数据
DELETE FROM user_profiles WHERE user_id = 1;
DELETE FROM orders WHERE user_id = 1;
COMMIT;级联删除
sql
-- 外键设置级联删除
CREATE TABLE orders (
id INT PRIMARY KEY,
user_id INT,
FOREIGN KEY (user_id) REFERENCES users(id)
ON DELETE CASCADE
);
-- 删除用户时自动删除其订单
DELETE FROM users WHERE id = 1;软删除
sql
-- 不真正删除,而是标记为已删除
UPDATE users
SET deleted_at = NOW(), status = 'deleted'
WHERE id = 1;
-- 查询时只显示未删除的用户
SELECT * FROM users WHERE deleted_at IS NULL;常见错误
错误 1:忘记 WHERE 子句
sql
-- 危险:删除所有行!
DELETE FROM users;
-- 正确:使用 WHERE 子句
DELETE FROM users WHERE id = 1;错误 2:外键约束
sql
-- 错误:由于外键无法删除
DELETE FROM users WHERE id = 1;
-- 错误:无法删除或更新父行
-- 解决方案 1:先删除子记录
DELETE FROM orders WHERE user_id = 1;
DELETE FROM users WHERE id = 1;
-- 解决方案 2:使用级联删除最佳实践
- 始终使用 WHERE 子句
- 先用 SELECT 测试条件
- 使用事务处理相关删除
- 批量删除前备份数据
- 重要数据考虑软删除
- 使用 LIMIT 分批删除
性能优化
sql
-- 为 WHERE 列创建索引
CREATE INDEX idx_status ON users(status);
-- 批量删除
DELETE FROM logs
WHERE created_at < '2023-01-01'
LIMIT 10000;小结
- DELETE FROM:删除行
- WHERE 子句:指定要删除的行
- TRUNCATE:快速删除所有行
- 级联删除:自动删除相关数据
- 软删除:标记为已删除而不是真正删除
下一步: 学习 ALTER 修改表