CASE
to wyrażenie zwracające wartość. Nie służy do kontroli przepływu, jak IF
. I nie możesz użyć IF
w zapytaniu.
Niestety istnieją pewne ograniczenia związane z CASE
wyrażenia, które sprawiają, że robienie tego, co chcesz, jest uciążliwe. Na przykład wszystkie gałęzie w CASE
wyrażenie musi zwracać ten sam typ lub być niejawnie konwertowane na ten sam typ. Nie próbowałbym tego ze stringami i datami. Nie możesz też użyć CASE
aby określić kierunek sortowania.
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;
Prawdopodobnie łatwiejszym rozwiązaniem (zwłaszcza jeśli staje się to bardziej skomplikowane) jest użycie dynamicznego SQL. Aby zapobiec wstrzyknięciu SQL, możesz przetestować wartości:
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;
Kolejny plus za dynamiczny SQL, pomimo całego siania strachu, które się wokół niego szerzy:możesz uzyskać najlepszy plan dla każdej odmiany sortowania, zamiast jednego pojedynczego planu, który zoptymalizuje się pod kątem dowolnej odmiany, którą wcześniej użyłeś. W ostatnim porównaniu wydajności, które przeprowadziłem, sprawdził się również najlepiej uniwersalnie:
http://sqlperformance.com/conditional-order-by