sql >> Database >  >> RDS >> Sqlserver

T-SQL voorwaardelijke bestelling op

CASE is een expressie die een waarde retourneert. Het is niet voor controle van de stroom, zoals IF . En je kunt IF . niet gebruiken binnen een zoekopdracht.

Helaas zijn er enkele beperkingen met CASE uitdrukkingen die het lastig maken om te doen wat je wilt. Bijvoorbeeld alle takken in een CASE expressie moet hetzelfde type retourneren of impliciet converteerbaar zijn naar hetzelfde type. Ik zou dat niet proberen met snaren en datums. U kunt CASE ook niet gebruiken om de sorteerrichting op te geven.

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;

Een aantoonbaar eenvoudigere oplossing (vooral als dit complexer wordt) is om dynamische SQL te gebruiken. Om SQL-injectie te voorkomen, kunt u de waarden testen:

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;

Nog een pluspunt van dynamische SQL, ondanks alle angstzaaierij die erover wordt verspreid:je kunt het beste plan krijgen voor elke soortvariatie, in plaats van één enkel plan dat zal optimaliseren voor de soortvariatie die je als eerste hebt gebruikt. Het presteerde ook universeel het beste in een recente prestatievergelijking die ik uitvoerde:

http://sqlperformance.com/conditional-order-by



  1. Kan de PostgreSQL-clientbibliotheek (libpq) niet vinden

  2. Vergelijking van Entity Framework-compatibele providers voor Oracle?

  3. Compressie inschakelen op een bestaande tabel in SQL Server (T-SQL)

  4. Hoe een rij in orakel te verwijderen