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