今天我们要搞定你新知识库里另一个重要的砖头——数据更新。来看看在PostgreSQL里怎么用 UPDATE 命令改已有的信息。为啥这很重要?因为现实生活里的数据不是一成不变的。比如你朋友换了手机号,或者学生换了班——你肯定想把这些信息在数据库里也改一下。
比如你高中暗恋的Svetka Sokolova突然变成了Svetka Khachaturyan(生活嘛,就是这样),这就得在你的数据库里改一下。需要更新数据的场景其实挺多的:
- 修正记录里的错误。
- 更新信息(搬家、状态变了啥的)。
- 批量改数据,比如给员工涨工资。
数据更新就是在不加新记录的情况下,把表里一行或多行的某些列的值改掉。
UPDATE 命令的语法
PostgreSQL里的 UPDATE 命令语法其实挺直观的。来看下结构:
UPDATE 表名
SET 列1 = 值1,
列2 = 值2
WHERE 条件;
解释一下:
表名:你要改的表的名字。SET 列 = 值:指定要改哪个列,改成啥值。WHERE 条件:条件,指定哪些行要被更新(这个超重要,不然全表都改了)。
关键点:如果你忘了加 WHERE(或者写错了),你改的会是表里的所有行。后果很严重。
例子:改学生的名字
假设我们有个 students 表,里面有 id、name、email 这几列。我们想把 id = 1 的学生名字改成 "Maria Chi"。
UPDATE students
SET name = 'Maria Chi'
WHERE id = 1;
这条命令会找到 id = 1 的那行,把 name 列改成新值。很简单吧?
更新多列
有时候你得一次改一条记录里的好几个值。比如学生不仅改了名字,还换了邮箱。这样写:
UPDATE students
SET name = 'Otto Lin',
email = 'otto.lin@example.com'
WHERE id = 2;
这里我们同时更新了 name 和 email,针对 id = 2 的学生。PostgreSQL支持在 SET 里用逗号分隔写多个 列=值。
更新多行
如果你要一次改多行数据怎么办?比如你想把一组学生转到新班级。可以根据某个条件批量更新。假设有个 group_number 字段,我们要把所有 group_number = 101 的学生转到 202 班:
UPDATE students
SET group_number = 202
WHERE group_number = 101;
这条命令会把所有 group_number 是 101 的行都改成 202。
5. WHERE 条件:一定要小心!
前面说过,WHERE 就是你的救命稻草。没有它,整张表的所有行都会被改。比如下面这条命令会把所有学生的班级都改了,不只是101班。这绝对不是你想要的:
UPDATE students
SET group_number = 202;
拜托,每次都加上 WHERE,不然一不小心数据就毁了。宁可多加点保险。
把 UPDATE 命令想象成改表的列,不是改行。它的目标是给某一列的所有单元格赋值。只有加了 WHERE,才只改部分行。
基于另一张表的数据更新
有时候我们不只是“手动填个值”,而是用表B的数据来更新表A。这种需求很常见——比如有的表存计算结果,另一个表存用户资料。
假设我们有 students 表,要用 payments 表里的 due_amount 字段来更新 students 里的 debt。每条 students 记录通过 student_id 和 payments 关联。
语法像这样:
UPDATE students
SET debt = payments.due_amount
FROM payments
WHERE students.id = payments.student_id;
发生了什么:
- PostgreSQL 用
FROM payments作为数据来源。 - 通过
WHERE条件把两表的行关联起来。 - 只更新那些在
payments里有对应记录的students行。
注意: 这个 UPDATE ... FROM 其实底层就是个JOIN,只是没写 JOIN 关键字。
其实底层就是个隐式JOIN。大概像这样:
UPDATE students
SET debt = p.due_amount
FROM payments p
JOIN students s ON s.id = p.student_id
WHERE students.id = p.student_id;
怎么预览会被更新的内容
在你执行 UPDATE 之前,最好先看看到底会改哪些内容。可以用类似的 SELECT 语句:
SELECT
students.id,
students.name,
students.debt AS old_debt,
payments.due_amount AS new_debt
FROM students
JOIN payments ON students.id = payments.student_id;
结果会显示:
- 原来的欠款值(
old_debt); - 新值,就是
payments表里的new_debt。
这样可以先验证下逻辑对不对,再决定要不要真的覆盖数据。
可能遇到的坑
- 如果
payments里一个学生有多条记录,UPDATE会报错:more than one row returned。要么用聚合函数(MAX、SUM、LIMIT 1),要么保证payments里的student_id是唯一的。 - 别忘了,
UPDATE ... FROM是PostgreSQL的特性,别的数据库(比如MySQL)可能不支持。
实用例子
例子1:改学生状态
比如学生完成了课程就变成“毕业生”。我们有个 status 列。要把 completed_course = true 的学生状态都改成“毕业生”:
UPDATE students
SET status = '毕业生'
WHERE completed_course = true;
例子2:给员工涨工资
如果你有个 employees 表,想给销售部的所有人涨10%工资:
UPDATE employees
SET salary = salary * 1.10
WHERE department = 'Sales';
这里我们直接在 SET 里用数学运算,批量改数据很方便。
例子3:条件更新
有时候要根据条件来更新数据。比如工资低于50,000的员工涨20%,高于的涨10%:
UPDATE employees
SET salary = CASE
WHEN salary < 50000 THEN salary * 1.20
ELSE salary * 1.10
END;
这条命令用 CASE 结构,根据 salary 的值决定怎么更新。
用 UPDATE 时常见的错误
你大概已经猜到,最常见的错误是什么?没错,就是漏写 WHERE。想象下:你有1万员工的数据库,一不小心给所有人都涨了工资。虽然员工们会很开心,但你老板可能就不高兴了。
另一个常见错误——更新错了列。每次都要再三确认你到底在写什么、写到哪。先用 SELECT 查查再 UPDATE,能帮你省下不少麻烦。
GO TO FULL VERSION