Nous souhaitons utiliser un paramètre dans la clause "Order By" d'une requête ou d'une procédure stockée créée avec Visual Studio DataSet Designer.
Exemple:
FROM TableName
WHERE (Forename LIKE '%' + @SearchValue + '%') OR
(Surname LIKE '%' + @SearchValue + '%') OR
(@SearchValue = 'ALL')
ORDER BY @OrderByColumn
Cette erreur s'affiche:
Variables are only allowed when ordering by an expression referencing
a column name.
Vous devriez pouvoir faire quelque chose comme ceci:
SELECT *
FROM
TableName
WHERE
(Forename LIKE '%' + @SearchValue + '%') OR
(Surname LIKE '%' + @SearchValue + '%') OR
(@SearchValue = 'ALL')
ORDER BY
CASE @OrderByColumn
WHEN 1 THEN Forename
WHEN 2 THEN Surname
END;
@OrderByColumn
pour trier sur Forename
.Surname
.Attention cependant aux performances. Ces types de constructions peuvent interférer avec la capacité de l'optimiseur de requêtes à trouver un plan d'exécution optimal. Par exemple, même si Forename
est couvert par l'index, la requête peut toujours nécessiter le tri complet au lieu de simplement parcourir l'index dans l'ordre.
Si tel est le cas et que vous ne pouvez pas supporter les implications en termes de performances, il peut être nécessaire d'avoir une version distincte de la requête pour chaque ordre de tri possible, ce qui complique considérablement les choses côté client.
Je sais que j'arrive tard dans ce fil, mais je veux juste le poster au cas où quelqu'un d'autre aurait un problème similaire.
Le problème semble se produire lorsque vous essayez d'effectuer un ORDER BY
Directement sur le paramètre, car SQL Server s'attend à ce que vous fournissiez un nombre (1 pour le premier champ, 2 pour le second, etc.) ou un nom de colonne présenté sous la forme d'un identifiant (MyField ou "MyField") ou d'une chaîne ('MyField').
Par exemple:
DECLARE @ORDERBY AS NVARCHAR(20)
;
SELECT @ORDERBY = :Param1 --(Supposing that the user enters 'MyField')
;
SELECT TOP 1 *
FROM MyTable
ORDER BY @ORDERBY DESC
;
Vous obtenez l'erreur suivante:
L'élément SELECT identifié par le numéro ORDER BY 1 contient une variable dans le cadre de l'expression identifiant une position de colonne. Les variables ne sont autorisées que lors de la commande par une expression faisant référence à un nom de colonne. (SQLSTATE = 42000) (1008) (Gravité = 16)
Si vous écrivez la requête manuellement de l'une des manières décrites (à l'aide d'un identifiant ou d'une chaîne), il n'y a pas d'erreur.
SELECT TOP 1 *
FROM MyTable
ORDER BY MyField DESC
;
SELECT TOP 1 *
FROM MyTable
ORDER BY "MyField" DESC
;
SELECT TOP 1 *
FROM MyTable
ORDER BY 'MyField' DESC
;
Donc, si vous effectuez une CAST()
sur ce même paramètre, sa valeur est convertie en chaîne et la requête s'exécute avec succès:
DECLARE @ORDERBY AS NVARCHAR(20)
;
SELECT @ORDERBY = :Param1 --(Supposing that the user enters the text 'MyField')
;
SELECT TOP 1 *
FROM MyTable
ORDER BY CAST(@ORDERBY AS NVARCHAR(20)) DESC
;
Dans ce cas, (encore une fois, en supposant que l'utilisateur a écrit la chaîne "MyField" comme valeur de: Param1), la requête en cours d'exécution est:
SELECT TOP 1 *
FROM MyTable
ORDER BY 'MyField' DESC
;
Cette requête s'exécute avec succès, sans erreur et sans impact significatif apparent sur les performances, sans avoir besoin d'énumérer toutes les entrées utilisateur possibles dans une instruction CASE
qui pourrait potentiellement s'étendre à des centaines de valeurs possibles.
J'ai utilisé cette solution plusieurs fois dans Microsoft SQL Server, de 2005 à 2016, sans aucun problème.
J'espère que cela peut encore être utile à quelqu'un.