Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Ordem condicional T-SQL por


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