W SQL Server CASE
T-SQL wyrażenie to wyrażenie skalarne, które zwraca wartość opartą na logice warunkowej. Ocenia listę warunków i zwraca wartość w oparciu o wynik tych warunków.
W pewnym sensie SQL Server CASE
wyrażenie jest podobne do IF...ELSE
. Jednak CASE
umożliwia sprawdzenie wielu warunków, podczas gdy IF...ELSE
nie.
Również w SQL Server, IF...ELSE
jest słowem kluczowym w języku kontroli przepływu, podczas gdy CASE
nie jest. CASE
wyrażenie nie może być używane do sterowania przepływem wykonywania instrukcji T-SQL, bloków instrukcji, funkcji zdefiniowanych przez użytkownika i procedur składowanych.
Dwie formy wyrażenia CASE
Istnieją dwie formy CASE
wyrażenie w SQL Server:
- Prosty
CASE
wyrażenie - Przeszukano
CASE
wyrażenie
Wyjaśniono je na poniższych przykładach.
Formularz 1 – proste wyrażenie CASE
Prosty CASE
wyrażenie porównuje wyrażenie z zestawem prostych wyrażeń w celu określenia wyniku.
Oto podstawowy przykład pokazujący, jak CASE
wyrażenie działa w SQL Server.
DECLARE @stock_ticker varchar(4) = 'V';
SELECT Company =
CASE @stock_ticker
WHEN 'AAPL' THEN 'Apple'
WHEN 'FB' THEN 'Facebook'
WHEN 'V' THEN 'Visa'
ELSE 'Not in the portfolio'
END
Wynik:
+-----------+ | Company | |-----------| | Visa | +-----------+
W tym przykładzie mój CASE
wyrażenie jest częścią SELECT
oświadczenie. Sprawdza trzy warunki i ma ELSE
aby zaspokoić wszystko, co nie jest objęte tymi trzema warunkami.
W tym przypadku symbol giełdowy V
pasuje do trzeciego WHEN
wyrażenie i wyrażenie dostarczone przez THEN
jest zwracany.
Żeby było jasne, rzeczywisty CASE
wyrażenie to ta część:
CASE @stock_ticker
WHEN 'AAPL' THEN 'Apple'
WHEN 'FB' THEN 'Facebook'
WHEN 'MA' THEN 'Mastercard'
WHEN 'V' THEN 'Visa'
ELSE 'Not in the portfolio'
END
Jaki CASE
robi to, sprawdza wartość każdego WHEN
wyrażenie w stosunku do wyrażenia wejściowego. W moim przykładzie @stock_ticker
zmienna jest wyrażeniem wejściowym. Dlatego sprawdza wartość każdego WHEN
wyrażenie na @stock_ticker
zmienna.
Kiedy/jeśli znajdzie dopasowanie, zwraca wyrażenie dostarczone przez THEN
.
Mój przykład używa trzech WHEN
wyrażeń, ale mogło być więcej i mogło być mniej, w zależności od moich wymagań.
Formularz 2 – Przeszukiwane wyrażenie CASE
Wyszukiwany CASE
wyrażenie oblicza zestaw wyrażeń logicznych w celu określenia wyniku.
Oto przykład przeszukiwanego CASE
wyrażenie.
DECLARE @price int = 1500;
SELECT Affordability =
CASE
WHEN @price < 100 THEN 'Cheap'
WHEN @price >= 100 AND @price < 500 THEN 'Affordable'
ELSE 'Expensive'
END
Wynik:
+-----------------+ | Affordability | |-----------------| | Expensive | +-----------------+
Przeszukany CASE
wyrażenie nie ma wyrażenia wejściowego, takiego jak prosty CASE
wyrażenie.
Przypomnisz to sobie w naszym prostym CASE
wyrażenie, zaczęło się od CASE
@stock_ticker
, dlatego wiedzieliśmy, że WHEN
wszystkie wyrażenia były oceniane względem wartości @stock_ticker
.
Z wyszukiwanym CASE
wyrażenie, nie zapewniamy wyrażenia wejściowego na początku w ten sposób. Zamiast tego każde WHEN
wyrażenie zawiera wyrażenie logiczne, dla którego ma być oceniane.
Przykład bazy danych
Oto przykład, który pokazuje, jak CASE
wyrażenie może być użyte w zapytaniu do bazy danych.
USE WideWorldImporters;
SELECT
CityName AS [City],
LatestRecordedPopulation AS [Population],
Size =
CASE
WHEN LatestRecordedPopulation < 2000000 THEN 'Small City'
WHEN LatestRecordedPopulation >= 2000000 AND LatestRecordedPopulation < 3000000 THEN 'Big City'
ELSE 'Really Big City'
END
FROM Application.Cities
WHERE LatestRecordedPopulation > 1000000;
Wynik:
+--------------+--------------+-----------------+ | City | Population | Size | |--------------+--------------+-----------------| | Brooklyn | 2565635 | Big City | | Chicago | 2695598 | Big City | | Dallas | 1197816 | Small City | | Houston | 2099451 | Big City | | Los Angeles | 3792621 | Really Big City | | Manhattan | 1619090 | Small City | | New York | 8175133 | Really Big City | | Philadelphia | 1526006 | Small City | | Phoenix | 1445632 | Small City | | Queens | 2272771 | Big City | | San Antonio | 1327407 | Small City | | San Diego | 1307402 | Small City | | The Bronx | 1408473 | Small City | +--------------+--------------+-----------------+
W tym przykładzie użyto przeszukiwanego CASE
wyrażenie do oceny wyników z LatestRecordedPopulation
kolumna Application.Cities
stół.
Typy danych
W SQL Server typ danych wyrażenia wejściowego i WHEN
wyrażenia muszą być takie same lub muszą być niejawną konwersją.
Oto, co się stanie, jeśli nie są:
DECLARE @stock_ticker varchar(4) = 'V';
SELECT Company =
CASE @stock_ticker
WHEN 1 THEN 'Apple'
WHEN 2 THEN 'Facebook'
WHEN 3 THEN 'Mastercard'
WHEN 4 THEN 'Visa'
ELSE 'Not in the portfolio'
END
Wynik:
Msg 245, Level 16, State 1, Line 3 Conversion failed when converting the varchar value 'V' to data type int.
Kolejność oceny
T-SQL CASE
wyrażenie ocenia swoje warunki sekwencyjnie i zatrzymuje się na pierwszym warunku, którego warunek jest spełniony.
Aby to zademonstrować, użyjmy wielu opcji WHEN
wyrażenia, które mają tę samą wartość:
DECLARE @stock_ticker varchar(4) = 'V';
SELECT Company =
CASE @stock_ticker
WHEN 'V' THEN 'Visa 1'
WHEN 'V' THEN 'Visa 2'
WHEN 'V' THEN 'Visa 3'
ELSE 'Not in the portfolio'
END
Wynik:
+-----------+ | Company | |-----------| | Visa 1 | +-----------+
W tym przypadku zatrzymał się przy pierwszym WHEN
wyrażenie.
Może wystąpić sporadyczny scenariusz, w którym wyrażenie jest oceniane przed CASE
wyrażenie otrzymuje wyniki wyrażenia jako dane wejściowe. W takich sytuacjach możesz skończyć z błędem. Może się tak zdarzyć, jeśli dodasz wyrażenie agregujące jako WHEN
wyrażenie.
Z tego powodu firma Microsoft zaleca, aby:
Powinieneś polegać tylko na kolejności oceny warunków WHEN dla wyrażeń skalarnych (w tym nieskorelowanych podzapytań zwracających skalary), a nie dla wyrażeń agregujących.
INNE jest opcjonalne
ELSE
argument jest opcjonalny. Dlatego moglibyśmy przepisać nasz przykład „przystępności cenowej” w następujący sposób:
DECLARE @price int = 1500;
SELECT Affordability =
CASE
WHEN @price < 100 THEN 'Cheap'
WHEN @price >= 100 AND @price < 500 THEN 'Affordable'
WHEN @price >= 500 THEN 'Expensive'
END
Wynik:
+-----------------+ | Affordability | |-----------------| | Expensive | +-----------------+
Pamiętaj jednak, że możesz skończyć z NULL
jeśli pominiesz ELSE
argument.
Poniższy przykład daje wynik NULL
:
DECLARE @price int = 1500;
SELECT Affordability =
CASE
WHEN @price < 100 THEN 'Cheap'
WHEN @price >= 100 AND @price < 500 THEN 'Affordable'
WHEN @price >= 500 AND @price < 1000 THEN 'Expensive'
END
Wynik:
+-----------------+ | Affordability | |-----------------| | NULL | +-----------------+
W takich przypadkach zawsze możemy dodać ELSE
argument, na wszelki wypadek (przepraszam za kalambur!):
DECLARE @price int = 1500;
SELECT Affordability =
CASE
WHEN @price < 100 THEN 'Cheap'
WHEN @price >= 100 AND @price < 500 THEN 'Affordable'
WHEN @price >= 500 AND @price < 1000 THEN 'Expensive'
ELSE 'Unknown'
END
Wynik:
+-----------------+ | Affordability | |-----------------| | Unknown | +-----------------+
Trzeba przyznać, że ten przykład jest prawdopodobnie nieco wymyślny. W końcu nie ma potrzeby ograniczania „drogo”. Jeśli coś jest drogie poniżej 1000 USD, jest również drogie, jeśli przekracza 1000 USD.
Ale chodzi o to, że możesz użyć ELSE
złapać wszystko, co nie jest objęte WHEN
wyrażenie/s.
Zagnieżdżone wyrażenia CASE
Możesz zagnieździć CASE
wyrażenia, jeśli są wymagane.
DECLARE @price int, @on_sale bit;
SET @price = 1500;
SET @on_sale = 1;
SELECT Affordability =
CASE
WHEN @price < 100 THEN 'Cheap'
WHEN @price >= 100 THEN
CASE @on_sale
WHEN 0 THEN 'Expensive (but it''s not currently on sale)'
WHEN 1 THEN 'Expensive (and it''s already on sale!)'
END
END
Wynik:
+---------------------------------------+ | Affordability | |---------------------------------------| | Expensive (and it's already on sale!) | +---------------------------------------+
Należy jednak pamiętać, że tylko 10 poziomów zagnieżdżenia jest dozwolonych dla CASE
wyrażenia w SQL Server. Jeśli spróbujesz zagnieździć więcej niż 10 poziomów, pojawi się błąd.
SPRAWA w klauzuli ORDER BY
Jak wspomniano, T-SQL CASE
wyrażenie może być użyte w dowolnej instrukcji lub klauzuli, która zezwala na prawidłowe wyrażenie. Dlatego możesz go używać w instrukcjach takich jak SELECT
, UPDATE
, DELETE
i SET
oraz w klauzulach, takich jak IN
, WHERE
, ORDER BY
, GROUP BY
i HAVING
.
Używanie CASE
wyrażenie w ORDER BY
instrukcji Klauzula może być przydatna, gdy chcesz zrobić specjalny wyjątek dla pewnych wartości podczas porządkowania wyników.
Załóżmy, że uruchamiamy następujące zapytanie w tabeli zawierającej gatunki muzyczne.
SELECT Genre
FROM MusicGenres
ORDER BY Genre ASC;
Wynik:
+---------+ | Genre | |---------| | Blues | | Country | | Hip Hop | | Jazz | | Metal | | Other | | Pop | | Rap | | Rock | +---------+
Tutaj sortujemy wyniki według Genre
kolumna w porządku rosnącym.
To jest w porządku, z wyjątkiem jednej rzeczy. Gatunek o nazwie Inne . Czy nie byłoby miło, gdybyśmy mogli przenieść Inne na sam dół?
Możemy to osiągnąć za pomocą CASE
wyrażenie, biorąc powyższe zapytanie i modyfikując je w następujący sposób.
SELECT Genre
FROM MusicGenres
ORDER BY
CASE Genre
WHEN 'Other' THEN 1
ELSE 0
END
ASC, Genre ASC;
Wynik:
+---------+ | Genre | |---------| | Blues | | Country | | Hip Hop | | Jazz | | Metal | | Pop | | Rap | | Rock | | Other | +---------+
CASE w instrukcji UPDATE
Oto przykład użycia CASE
wyrażenie w UPDATE
oświadczenie.
Załóżmy, że mamy następującą tabelę:
+---------+-----------+-----------+----------+ | DogId | DogName | GoodDog | Dinner | |---------+-----------+-----------+----------| | 1 | Fetch | 1 | NULL | | 2 | Fluffy | 0 | NULL | | 3 | Wag | 0 | NULL | | 1001 | Brian | 1 | NULL | | 1002 | Rambo | 0 | NULL | | 1003 | BamBam | 1 | NULL | +---------+-----------+-----------+----------+
Niedawno dodaliśmy Dinner
kolumna i nadal jest NULL
, czekając na wstawienie wartości.
Ale wstawiane wartości będą zależeć od wartości GoodDog
kolumna.
Moglibyśmy użyć CASE
wyrażenie w takim scenariuszu.
UPDATE Dogs
SET Dinner =
CASE GoodDog
WHEN 1 THEN 'Sunday Roast'
ELSE 'Airline food'
END
SELECT * FROM Dogs;
Wynik:
+---------+-----------+-----------+--------------+ | DogId | DogName | GoodDog | Dinner | |---------+-----------+-----------+--------------| | 1 | Fetch | 1 | Sunday Roast | | 2 | Fluffy | 0 | Airline food | | 3 | Wag | 0 | Airline food | | 1001 | Brian | 1 | Sunday Roast | | 1002 | Rambo | 0 | Airline food | | 1003 | BamBam | 1 | Sunday Roast | +---------+-----------+-----------+--------------+
CASE w instrukcji INSERT
Możemy wziąć tabelę z powyższego przykładu i wstawić nową wartość.
I znowu możemy skorzystać z CASE
wyrażenie do wstawienia odpowiedniej wartości do Dinner
kolumna.
DECLARE @DogName nvarchar(60), @GoodDog bit;
SET @DogName = 'Lazy';
SET @GoodDog = 0;
INSERT INTO Dogs ( DogName, GoodDog, Dinner )
VALUES (
@DogName,
@GoodDog,
CASE @GoodDog
WHEN 1 THEN 'Sunday Roast'
ELSE 'Airline food'
END
);
SELECT * FROM Dogs;
Wynik:
+---------+-----------+-----------+--------------+ | DogId | DogName | GoodDog | Dinner | |---------+-----------+-----------+--------------| | 1 | Fetch | 1 | Sunday Roast | | 2 | Fluffy | 0 | Airline food | | 3 | Wag | 0 | Airline food | | 1001 | Brian | 1 | Sunday Roast | | 1002 | Rambo | 0 | Airline food | | 1003 | BamBam | 1 | Sunday Roast | | 1004 | Lazy | 0 | Airline food | +---------+-----------+-----------+--------------+
Tym razem CASE
wyrażenie oceniało wartość zmiennej, którą właśnie ustawiliśmy, a następnie wstawiało odpowiednią wartość do Dinner
kolumna.
Czy jest to instrukcja CASE czy wyrażenie CASE?
W SQL wiele rzeczy jest określanych jako „oświadczenie”, podczas gdy w rzeczywistości jest to coś innego. Wydaje się, że dotyczy to również T-SQL „CASE
oświadczenie”.
Chociaż często jest określany jako CASE
oświadczenie, lepiej nazywać to CASE
wyrażenie . Tak też odnosi się do tego dokumentacja Microsoft.
W SQL Server, zamiast być samą instrukcją, CASE
może być użyty w dowolnej instrukcji lub klauzuli, która zezwala na prawidłowe wyrażenie. Wyrażenie to kombinacja symboli i operatorów, które są oceniane w celu uzyskania pojedynczej wartości danych.
Jednak niektóre DBMS rozróżniają CASE
oświadczenie i CASE
wyrażenie i mają nieco inną składnię dla każdego. MySQL rozróżnia CASE
oświadczenie i CASE
operator, który jest zasadniczo taki sam jak CASE
wyrażenie.