CASE
es una expresión que devuelve un valor. No es para control de flujo, como IF
. Y no puedes usar IF
dentro de una consulta.
Desafortunadamente, hay algunas limitaciones con CASE
Expresiones que hacen que sea engorroso hacer lo que quieres. Por ejemplo, todas las ramas en un CASE
expresión debe devolver el mismo tipo, o ser implícitamente convertible al mismo tipo. No intentaría eso con cadenas y fechas. Tampoco puedes usar CASE
para especificar la dirección de clasificación.
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;
Podría decirse que una solución más fácil (especialmente si esto se vuelve más complejo) es usar SQL dinámico. Para frustrar la inyección de SQL, puede probar los valores:
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;
Otra ventaja para el SQL dinámico, a pesar de todo el miedo que se propaga al respecto:puede obtener el mejor plan para cada variación de clasificación, en lugar de un solo plan que se optimizará para cualquier variación de clasificación que haya utilizado primero. También se desempeñó mejor universalmente en una comparación de rendimiento reciente que ejecuté:
http://sqlperformance.com/pedido-condicional-por