CASE
é uma expressão que retorna um valor. Não é para controle de fluxo, como IF
. E você não pode usar IF
dentro de uma consulta. Infelizmente, existem algumas limitações com
CASE
expressões que tornam complicado fazer o que você quer. Por exemplo, todas as ramificações em um CASE
expressão deve retornar o mesmo tipo ou ser implicitamente conversível para o mesmo tipo. Eu não tentaria isso com strings e datas. Você também não pode usar CASE
para especificar a direção de classificação. 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;
Uma solução sem dúvida mais fácil (especialmente se isso ficar mais complexo) é usar SQL dinâmico. Para impedir a injeção de SQL, você pode testar os valores:
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;
Outra vantagem para o SQL dinâmico, apesar de todo o medo espalhado sobre ele:você pode obter o melhor plano para cada variação de classificação, em vez de um único plano que otimizará qualquer variação de classificação que você usou primeiro. Ele também teve o melhor desempenho universal em uma comparação de desempenho recente que fiz:
http://sqlperformance.com/conditional-order-by