PAYATHON 2026

Access SQL 中使用聚合函数执行 UPDATE SET

支付小周

结论

Access SQL 对 UPDATE ... SET 中的相关聚合子查询支持有限。如果直接在 SET 后写 SELECT AVG(...),通常会出现语法错误,或提示“查询必须是可更新的查询”。

比较稳妥的办法是先将各城市的平均值写入临时表,再用可更新的连接查询更新 Agent。

解决方法

先计算每个城市的平均 Payment,并将结果保存到临时表:

SELECT
    City,
    AVG(Payment) AS AvgPayment
INTO AgentCityAverage
FROM Agent
GROUP BY City;

再把平均值更新到 Agent:

UPDATE Agent
INNER JOIN AgentCityAverage
    ON Agent.City = AgentCityAverage.City
SET Agent.Payment = AgentCityAverage.AvgPayment;

执行后,数据如下:

ID_AgentCityPayment
1London1300
2York1750
3London1300
4York1750

确认更新结果正确后,可以删除临时表:

DROP TABLE AgentCityAverage;

为什么原来的 SQL 不能运行

下面的写法在部分数据库中有效:

UPDATE Agent AS a1
SET a1.Payment =
(
    SELECT AVG(a2.Payment)
    FROM Agent AS a2
    WHERE a2.City = a1.City
);

但 Access 的更新查询无法可靠地将这种相关聚合子查询用作 SET 的值。即使把聚合查询直接连接到更新查询,Access 也可能因为聚合结果集不可更新而拒绝执行。先将聚合结果写入普通表,可以避开这个限制。

临时表已经存在时

SELECT ... INTO 要求目标表尚不存在。如果需要重复执行,可以保留 AgentCityAverage,每次先清空表中的数据:

DELETE FROM AgentCityAverage;

然后重新写入各城市的平均值:

INSERT INTO AgentCityAverage (City, AvgPayment)
SELECT City, AVG(Payment)
FROM Agent
GROUP BY City;

最后再次执行更新:

UPDATE Agent
INNER JOIN AgentCityAverage
    ON Agent.City = AgentCityAverage.City
SET Agent.Payment = AgentCityAverage.AvgPayment;

注意事项

  • AVG() 会忽略 Null。如果某个城市的 Payment 全部为 Null,计算结果也会是 Null。
  • City 为 Null 的记录无法通过普通等值连接匹配,需要另行处理。
  • 如果 Payment 是整数类型,而平均值可能带有小数,应将该字段改为合适的数值类型或 Currency 类型,否则 Access 可能会进行舍入。
  • 此更新会覆盖原始 Payment。如果需要保留原始金额,应先备份表,或将平均值写入新字段。

备注:内容仅供参考。