跳到主要内容

PostgreSQL DELETE 实用教程(常用语法 + 安全删除 + 易错点)

DELETE 基本语法​

DELETE FROM 表名
WHERE 条件;
-- 删除 id = 10 的记录
DELETE FROM users WHERE id = 10;
-- 删除状态为 0 且 30 天前创建的记录
DELETE FROM users WHERE status = 0 AND create_time < NOW() - INTERVAL '30 days';
注意

高危:没有 WHERE 的 DELETE 会删除整个表中的所有数据。必须先确认条件,并尽量先用 SELECT 验证目标结果。

DELETE 也能配合 RETURNING​

-- 删除后返回被删记录
DELETE FROM users WHERE id = 100 RETURNING id, name, status;

RETURNING 在 PostgreSQL 中非常实用,用于审计、日志记录和回滚前确认。

信息

如果未命中任何行,RETURNING 返回空结果集,且受影响行数为 0。

DELETE ... USING:关联表删除​

当删除条件依赖其他表时,可通过 USING 关联过滤。

-- 删除与某个用户无关的旧日志
DELETE FROM user_log ul USING users u WHERE ul.user_id = u.id AND u.deleted_at IS NOT NULL;
注意

易错:如果 DELETE 语句里有多张表,确保目标表和关联表的过滤条件明确,不要混淆“删除目标表”与“被关联表”。

DELETE + 子查询​

-- 删除没有订单的用户
DELETE FROM users u WHERE NOT EXISTS ( SELECT 1 FROM orders o WHERE o.user_id = u.id );
信息

对于“查找没有关联记录”的场景,通常优先使用 NOT EXISTS,比 NOT IN 更稳定,也规避了 NULL 造成的隐性问题。

删除前先看数据​

-- 先查看大概率要删的记录
SELECT * FROM users WHERE status = 0 AND create_time < NOW() - INTERVAL '365 days';
-- 再执行删除
DELETE FROM users WHERE status = 0 AND create_time < NOW() - INTERVAL '365 days';
注意

生产环境中删除、更新、修改都应该“先读后写”:用 SELECT 先确认数据范围,确保条件命中的是想删的那批记录。

事务与回滚​

BEGIN;
DELETE FROM user_log WHERE created_at < NOW() - INTERVAL '180 days';
-- 确认行数正确后再提交,或者执行
ROLLBACK 取消删除 COMMIT;
信息

批量删除往往伴随大量行锁与事务日志;在大表上要避免一次删太多,并考虑使用分批删除。

TRUNCATE 与 DELETE 的区别​

操作特点适用场景
DELETE按条件删除,可回滚,逐行删除删除少量/按条件删除
TRUNCATE快速清空表,不能带 WHERE 条件,通常更快彻底清空整表,通常需要谨慎
-- 清空整个表(谨慎)
TRUNCATE TABLE temp_data;
注意

TRUNCATE 不是条件删除,不可用于“删除部分数据”,而且通常不能在事务中和某些引用关系下随意使用。

DELETE 常见坑​

  • 1. 忘记 WHERE,删除整表;要先 SELECT 复核。
  • 2. NOT IN 子查询里出现 NULL 时容易“误删不删都不对”;优先 NOT EXISTS。
  • 3. 大批量删除时没有分批,可能锁表很久,影响业务。
  • 4. 误删引用数据时,外键约束会阻止或触发级联行为,需要先设计好删除策略。

总结:DELETE 高频易错清单​

  • 1. 永远先 SELECT,再 DELETE。
  • 2. 任何大批量删除都应考虑事务和分批策略。
  • 3. 关联删除用 DELETE ... USING 或子查询,条件要清晰。
  • 4. RETURNING 可用于审计和回滚前确认。
  • 5. TRUNCATE 适合清空整表,不适合按条件删除。