SQL Server - pourquoi les fonctions de fenêtre ne sont-elles pas autorisées dans les instructions de mise à jour?

10

Lors de l'exécution d'une instruction de mise à jour, comme celle ci-dessous, j'obtiens une erreur me disant que

Les fonctions fenêtrées ne peuvent apparaître que dans les clauses SELECT ou ORDER BY.

UPDATE dbo.Dim_Chart_of_Account
SET Account_Order = LAG([Account_Order]) OVER (ORDER BY [Account_SKey])

Je sais que cela peut être facilement résolu en utilisant un cte pouvant être mis à jour, comme ci-dessous

 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

Ma question est, y a-t-il des raisons pour lesquelles cela n'est pas autorisé dans une déclaration de mise à jour, devrais-je éviter d'utiliser un cte pouvant être mis à jour comme solution de contournement?

Ma préoccupation est qu'il y a des problèmes lors de l'utilisation des fonctions de fenêtre avec des instructions de mise à jour et je voudrais donc comprendre si c'est une méthode acceptable ou si elle doit être évitée.

Neil P
la source
1
Le CTE pouvant être mis à jour est acceptable et correct. Aucune idée pourquoi cela n'est pas autorisé dans la MISE À JOUR.
ypercubeᵀᴹ
2
Peut-être une protection de quelque sorte que ce soit?
Aaron Bertrand

Réponses:

5

Les fonctions de fenêtre ne sont pas autorisées dans les instructions UPDATE car UPDATE n'est pas compatible avec SELECT ou ORDER BY.

Les fonctions de fenêtre sont comme des instructions SELECT étendues qui réexaminent les lignes pertinentes et appliquent des conditions telles que PARTITION BY et ORDER BY. De plus, de nombreuses fonctions de fenêtre nécessitent une clause ORDER BY (ROW_NUMBER, LAG et FIRST_VALUE, par exemple).

Les instructions UPDATE utilisent SET au lieu de SELECT, donc SELECT n'est autorisé nulle part dans le même niveau de requête. Tout SELECT apparaissant avec UPDATE doit être contenu dans une sous-requête.

Ne pas autoriser ORDER BY est logique étant donné qu'une instruction UPDATE est indifférente à l'ordre dans lequel elle met à jour les lignes.

Il n'y a aucun inconvénient inhérent à utiliser un CTE ou une autre sous-requête comme solution de contournement pour obtenir une MISE À JOUR pour utiliser une fonction de fenêtre. C'est la pratique courante préconisée par des experts T-SQL comme Itzik Ben-Gan. (Voir page 29 de son livre, Microsoft SQL Server 2012 T-SQL hautes performances utilisant des fonctions de fenêtre où il couvre ce scénario exact.)

Doug Lane
la source