Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Bedingte T-SQL-Reihenfolge nach

CASE ist ein Ausdruck, der einen Wert zurückgibt. Es dient nicht der Flusskontrolle, wie IF . Und Sie können IF nicht verwenden innerhalb einer Abfrage.

Leider gibt es einige Einschränkungen bei CASE Ausdrücke, die es umständlich machen, das zu tun, was Sie wollen. Zum Beispiel alle Zweige in einem CASE Ausdruck muss denselben Typ zurückgeben oder implizit in denselben Typ konvertierbar sein. Ich würde das nicht mit Strings und Dates versuchen. Sie können auch nicht CASE verwenden um die Sortierrichtung anzugeben.

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;

Eine wohl einfachere Lösung (insbesondere wenn dies komplexer wird) ist die Verwendung von dynamischem SQL. Um die SQL-Injection zu vereiteln, können Sie die Werte 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;

Ein weiteres Plus für dynamisches SQL, trotz aller Angstmacherei, die darüber verbreitet wird:Sie können den besten Plan für jede Sortiervariante erhalten, anstatt einen einzigen Plan, der auf die Sortiervariante optimiert, die Sie zufällig zuerst verwendet haben. Es hat auch in einem kürzlich von mir durchgeführten Leistungsvergleich am besten abgeschnitten:

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