CASE
е израз, който връща стойност. Не е за контрол на потока, като IF
. И не можете да използвате IF
в рамките на заявка.
За съжаление, има някои ограничения с CASE
изрази, които правят тромаво да правиш това, което искаш. Например всички клонове в CASE
изразът трябва да връща същия тип или да бъде имплицитно конвертируем в същия тип. Не бих пробвал това с низове и дати. Също така не можете да използвате CASE
за да посочите посоката на сортиране.
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;
Може би по-лесно решение (особено ако това стане по-сложно) е да се използва динамичен SQL. За да предотвратите SQL инжектирането, можете да тествате стойностите:
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;
Още един плюс за динамичния SQL, въпреки целия страх, който се разпространява около него:можете да получите най-добрия план за всеки вариант на сортиране, вместо един-единствен план, който ще се оптимизира за всяка вариация на сортиране, която сте използвали първи. Той също така се представи най-добре универсално в скорошно сравнение на производителността, което проведох:
http://sqlperformance.com/conditional-order-by