CASE (Transact-SQL)

Wertet eine Liste von Bedingungen aus und gibt einen von mehreren möglichen Ergebnisausdrücken zurück.

Der CASE-Ausdruck verfügt über zwei Formate:

  • Der einfache CASE-Ausdruck vergleicht einen Ausdruck mit mehreren einfachen Ausdrücken, um das Ergebnis zu bestimmen.

  • Der komplexe CASE-Ausdruck wertet eine Menge boolescher Ausdrücke aus, um das Ergebnis zu bestimmen.

Bei beiden Formaten wird ein optionales ELSE-Argument unterstützt.

CASE kann in einer beliebigen Anweisung oder Klausel verwendet werden, die einen gültigen Ausdruck zulässt. Beispielsweise können CASE-Anweisungen wie SELECT, UPDATE, DELETE und SET und Klauseln wie select_list, IN, WHERE, ORDER BY und HAVING verwendet werden.

Themenlink (Symbol)Transact-SQL-Syntaxkonventionen

Syntax

Simple CASE expression: 
CASE input_expression 
     WHEN when_expression THEN result_expression [ ...n ] 
     [ ELSE else_result_expression ] 
END 
Searched CASE expression:
CASE
     WHEN Boolean_expression THEN result_expression [ ...n ] 
     [ ELSE else_result_expression ] 
END

Argumente

  • input_expression
    Der Ausdruck, der ausgewertet wird, wenn das einfache CASE-Format verwendet wird. input_expression kann jeder gültige Ausdruck sein.

  • WHEN when_expression
    Ein einfacher Ausdruck, mit dem input_expression verglichen wird, wenn das einfache CASE-Format verwendet wird. when_expression kann jeder gültige Ausdruck sein. Die Datentypen von input_expression und allen when_expression-Ausdrücken müssen gleich sein, oder es muss eine implizite Konvertierung vorliegen.

  • THEN result_expression
    Der Ausdruck, der zurückgegeben wird, wenn input_expression gleich when_expression zu TRUE ausgewertet wird oder wenn Boolean_expression zu TRUE ausgewertet wird. result expression kann jeder gültige Ausdruck sein.

  • ELSE else_result_expression
    Der Ausdruck, der zurückgegeben wird, wenn keine Vergleichsoperation TRUE ergibt. Wird dieses Argument nicht angegeben und wird keine Vergleichsoperation zu TRUE ausgewertet, gibt die CASE-Funktion NULL zurück. else_result_expression kann jeder gültige Ausdruck sein. Die Datentypen von else_result_expression und allen result_expression-Ausdrücken müssen gleich sein, oder es muss eine implizite Konvertierung vorliegen.

  • WHEN Boolean_expression
    Der boolesche Ausdruck, der ausgewertet wird, wenn das komplexe CASE-Format verwendet wird. Boolean_expression kann jeder gültige boolesche Ausdruck sein.

Rückgabetypen

Gibt den vorrangigsten Typ der Typen in result_expressions und in dem optionalen else_result_expression-Ausdruck zurück. Weitere Informationen finden Sie unter Rangfolge der Datentypen (Transact-SQL).

Rückgabewerte

Einfacher CASE-Ausdruck:

Beim einfachen CASE-Ausdruck wird verglichen, ob der erste Ausdruck mit dem Ausdruck in den einzelnen WHEN-Klauseln gleichwertig ist. Wenn diese Ausdrücke gleichwertig sind, wird der Ausdruck in der THEN-Klausel zurückgegeben.

  • Lässt nur eine Gleichheitsüberprüfung zu.

  • input_expression wird ausgewertet, und anschließend werden die input_expression = when_expression-Ausdrücke für jede WHEN-Klausel in der angegebenen Reihenfolge ausgewertet.

  • Gibt den result_expression-Ausdruck des ersten input_expression = when_expression-Ausdrucks zurück, der zu TRUE ausgewertet wird.

  • Wird kein input_expression = when_expression-Ausdruck zu TRUE ausgewertet, gibt SQL Server Database Engine (Datenbankmodul) den else_result_expression-Ausdruck zurück, falls eine ELSE-Klausel angegeben ist, oder einen NULL-Wert, falls keine ELSE-Klausel angegeben ist.

Komplexer CASE-Ausdruck:

  • Für jede WHEN-Klausel werden die Boolean_expression-Ausdrücke in der angegebenen Reihenfolge ausgewertet.

  • Gibt den result_expression-Ausdruck des ersten Boolean_expression-Ausdrucks zurück, der zu TRUE ausgewertet wird.

  • Wird kein Boolean_expression-Ausdruck zu TRUE ausgewertet, gibt Database Engine (Datenbankmodul) den else_result_expression-Ausdruck zurück, falls eine ELSE-Klausel angegeben ist, oder einen NULL-Wert, falls keine ELSE-Klausel angegeben ist.

Hinweise

In SQL Server ist für CASE-Ausdrücke nur eine Schachtelung von 10 Ebenen zulässig.

Der CASE-Ausdruck kann nicht verwendet werden, um den Ablauf bei der Ausführung von Transact-SQL-Anweisungen, Anweisungsblöcken, benutzerdefinierten Funktionen und gespeicherten Prozeduren zu steuern. Eine Liste von Ablaufsteuerungsmethoden finden Sie unter Ablaufsteuerungssprache (Transact-SQL).

Die Bedingungen der CASE-Anweisung werden in der festgelegten Reihenfolge ausgewertet, wobei bei der ersten Bedingung angehalten wird, deren Bedingung erfüllt wird. In manchen Situationen wird ein Ausdruck ausgewertet, bevor eine CASE-Anweisung die Ergebnisse des Ausdrucks als Eingabe empfängt. Fehler beim Auswerten dieser Ausdrücke sind möglich. Aggregatausdrücke, die in WHEN-Argumenten einer CASE-Anweisung angegeben sind, werden zuerst ausgewertet, dann für die CASE-Anweisung bereitgestellt. Beispielsweise erzeugt die folgende Abfrage einen Fehler durch arithmetische Teilung durch null, wenn der Wert des MAX-Aggregats erzeugt wird. Dieser Fehler tritt auf, bevor der CASE-Ausdruck ausgewertet wird.

WITH Data (value) AS 
( 
SELECT 0 
UNION ALL 
SELECT 1 
) 
SELECT 
   CASE 
      WHEN MIN(value) <= 0 THEN 0 
      WHEN MAX(1/value) >= 100 THEN 1 
   END 
FROM Data ;

Sie sollten nur von der Auswertungsreihenfolge der WHEN-Bedingungen für Skalarausdrücke (einschließlich nicht korrelierter Abfragen, die Skalare zurückgeben), nicht jedoch für Aggregatausdrücke abhängen.

Beispiele

A. Verwenden einer SELECT-Anweisung mit einem einfachen CASE-Ausdruck

Innerhalb einer SELECT-Anweisung ermöglicht ein einfacher CASE-Ausdruck nur eine Überprüfung auf Gleichheit. Andere Vergleiche werden nicht angestellt. Im folgenden Beispiel wird ein CASE-Ausdruck verwendet, um die Anzeige von Produktkategorien so zu ändern, dass sie leichter verständlich werden.

USE AdventureWorks2008R2;
GO
SELECT   ProductNumber, Category =
      CASE ProductLine
         WHEN 'R' THEN 'Road'
         WHEN 'M' THEN 'Mountain'
         WHEN 'T' THEN 'Touring'
         WHEN 'S' THEN 'Other sale items'
         ELSE 'Not for sale'
      END,
   Name
FROM Production.Product
ORDER BY ProductNumber;
GO

B. Verwenden einer SELECT-Anweisung mit einem komplexen CASE-Ausdruck

Innerhalb einer SELECT-Anweisung können mit dem komplexen CASE-Ausdruck Werte im Resultset basierend auf den Vergleichsergebnissen ersetzt werden. Im folgenden Beispiel wird anstelle des Listenpreises ein Kommentar angezeigt, der vom Preisbereich der einzelnen Produkte abhängt.

USE AdventureWorks2008R2;
GO
SELECT   ProductNumber, Name, 'Price Range' = 
      CASE 
         WHEN ListPrice =  0 THEN 'Mfg item - not for resale'
         WHEN ListPrice < 50 THEN 'Under $50'
         WHEN ListPrice >= 50 and ListPrice < 250 THEN 'Under $250'
         WHEN ListPrice >= 250 and ListPrice < 1000 THEN 'Under $1000'
         ELSE 'Over $1000'
      END
FROM Production.Product
ORDER BY ProductNumber ;
GO

C. Verwenden von CASE als Ersatz für die IIf-Funktion von Microsoft Access

Die von CASE bereitgestellte Funktionalität gleicht der IIf-Funktion in Microsoft Access. Das folgende Beispiel zeigt eine einfache Abfrage, die mithilfe von IIf einen Ausgabewert für die TelephoneInstructions-Spalte in einer Access-Tabelle mit dem Namen db1.ContactInfo bereitstellt.

SELECT FirstName, LastName, TelephoneNumber, 
     IIf(IsNull(TelephoneInstructions),"Any time",
     TelephoneInstructions) AS [When to Contact]
FROM db1.ContactInfo; 

Im folgenden Beispiel wird CASE verwendet, um einen Ausgabewert für die TelephoneSpecialInstructions-Spalte in der AdventureWorks2008R2-Sicht Person.vAdditionalContactInfo bereitzustellen.

USE AdventureWorks2008R2;
GO
SELECT FirstName, LastName, TelephoneNumber, 'When to Contact' = 
     CASE
          WHEN TelephoneSpecialInstructions IS NULL THEN 'Any time'
          ELSE TelephoneSpecialInstructions
     END
FROM Person.vAdditionalContactInfo;

D. Verwenden von CASE in einer ORDER BY-Klausel

In den folgenden Beispielen wird der CASE-Ausdruck in einer ORDER BY-Klausel verwendet, um die Sortierreihenfolge der Zeilen auf Grundlage eines angegebenen Spaltenwerts zu bestimmen. Im ersten Beispiel wird der Wert in der SalariedFlag-Spalte der HumanResources.Employee-Tabelle ausgewertet. Mitarbeiter, deren SalariedFlag auf 1 festgelegt wurde, werden nach EmployeeID in absteigender Folge zurückgegeben. Mitarbeiter, deren SalariedFlag auf 0 festgelegt wurde, werden nach EmployeeID in aufsteigender Folge zurückgegeben. Im zweiten Beispiel wird das Resultset nach der TerritoryName-Spalte sortiert, wenn die CountryRegionName-Spalte gleich 'USA' ist, und bei allen anderen Zeilen nach CountryRegionName.

SELECT BusinessEntityID, SalariedFlag
FROM HumanResources.Employee
ORDER BY CASE SalariedFlag WHEN 1 THEN BusinessEntityID END DESC
        ,CASE WHEN SalariedFlag = 0 THEN BusinessEntityID END;
GO
SELECT BusinessEntityID, LastName, TerritoryName, CountryRegionName
FROM Sales.vSalesPerson
WHERE TerritoryName IS NOT NULL
ORDER BY CASE CountryRegionName WHEN 'United States' THEN TerritoryName
         ELSE CountryRegionName END;

E. Verwenden von CASE in einer UPDATE-Anweisung

Im folgenden Beispiel wird der CASE-Ausdruck in einer UPDATE-Anweisung verwendet, um den Wert zu bestimmen, der für die VacationHours-Spalte für Mitarbeiter mit SalariedFlag gleich 0 festgelegt wurde. Wenn von VacationHours 10 Stunden subtrahiert werden, und dies einen negativen Wert ergibt, wird VacationHours um 40 Stunden erhöht; andernfalls wird VacationHours um 20 Stunden erhöht. Die OUTPUT-Klausel wird verwendet, um die Werte vor und nach dem Urlaub anzuzeigen.

USE AdventureWorks2008R2;
GO
UPDATE HumanResources.Employee
SET VacationHours = 
    ( CASE
         WHEN ((VacationHours - 10.00) < 0) THEN VacationHours + 40
         ELSE (VacationHours + 20.00)
       END
    )
OUTPUT Deleted.BusinessEntityID, Deleted.VacationHours AS BeforeValue, 
       Inserted.VacationHours AS AfterValue
WHERE SalariedFlag = 0; 

F. Verwenden von CASE in einer SET-Anweisung

Im folgenden Beispiel wird der CASE-Ausdruck in einer SET-Anweisung in der Tabellenwertfunktion dbo.GetContactInfo verwendet. In der AdventureWorks2008R2-Datenbank werden alle Daten zu Personen in der Person.Person-Tabelle gespeichert. Die Person kann z. B. ein Mitarbeiter, Herstellerkontakt oder Kunde sein. Die Funktion gibt den Vor- und Nachnamen einer bestimmten BusinessEntityID und den Kontakttyp für diese Person zurück. Der CASE-Ausdruck in der SET-Anweisung bestimmt den Wert, der für die ContactType-Spalte basierend auf dem Vorhandensein der BusinessEntityID-Spalte in der Tabelle Employee, Vendor oder Customer angezeigt werden soll.

  USE AdventureWorks2008R2;
    GO
    CREATE FUNCTION dbo.GetContactInformation(@BusinessEntityID int)
    RETURNS @retContactInformation TABLE 
    (
    BusinessEntityID int NOT NULL,
    FirstName nvarchar(50) NULL,
    LastName nvarchar(50) NULL,
    ContactType nvarchar(50) NULL,
    PRIMARY KEY CLUSTERED (BusinessEntityID ASC)
) 
AS 
-- Returns the first name, last name and contact type for the specified contact.
BEGIN
    DECLARE 
        @FirstName nvarchar(50), 
        @LastName nvarchar(50), 
        @ContactType nvarchar(50);

    -- Get common contact information
    SELECT 
        @BusinessEntityID = BusinessEntityID, 
        @FirstName = FirstName, 
        @LastName = LastName
    FROM Person.Person 
    WHERE BusinessEntityID = @BusinessEntityID;

    SET @ContactType = 
        CASE 
            -- Check for employee
            WHEN EXISTS(SELECT * FROM HumanResources.Employee AS e 
                WHERE e.BusinessEntityID = @BusinessEntityID) 
                THEN 'Employee'

            -- Check for vendor
            WHEN EXISTS(SELECT * FROM Person.BusinessEntityContact AS bec
                WHERE bec.BusinessEntityID = @BusinessEntityID) 
                THEN 'Vendor'

            -- Check for store
            WHEN EXISTS(SELECT * FROM Purchasing.Vendor AS v          
                WHERE v.BusinessEntityID = @BusinessEntityID) 
                THEN 'Store Contact'

            -- Check for individual consumer
            WHEN EXISTS(SELECT * FROM Sales.Customer AS c 
                WHERE c.PersonID = @BusinessEntityID) 
                THEN 'Consumer'
        END;

    -- Return the information to the caller
    IF @BusinessEntityID IS NOT NULL 
    BEGIN
        INSERT @retContactInformation
        SELECT @BusinessEntityID, @FirstName, @LastName, @ContactType;
    END;

    RETURN;
END;
GO

SELECT BusinessEntityID, FirstName, LastName, ContactType
FROM dbo.GetContactInformation(2200);
GO
SELECT BusinessEntityID, FirstName, LastName, ContactType
FROM dbo.GetContactInformation(5);

G. Verwenden von CASE in einer HAVING-Klausel

Im folgenden Beispiel wird der CASE-Ausdruck in einer HAVING-Klausel verwendet, um die von der SELECT-Anweisung zurückgegebenen Zeilen einzuschränken. Die Anweisung gibt den maximalen Stundensatz für jede Berufsbezeichnung in der HumanResources.Employee-Tabelle zurück. Die HAVING-Klausel beschränkt die Bezeichnungen auf diejenigen Positionen, die von Männern mit einem maximalen Stundensatz von über 40 Dollar bzw. von Frauen mit einem maximalen Stundensatz von über 42 Dollar besetzt werden.

USE AdventureWorks2008R2;
GO
SELECT JobTitle, MAX(ph1.Rate)AS MaximumRate
FROM HumanResources.Employee AS e
JOIN HumanResources.EmployeePayHistory AS ph1 ON e.BusinessEntityID = ph1.BusinessEntityID
GROUP BY JobTitle
HAVING (MAX(CASE WHEN Gender = 'M' 
        THEN ph1.Rate 
        ELSE NULL END) > 40.00
     OR MAX(CASE WHEN Gender  = 'F' 
        THEN ph1.Rate  
        ELSE NULL END) > 42.00)
ORDER BY MaximumRate DESC;