Oblicza listę warunków i zwraca jedno z wielu możliwych wyrażeń wynikowych.
Wyrażenie CASE ma dwa formaty:
Oba formaty obsługują opcjonalny argument ELSE.
Wyrażenie CASE może być używane w dowolnej instrukcji lub klauzuli, która umożliwia obsługę prawidłowych wyrażeń. Na przykład można używać CASE w instrukcjach np. SELECT, UPDATE, DELETE i SET oraz klauzulach np. select_list, IN, WHERE, ORDER BY i HAVING.
Konwencje składni języka Transact-SQL
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
- input_expression
Wyrażenie obliczane w przypadku użycia prostego formatu CASE. input_expression jest dowolnym prawidłowym wyrażeniem.
- WHEN when_expression
Proste wyrażenie, z którym porównywane jest wyrażenie input_expression w przypadku używania prostego formatu wyrażenia CASE. when_expression jest dowolnym prawidłowym wyrażeniem. Typy danych wyrażenia input_expression i każdego wyrażenia when_expression muszą być takie same lub muszą być konwertowane niejawnie.
- THEN result_expression
Wyrażenie zwracane, gdy wyrażenie input_expression równe when_expression zwraca wynik o wartości TRUE lub wyrażenie Boolean_expression zwraca wynik o wartości TRUE. result expression jest dowolnym prawidłowym wyrażeniem.
- ELSE else_result_expression
Wyrażenie zwracane, jeśli żadna operacja porównania nie zwraca wyniku o wartości TRUE. W przypadku pominięcia tego argumentu oraz gdy żadna operacja porównania nie zwraca wyniku o wartości TRUE, CASE zwraca wartość NULL. else_result_expression jest dowolnym prawidłowym wyrażeniem. Typy danych wyrażenia else_result_expression i dowolnego wyrażenia result_expression muszą być takie same lub muszą być konwertowane niejawnie.
- WHEN Boolean_expression
Wyrażenie logiczne obliczane w przypadku używania wyszukiwanego formatu CASE. Boolean_expression jest dowolnym prawidłowym wyrażeniem logicznym.
Zwraca najwyższy typ pierwszeństwa z zestawu typów wyrażenia result_expressions i opcjonalnego wyrażenia else_result_expression. Aby uzyskać więcej informacji, zobacz temat Dane typu priorytet (języka Transact-SQL).
Zwracane wartości
Proste wyrażenie CASE:
Działanie prostego wyrażenia CASE polega na porównywaniu pierwszego wyrażenia z wyrażeniem w każdej klauzuli WHEN w celu sprawdzenia równoważności. Jeśli te wyrażenia są równoważne, zostanie zwrócone wyrażenie w klauzuli THEN.
Umożliwia tylko sprawdzenie równości.
Oblicza wyrażenie input_expression, a następnie w określonej kolejności oblicza wyrażenie input_expression = when_expression dla każdej klauzuli WHEN.
Zwraca wynik result_expression pierwszego obliczenia input_expression = when_expression, które zwraca wynik o wartości TRUE.
Jeśli brak jest obliczenia input_expression = when_expression zwracającego wynik o wartości TRUE, program Aparat baz danych programu SQL Server zwraca else_result_expression, jeśli określona jest klauzula ELSE, lub wartość NULL, jeśli nie określono klauzuli ELSE.
Wyrażenie CASE z przeszukiwaniem:
Oblicza w określonej kolejności wyrażenie Boolean_expression dla każdej klauzuli WHEN.
Zwraca wynik result_expression pierwszego obliczenia Boolean_expression, które zwraca wynik o wartości TRUE.
Jeśli brak jest wyrażenia Boolean_expression zwracającego wynik o wartości TRUE, program Aparat baz danych zwraca wynik wyrażenia else_result_expression, jeśli określona jest klauzula ELSE, lub wartość NULL, jeśli nie określono klauzuli ELSE.
Program SQL Server zezwala tylko na 10 poziomów zagnieżdżania w wyrażeniach CASE.
Nie można używać wyrażenia CASE do sterowania przepływem wykonywania instrukcji Transact-SQL, bloków instrukcji, funkcji zdefiniowanych przez użytkownika i procedur składowanych. Aby zapoznać się z listą metod sterowania przepływem, zobacz temat Język sterowania przepływem (języka Transact-SQL).
Instrukcja CASE oblicza warunki sekwencyjnie i zatrzymuje działanie przy pierwszym spełnianiu warunku. W pewnych sytuacjach wyrażenie jest obliczane zanim instrukcja CASE odbierze wyniki wyrażenia jako swoje dane wejściowe. Możliwe są błędy przy obliczaniu tych wyrażeń. Wyrażenia agregujące występujące w argumentach WHEN przeznaczonych dla instrukcji CASE są obliczane w pierwszej kolejności, następnie są przekazywane do instrukcji CASE. Przykładowo poniższe zapytanie generuje błąd dzielenia przez zero podczas obliczania wartości zagregowanej MAX. Błąd występuje przed obliczeniem wyrażenia CASE.
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 ;
W przypadku wyrażeń skalarnych (w tym nieskorelowanych zapytań podrzędnych zwracających wartości skalarne) należy polegać na kolejności obliczania warunków WHEN, a nie na wyrażeniach agregujących.
A.Użycie instrukcji SELECT z prostym wyrażeniem CASE
W obrębie instrukcji SELECT proste wyrażenie CASE umożliwia tylko sprawdzenie równości; inne porównania nie są wykonywane. W poniższym przykładzie użyto wyrażenia CASE do zmiany sposobu wyświetlania kategorii linii produktów na bardziej czytelny.
USE AdventureWorks2012;
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.Użycie instrukcji SELECT z wyrażeniem CASE z przeszukiwaniem
W obrębie instrukcji SELECT wyszukiwane wyrażenie CASE umożliwia zamianę wartości w zestawie wyników na podstawie porównania wartości. W poniższym przykładzie pokazano wyświetlanie ceny katalogowej jako komentarz tekstowy na podstawie zakresu cen produktu.
USE AdventureWorks2012;
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.Użycie wyrażenia CASE do zastąpienia funkcji IIf używanej w programie Microsoft Access
Instrukcja CASE udostępnia funkcję podobną do funkcji IIf programu Microsoft Access W poniższym przykładzie pokazano proste zapytanie, w którym funkcja IIf służy do obliczenia wartości wyjściowej dla kolumny TelephoneInstructions w tabeli programu Access o nazwie db1.ContactInfo.
SELECT FirstName, LastName, TelephoneNumber,
IIf(IsNull(TelephoneInstructions),"Any time",
TelephoneInstructions) AS [When to Contact]
FROM db1.ContactInfo;
W poniższym przykładzie pokazano sposób użycia instrukcji CASE do obliczenia wartości wyjściowej dla kolumny TelephoneSpecialInstructions w widoku
AdventureWorks2012
Person.vAdditionalContactInfo.
USE AdventureWorks2012;
GO
SELECT FirstName, LastName, TelephoneNumber, 'When to Contact' =
CASE
WHEN TelephoneSpecialInstructions IS NULL THEN 'Any time'
ELSE TelephoneSpecialInstructions
END
FROM Person.vAdditionalContactInfo;
D.Użycie wyrażenia CASE w klauzuli ORDER BY
W poniższym przykładzie użyto wyrażenia CASE w klauzuli ORDER BY do określania kolejności sortowania wierszy na podstawie danej wartości kolumny. W pierwszym przykładzie obliczana jest wartość w kolumnie SalariedFlag tabeli HumanResources.Employee. Zwracana jest lista pracowników mających ustawienie SalariedFlag o wartości 1, według wartości EmployeeID w kolejności malejącej. Zwracana jest lista pracowników mających ustawienie SalariedFlag o wartości 0, według wartości EmployeeID w kolejności rosnącej. W drugim przykładzie zestaw wyników został uporządkowany w kolejności według kolumny TerritoryName, gdy kolumna CountryRegionName jest równa wartości United States, oraz według wartości CountryRegionName dla wszystkich innych wierszy.
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.Użycie wyrażenia CASE w instrukcji UPDATE
W poniższym przykładzie użyto wyrażenia CASE w instrukcji UPDATE do określenia wartości kolumny VacationHours dla pracowników z ustawieniem SalariedFlag o wartości 0. Jeśli w wyniku odjęcia 10 godz. od wartości VacationHours zwracana jest liczba ujemna, wartość VacationHours jest zwiększana o 40 godzin; w przeciwnym razie wartość VacationHours jest zwiększana o 20 godz. Klauzula OUTPUT służy do wyświetlania liczby godzin urlopu przed i po.
USE AdventureWorks2012;
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.Użycie wyrażenia CASE w instrukcji SET
W poniższym przykładzie użyto wyrażenia CASE w instrukcji SET w funkcji zwracającej tabelę dbo.GetContactInfo. W bazie danych
AdventureWorks2012
wszystkie dane związane z osobami są przechowywane w tabeli Person.Person. Osoba może być np. pracownikiem, reprezentantem dostawcy lub klientem. Funkcja zwraca imię i nazwisko dla danej wartości BusinessEntityID oraz typ kontaktu dla tej osoby. Wyrażenie CASE w instrukcji SET określa wartość, która ma być wyświetlana dla kolumny ContactType na podstawie istnienia kolumny BusinessEntityID w tabelach Employee, Vendor lub Customer.
USE AdventureWorks2012;
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.Użycie wyrażenia CASE w klauzuli HAVING
W poniższym przykładzie użyto wyrażenia CASE w klauzuli HAVING do ograniczenia wierszy zwracanych przez instrukcję SELECT. Instrukcja zwraca maksymalną stawkę godzinową dla każdego stanowiska w tabeli HumanResources.Employee. Klauzula HAVING ogranicza stanowiska do stanowisk zajmowanych przez mężczyzn z maksymalną stawką płacy większą niż 40 dolarów lub kobiet z maksymalną stawką większą niż 42 dolary.
USE AdventureWorks2012;
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;
Odwołanie