sql >> Base de Datos >  >> RDS >> Sqlserver

Orden condicional de T-SQL por

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