CASE
est une expression qui renvoie une valeur. Ce n'est pas pour le contrôle de flux, comme IF
. Et vous ne pouvez pas utiliser IF
dans une requête.
Malheureusement, il existe certaines limitations avec CASE
expressions qui rendent encombrant de faire ce que vous voulez. Par exemple, toutes les branches d'un CASE
L'expression doit renvoyer le même type ou être implicitement convertible dans le même type. Je n'essaierais pas cela avec des chaînes et des dates. Vous ne pouvez pas non plus utiliser CASE
pour spécifier le sens du tri.
SELECT column_list_please
FROM dbo.Product -- dbo prefix please
ORDER BY
CASE WHEN @sortDir = 'asc' AND @sortOrder = 'name' THEN name END,
CASE WHEN @sortDir = 'asc' AND @sortOrder = 'created_date' THEN created_date END,
CASE WHEN @sortDir = 'desc' AND @sortOrder = 'name' THEN name END DESC,
CASE WHEN @sortDir = 'desc' AND @sortOrder = 'created_date' THEN created_date END DESC;
Une solution sans doute plus simple (surtout si cela devient plus complexe) consiste à utiliser SQL dynamique. Pour contrecarrer l'injection SQL, vous pouvez tester les valeurs :
IF @sortDir NOT IN ('asc', 'desc')
OR @sortOrder NOT IN ('name', 'created_date')
BEGIN
RAISERROR('Invalid params', 11, 1);
RETURN;
END
DECLARE @sql NVARCHAR(MAX) = N'SELECT column_list_please
FROM dbo.Product ORDER BY ' + @sortOrder + ' ' + @sortDir;
EXEC sp_executesql @sql;
Un autre avantage pour le SQL dynamique, malgré tous les discours alarmistes qui se répandent à son sujet :vous pouvez obtenir le meilleur plan pour chaque variation de tri, au lieu d'un seul plan qui s'optimisera en fonction de la variation de tri que vous avez utilisée en premier. Il a également obtenu les meilleurs résultats universels dans une récente comparaison de performances que j'ai effectuée :
http://sqlperformance.com/ordre-conditionnel-par