Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Ordine condizionale T-SQL per

CASE è un'espressione che restituisce un valore. Non è per il controllo del flusso, come IF . E non puoi usare IF all'interno di una query.

Sfortunatamente, ci sono alcune limitazioni con CASE espressioni che rendono ingombrante fare quello che vuoi. Ad esempio, tutti i rami in un CASE l'espressione deve restituire lo stesso tipo o essere convertibile in modo implicito nello stesso tipo. Non lo proverei con stringhe e date. Inoltre, non puoi utilizzare CASE per specificare la direzione di ordinamento.

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;

Una soluzione probabilmente più semplice (soprattutto se diventa più complessa) consiste nell'usare SQL dinamico. Per contrastare l'iniezione di SQL puoi testare i valori:

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 altro vantaggio per l'SQL dinamico, nonostante tutta la paura che si diffonde al riguardo:puoi ottenere il piano migliore per ogni variazione di ordinamento, invece di un unico piano che ottimizzerà in base a qualsiasi variazione di ordinamento tu abbia utilizzato per prima. Ha anche funzionato meglio universalmente in un recente confronto delle prestazioni che ho eseguito:

http://sqlperformance.com/conditional-order-by