update语句支持同表字段赋值,语法为set target_field = source_field where条件;必须加where防全表误改,source_field为null时target_field也置null,跨表需join或from关联。

UPDATE语句中直接用字段名赋值
可以直接在 SET 子句里把一个字段的值赋给另一个字段,前提是两字段类型兼容(比如都是字符串或都是数字),且在同一张表里操作。
- 语法就是:
UPDATE table_name SET target_field = source_field WHERE condition; - 不加
WHERE会整表更新,极易误操作——务必确认条件是否精确匹配 - 如果
source_field为NULL,目标字段也会被设成NULL,不是保持原值 - MySQL、PostgreSQL、SQL Server 都支持这种写法;SQLite 同样可用,但注意它不校验类型,可能隐式转换出意外结果
跨表更新时用JOIN或子查询
当源字段和目标字段不在同一张表时,不能直接写 SET a.x = b.y,必须关联查询。不同数据库写法略有差异。
- MySQL 支持
UPDATE ... JOIN:UPDATE t1 JOIN t2 ON t1.id = t2.t1_id SET t1.name = t2.fullname; - PostgreSQL 要用
FROM子句:UPDATE t1 SET name = t2.fullname FROM t2 WHERE t1.id = t2.t1_id; - SQL Server 类似 PostgreSQL,但语法是
UPDATE t1 SET t1.name = t2.fullname FROM t1 INNER JOIN t2 ON t1.id = t2.t1_id; - 避免用相关子查询(
SET x = (SELECT y FROM ... WHERE ...)),性能差,且若子查询返回多行会报错Subquery returns more than 1 row
更新前先检查数据兼容性
字段类型不匹配会导致静默截断、报错或意外转换,尤其是字符长度、数值精度、时区/格式等细节。
- 用
SELECT target_field, source_field FROM table LIMIT 5;看实际值,别只看表结构 - 字符字段注意长度:如果
target_field是VARCHAR(10),而source_field有 15 位内容,MySQL 可能截断不报错,PostgreSQL 则直接报value too long for type character varying(10) - 时间字段要小心:把
TIMESTAMP写进DATE字段会丢掉时分秒;反过来可能触发时区转换 - 执行前建议先用
SELECT模拟更新逻辑:SELECT id, old_field, new_field FROM t WHERE ...,验证映射关系是否符合预期
批量更新时考虑性能与锁
一次更新几万行以上,容易锁表、阻塞其他操作,甚至触发事务日志爆满。
- 加
WHERE条件尽量走索引,避免全表扫描;可以用EXPLAIN UPDATE ...(MySQL)或EXPLAIN ANALYZE(PostgreSQL)看执行计划 - 大表建议分批更新,例如每次 1000 行:
UPDATE t SET x = y WHERE id BETWEEN ? AND ? - 某些数据库(如 MySQL 的 InnoDB)在事务中更新大量行时,可能因 undo log 增长过快导致失败,需监控
innodb_log_file_size和事务大小 - 生产环境务必在低峰期操作,并提前备份关键数据——
UPDATE没有后悔键
WHERE 条件,这两点几乎每次出问题都绕不开。











