删除可不是随便点个按钮那么简单,这其实是一门艺术!你得删得刚刚好,别多删一条(不小心删掉的数据,晚上做梦都能吓醒你)。今天我们就来学学怎么优雅又靠谱地删数据!
删除数据,就是把表里不再符合业务逻辑或者系统需求的某些行给移除掉。比如,你要删掉已经毕业的学生,或者那些,嗯,严重违反校规的同学。又或者,你想清理一下表,只留下最新的数据。
删除操作一般用在这些场景:
- 删掉那些已经不活跃的用户数据。
- 清理表里的临时记录。
- 去除重复的数据。
- 根据业务逻辑删掉过时的记录。
DELETE 命令的语法
我们用 DELETE 命令来删数据。基本语法长这样:
DELETE FROM 表名
WHERE 条件;
主要部分:
DELETE FROM—— 关键字,告诉 SQL 要从哪个表里删行。- 表名 —— 你要删数据的表的名字。
WHERE 条件—— 用来筛选要删哪些行的条件。你可以用各种比较运算符、逻辑运算符(AND、OR、NOT),甚至还能用子查询。
举个例子:假设我们有个 students 表,要删掉 id = 5 的学生:
DELETE FROM students
WHERE id = 5;
这个语句会把 students 表里 id(学生编号)等于 5 的那一行删掉。
注意: 如果你忘了写 WHERE 条件,PostgreSQL 会把表里的所有行都删掉。这种失误在生产环境里简直灾难级别,千万小心!
删除表里的所有行
如果你想把表里的所有行都删掉,可以直接写不带 WHERE 的语句,比如:
DELETE FROM students;
这个语句会把 所有记录 都从 students 表里删掉。但表的结构还在,只是内容变空了。
替代方案:TRUNCATE
要删掉表里的所有行,还可以用 TRUNCATE 命令。它比 DELETE 快,因为不会一行一行地写日志。比如:
TRUNCATE TABLE students;
DELETE 和 TRUNCATE 的区别:
DELETE会把每一行的删除都写进事务日志,所以可以回滚。TRUNCATE不支持WHERE条件,也不会一条条记录日志,所以更快,但没那么灵活。
如果你只是想清空表,TRUNCATE 很棒。但如果你只想删部分数据,或者想要能回滚,还是用 DELETE 更合适。
按复杂条件删除数据
DELETE 的条件不仅可以很简单,还能很复杂,比如用逻辑运算符(AND、OR、NOT)或者子查询。来看例子。
例子1:删除多条记录 删掉所有年龄大于30岁且最近3个月没来上课的学生:
DELETE FROM students
WHERE age > 30 AND last_attendance_date < (CURRENT_DATE - INTERVAL '3 months');
这个语句只会删掉同时满足这两个条件的学生。
例子2:用子查询删除
假设有个 failed_students 表,里面存着因学业不及格被开除的学生 id。我们要把这些学生从 students 主表里删掉:
DELETE FROM students
WHERE id IN (SELECT student_id FROM failed_students);
这里子查询会返回 failed_students 表里的所有学生 id,DELETE 会把 students 表里对应的行删掉。
小建议
在你删数据之前,先写个 SELECT,查查你想删的内容。确认没问题后,把 SELECT 换成 DELETE,这样删掉的就是你刚查到的那些行。
实战例子
假如 id = 7 的学生要转学了,我们要把他的信息从表里删掉:
DELETE FROM students
WHERE id = 7;
执行完后查查表,确认这条记录真的被删了:
SELECT * FROM students WHERE id = 7;
如果查不到 id = 7 的记录,说明删除成功。
警告和常见错误
忘记写 WHERE 条件
用 DELETE 时最常见的坑就是忘了写 WHERE 条件。这样会把表里所有行都删掉,后果很严重。一定要在执行前检查你的语句!
比如这种粗心导致的事故:
DELETE FROM students;
-- 错误!所有学生都被删了。
为了避免这种事,建议你在执行 DELETE 前,先用 SELECT 测试一下 WHERE 条件。比如:
SELECT * FROM students WHERE id = 5;
如果查出来的结果没问题,再放心地用 DELETE。
删除有关联的数据
如果表里有外键(FOREIGN KEY),删数据时可能会报错。比如,学生在 enrollments 表里有选课记录,PostgreSQL 就不让你直接把他从 students 表里删掉。
解决办法有:
- 建外键时加上
ON DELETE CASCADE,让删除自动级联。 - 先手动删掉关联表里的记录,再删主表里的。
手动删除关联数据的例子:
-- 先从 enrollments 表里删掉学生 5 的记录
DELETE FROM enrollments
WHERE student_id = 5;
-- 再删掉学生 5 本人
DELETE FROM students
WHERE id = 5;
用事务删除
做重要的删除操作时,建议用事务,这样出错可以回滚。
事务删除的例子:
BEGIN;
DELETE FROM students
WHERE id = 42;
-- 检查结果
SELECT * FROM students WHERE id = 42;
-- 没问题就提交
COMMIT;
-- 有问题就回滚
-- ROLLBACK;
事务的更多内容我们后面讲座再聊 :P
GO TO FULL VERSION