CASE
je výraz, který vrací hodnotu. Není to pro kontrolu toku, jako IF
. A nemůžete použít IF
v rámci dotazu.
Bohužel existují určitá omezení s CASE
výrazy, díky nimž je těžkopádné dělat to, co chcete. Například všechny větve v CASE
výraz musí vracet stejný typ nebo být implicitně převoditelný na stejný typ. To bych s řetězci a datlemi nezkoušel. Nemůžete také použít CASE
k určení směru řazení.
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;
Pravděpodobně jednodušším řešením (zejména pokud je to složitější) je použití dynamického SQL. Chcete-li zabránit vkládání SQL, můžete otestovat hodnoty:
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;
Další plus pro dynamické SQL, navzdory všemu strachu, který se kolem toho šíří:můžete získat nejlepší plán pro každou variantu řazení namísto jediného plánu, který se bude optimalizovat pro jakoukoli variantu řazení, kterou jste náhodou použili jako první. V nedávném srovnání výkonu, které jsem provedl, si také vedl univerzálně nejlépe:
http://sqlperformance.com/conditional-order-by