При выполнении оператора обновления, такого как приведенный ниже, я получаю сообщение об ошибке, сообщающее, что
Оконные функции могут появляться только в предложениях 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 не допускается нигде на одном уровне запроса. Любой SELECT, появляющийся с UPDATE, должен содержаться в подзапросе.
Запрещение ORDER BY имеет смысл, учитывая, что инструкция UPDATE безразлична к порядку, в котором она обновляет строки.
Нет никакого недостатка в использовании CTE или другого подзапроса в качестве обходного пути, чтобы получить ОБНОВЛЕНИЕ для использования оконной функции. Это обычная практика, отстаиваемая экспертами T-SQL, такими как Ицик Бен-Ган. (См. Стр. 29 его книги « Высокопроизводительный T-SQL в Microsoft SQL Server 2012 с использованием оконных функций», где он описывает именно этот сценарий.)
источник