运行更新语句时,例如下面的语句,我收到一条错误消息,告诉我
窗口函数只能出现在 SELECT 或 ORDER BY 子句中。
UPDATE dbo.Dim_Chart_of_Account
SET Account_Order = LAG([Account_Order]) OVER (ORDER BY [Account_SKey])
我知道这可以使用可更新的 cte 轻松解决,如下所示
WITH my_cte AS (
SELECT [Account_Order], LAG([Account_Order]) OVER (ORDER BY [Account_SKey]) AS acc_order_lag
FROM Dim_Chart_of_Account
)
UPDATE my_cte
SET [Account_Order] = acc_order_lag
我的问题是,是否有任何理由在更新语句中不允许这样做,我是否应该避免使用可更新的 cte 作为解决方法?
我担心的是在使用带有更新语句的窗口函数时会出现问题,因此我想了解这是否是一种可接受的方法或应该避免。
UPDATE 语句中不允许使用窗口函数,因为 UPDATE 与 SELECT 或 ORDER BY 不兼容。
窗口函数类似于范围 SELECT 语句,它重新检查相关行并应用 PARTITION BY 和 ORDER BY 等条件。此外,许多窗口函数需要 ORDER BY 子句(例如 ROW_NUMBER、LAG 和 FIRST_VALUE)。
UPDATE 语句使用 SET 而不是 SELECT,因此在同一查询级别的任何地方都不允许 SELECT。与 UPDATE 一起出现的任何 SELECT 都必须包含在子查询中。
考虑到 UPDATE 语句与更新行的顺序无关,禁止 ORDER BY 是有意义的。
使用 CTE 或其他子查询作为解决方法来获取 UPDATE 以使用窗口函数并没有固有的缺点。这是 Itzik Ben-Gan 等 T-SQL 专家所提倡的常见做法。(参见他的书的第 29 页,Microsoft SQL Server 2012 High-Performance T-SQL Using Window Functions,其中他涵盖了这个确切的场景。)