不能。SQL Server 的 UPDATE ... FROM 语法仅允许更新单个目标表,FROM 后可关联多表用于条件或取值,但 SET 只能赋值给该表列;错误写法如 UPDATE t1, t2 会报错,正确方式是 UPDATE ... FROM ... JOIN 或子查询/CTE。

SQL Server 中 UPDATE FROM 能否直接更新多表?
不能。标准 SQL 的 UPDATE 语句本身不支持 FROM 子句(除 SQL Server 外),而 SQL Server 的 UPDATE ... FROM 语法虽存在,但**只允许一个目标表被修改**,FROM 后可关联多表用于条件或取值,但 SET 只能赋值给该单个目标表的列。
常见误解是写成这样(错误):
UPDATE t1, t2 SET t1.name = t2.name WHERE t1.id = t2.t1_id
这在 SQL Server 中会报错:Incorrect syntax near ',';在 MySQL 中虽支持多表 UPDATE,但语法和语义完全不同,不可混用。
SQL Server 正确实现多表关联更新的两种方式
实际需求通常是:根据表 B 的数据更新表 A 的某些字段。核心思路是把表 B 当作「数据源」,通过 JOIN 关联到目标表 A 上。
- 推荐用法:使用
UPDATE ... FROM ... JOIN结构(SQL Server 特有,最直观) - 兼容写法:用子查询或 CTE 预先聚合/关联,再更新(更可控,适合复杂逻辑)
✅ 正确示例(更新 orders 表的 customer_name 字段,来自 customers 表):
UPDATE o SET o.customer_name = c.name FROM orders o INNER JOIN customers c ON o.customer_id = c.id;
⚠️ 注意:o 是要更新的目标别名,必须出现在 UPDATE 后且与 FROM 中的别名一致;SET 中的列必须属于该目标表。
为什么 JOIN 类型和 WHERE 条件容易出错?
看似只是关联,但影响结果是否安全、是否漏更新、是否重复更新:
-
INNER JOIN:只更新有匹配记录的行 —— 安全,推荐作为默认选择 -
LEFT JOIN+WHERE ... IS NOT NULL:等效于 INNER,但写法冗余,且若条件放错位置(如写在ON里)会导致逻辑偏差 - 没加
WHERE或关联条件缺失:可能触发全表更新,尤其当 JOIN 产生笛卡尔积时,SET值会取非确定性匹配行(SQL Server 选任意一行),结果不可控 - 多对一关联未去重:比如订单表 JOIN 订单明细表(一对多),直接更新会报错
The table 'xxx' is ambiguous或静默取某一行值 —— 必须提前聚合或限制(如用TOP 1子查询)
MySQL 用户注意:语法完全不同
MySQL 不支持 UPDATE ... FROM,而是用 UPDATE t1 JOIN t2 ON ... SET t1.col = t2.col 形式:
UPDATE orders o JOIN customers c ON o.customer_id = c.id SET o.customer_name = c.name;
关键区别:
- MySQL 的
UPDATE后可跟多个表名(或别名),用JOIN连接 -
SET可跨表赋值(例如同时更新o.name和c.status),但需有明确权限 - 没有
FROM关键字;写FROM会直接报错
跨数据库迁移存储过程时,这部分几乎必然要重写。
真正难的不是写出来,而是确认 JOIN 是否恰好一对一、是否所有业务主键都参与了关联、以及测试时有没有覆盖 NULL 关联场景 —— 这些地方一漏,上线后就默默改错数据。










