I SQL er CASE
sætning evaluerer en liste over betingelser og returnerer et af flere mulige resultatudtryk.
På nogle måder er SQL CASE
sætningen ligner IF...ELSE
erklæring ved, at det giver os mulighed for at tjekke for en given tilstand og returnere et andet resultat afhængigt af resultatet.
Er det en CASE
Erklæring eller CASE
Udtryk?
I SQL omtales ting nogle gange som en "erklæring", når de faktisk er noget andet. SQL'en "CASE
statement” er et eksempel (undskyld ordspillet!).
CASE
sætning omtales i SQL-standarden (ISO/IEC 9075) som CASE
udtryk . Dens formål er at "specificere en betinget værdi".
Nogle DBMS'er skelner dog mellem CASE
sætning og CASE
udtryk og har en lidt forskellig syntaks for hver. For eksempel leverer både MySQL og MariaDB CASE
sætning og CASE
operator som to forskellige funktioner, hver med lidt forskellig syntaks.
CASE
Formater
I SQL er der to formater af CASE
udtryk:
- Simpel
CASE
udtryk - Søgte i
CASE
udtryk
Nedenfor er eksempler på hver.
Den simple CASE
Udtryk
Den simple CASE
udtryk sammenligner et udtryk med et sæt simple udtryk for at bestemme resultatet.
Eksempel:
DECLARE @animal VARCHAR(40);
SET @animal = 'Cow';
SELECT
CASE @animal
WHEN 'Bird' THEN 'Seed'
WHEN 'Dog' THEN 'Beef'
WHEN 'Cow' THEN 'Grass'
ELSE 'Leftovers'
END;
Resultat:
Grass
Dette eksempel blev udført i MySQL, men den faktiske CASE
udtryk bør fungere på tværs af de fleste større RDBMS'er.
I dette eksempel er min CASE
udtryk er en del af en SELECT
udmelding. Den tjekker for tre forhold og har en ELSE
at tage højde for alt, der ikke er dækket af de tre betingelser.
I dette tilfælde dyret Cow
matcher den tredje WHEN
udtryk og udtrykket leveret af dets THEN
er returneret.
For at være klar, den faktiske CASE
udtryk er denne del:
CASE @animal
WHEN 'Bird' THEN 'Seed'
WHEN 'Dog' THEN 'Beef'
WHEN 'Cow' THEN 'Grass'
ELSE 'Leftovers'
END
Hvilken CASE
er at kontrollere værdien af hver WHEN
udtryk mod inputudtrykket. I dette eksempel er @animal
variabel er input-udtrykket. Derfor tjekker den værdien af hver WHEN
udtryk mod @animal
variabel.
Når/hvis den finder et match, returnerer den udtrykket leveret af den tilsvarende THEN
.
Mit eksempel bruger tre WHEN
udtryk, men jeg kunne have brugt mere, og jeg kunne have brugt mindre, afhængig af kravene.
Den søgte CASE
Udtryk
Den søgte CASE
udtryk evaluerer et sæt boolske udtryk for at bestemme resultatet.
Her er et eksempel på en søgt CASE
udtryk.
DECLARE @score int;
SET @score = 7;
SELECT
CASE
WHEN @score > 8 THEN 'Congratulations!'
WHEN @score > 5 AND @score < 8 THEN 'Well done!'
ELSE 'Try harder next time'
END;
Resultat:
Well done!
Den søgte CASE
udtryk har ikke et input-udtryk som den simple CASE
udtryk.
Du husker det i vores simple CASE
udtryk, det startede med CASE
@animal
, og derfor vidste vi, at WHEN
alle udtryk blev evalueret mod værdien af @animal
.
Med den søgte CASE
udtryk, giver vi ikke et input-udtryk i starten på den måde. I stedet skal hver WHEN
udtryk inkluderer et boolesk udtryk, som der skal evalueres i forhold til.
Et databaseeksempel
Her er et eksempel, der viser, hvordan CASE
udtryk kan bruges i en databaseforespørgsel.
USE World;
SELECT
Name,
Population,
CASE
WHEN Population > 2000000 THEN 'Huge City'
WHEN Population >= 1000000 AND Population < 2000000 THEN 'Big City'
ELSE 'Small City'
END AS Size
FROM City
WHERE CountryCode = 'USA'
ORDER BY Population DESC
LIMIT 20;
Resultat:
+---------------+------------+------------+ | Name | Population | Size | +---------------+------------+------------+ | New York | 8008278 | Huge City | | Los Angeles | 3694820 | Huge City | | Chicago | 2896016 | Huge City | | Houston | 1953631 | Big City | | Philadelphia | 1517550 | Big City | | Phoenix | 1321045 | Big City | | San Diego | 1223400 | Big City | | Dallas | 1188580 | Big City | | San Antonio | 1144646 | Big City | | Detroit | 951270 | Small City | | San Jose | 894943 | Small City | | Indianapolis | 791926 | Small City | | San Francisco | 776733 | Small City | | Jacksonville | 735167 | Small City | | Columbus | 711470 | Small City | | Austin | 656562 | Small City | | Baltimore | 651154 | Small City | | Memphis | 650100 | Small City | | Milwaukee | 596974 | Small City | | Boston | 589141 | Small City | +---------------+------------+------------+
Dette eksempel bruger en søgt CASE
udtryk for at evaluere resultaterne fra Population
kolonne i City
bord.
ELSE
er valgfrit
ELSE
argument er valgfrit. Hvis vi udelader ELSE
, og ingen af betingelserne udløses, er resultatet NULL
.
Her er, hvad der sker, når vi udelader ELSE
klausul fra det foregående eksempel:
USE World;
SELECT
Name,
Population,
CASE
WHEN Population > 2000000 THEN 'Huge City'
WHEN Population >= 1000000 AND Population < 2000000 THEN 'Big City'
END AS Size
FROM City
WHERE CountryCode = 'USA'
ORDER BY Population DESC
LIMIT 20;
Resultat:
+---------------+------------+-----------+ | Name | Population | Size | +---------------+------------+-----------+ | New York | 8008278 | Huge City | | Los Angeles | 3694820 | Huge City | | Chicago | 2896016 | Huge City | | Houston | 1953631 | Big City | | Philadelphia | 1517550 | Big City | | Phoenix | 1321045 | Big City | | San Diego | 1223400 | Big City | | Dallas | 1188580 | Big City | | San Antonio | 1144646 | Big City | | Detroit | 951270 | NULL | | San Jose | 894943 | NULL | | Indianapolis | 791926 | NULL | | San Francisco | 776733 | NULL | | Jacksonville | 735167 | NULL | | Columbus | 711470 | NULL | | Austin | 656562 | NULL | | Baltimore | 651154 | NULL | | Memphis | 650100 | NULL | | Milwaukee | 596974 | NULL | | Boston | 589141 | NULL | +---------------+------------+-----------+
CASE
i en UPDATE
Erklæring
Lad os tilføje en kolonne til City
tabel fra det foregående eksempel:
ALTER TABLE City
ADD COLUMN Size VARCHAR(30) AFTER Population;
SELECT * FROM City
LIMIT 10;
Sådan ser det ud nu:
+----+----------------+-------------+---------------+------------+------+ | ID | Name | CountryCode | District | Population | Size | +----+----------------+-------------+---------------+------------+------+ | 1 | Kabul | AFG | Kabol | 1780000 | NULL | | 2 | Qandahar | AFG | Qandahar | 237500 | NULL | | 3 | Herat | AFG | Herat | 186800 | NULL | | 4 | Mazar-e-Sharif | AFG | Balkh | 127800 | NULL | | 5 | Amsterdam | NLD | Noord-Holland | 731200 | NULL | | 6 | Rotterdam | NLD | Zuid-Holland | 593321 | NULL | | 7 | Haag | NLD | Zuid-Holland | 440900 | NULL | | 8 | Utrecht | NLD | Utrecht | 234323 | NULL | | 9 | Eindhoven | NLD | Noord-Brabant | 201843 | NULL | | 10 | Tilburg | NLD | Noord-Brabant | 193238 | NULL | +----+----------------+-------------+---------------+------------+------+
Vi har ikke indsat nogen data i den nye Size
kolonne, så den returnerer NULL
i hver række.
Vi kan nu bruge en CASE
udtryk for at opdatere Size
kolonne med en værdi, der afhænger af værdien i Population
kolonne:
UPDATE City
SET Size =
CASE
WHEN Population > 2000000 THEN 'Huge City'
WHEN Population >= 1000000 AND Population < 2000000 THEN 'Big City'
ELSE 'Small City'
END;
Lad os nu vælge data fra tabellen:
SELECT * FROM City
WHERE CountryCode = 'USA'
ORDER BY Population DESC
LIMIT 20;
Resultat:
+------+---------------+-------------+---------------+------------+------------+ | ID | Name | CountryCode | District | Population | Size | +------+---------------+-------------+---------------+------------+------------+ | 3793 | New York | USA | New York | 8008278 | Huge City | | 3794 | Los Angeles | USA | California | 3694820 | Huge City | | 3795 | Chicago | USA | Illinois | 2896016 | Huge City | | 3796 | Houston | USA | Texas | 1953631 | Big City | | 3797 | Philadelphia | USA | Pennsylvania | 1517550 | Big City | | 3798 | Phoenix | USA | Arizona | 1321045 | Big City | | 3799 | San Diego | USA | California | 1223400 | Big City | | 3800 | Dallas | USA | Texas | 1188580 | Big City | | 3801 | San Antonio | USA | Texas | 1144646 | Big City | | 3802 | Detroit | USA | Michigan | 951270 | Small City | | 3803 | San Jose | USA | California | 894943 | Small City | | 3804 | Indianapolis | USA | Indiana | 791926 | Small City | | 3805 | San Francisco | USA | California | 776733 | Small City | | 3806 | Jacksonville | USA | Florida | 735167 | Small City | | 3807 | Columbus | USA | Ohio | 711470 | Small City | | 3808 | Austin | USA | Texas | 656562 | Small City | | 3809 | Baltimore | USA | Maryland | 651154 | Small City | | 3810 | Memphis | USA | Tennessee | 650100 | Small City | | 3811 | Milwaukee | USA | Wisconsin | 596974 | Small City | | 3812 | Boston | USA | Massachusetts | 589141 | Small City | +------+---------------+-------------+---------------+------------+------------+
CASE
i en INSERT
Erklæring
Antag, at vi har følgende tabel i en SQL Server-database:
+---------+-----------+-----------+--------------+ | DogId | DogName | GoodDog | Dinner | |---------+-----------+-----------+--------------| | 1001 | Brian | 1 | Sunday Roast | | 1002 | Rambo | 0 | Airline food | | 1003 | BamBam | 1 | Sunday Roast | +---------+-----------+-----------+--------------+
Lad os indsætte en ny række i den tabel. Men lad os bruge CASE
udtryk for at indsætte den passende værdi i Dinner
kolonne, afhængigt af værdien i GoodDog
kolonne:
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
);
Her er CASE
expression evaluerede værdien af en variabel, vi lige havde indstillet, og indsatte derefter den passende værdi i Dinner
kolonne.
Lad os nu tjekke tabellen igen:
SELECT * FROM Dogs;
Resultat:
+---------+-----------+-----------+--------------+ | DogId | DogName | GoodDog | Dinner | |---------+-----------+-----------+--------------| | 1001 | Brian | 1 | Sunday Roast | | 1002 | Rambo | 0 | Airline food | | 1003 | BamBam | 1 | Sunday Roast | | 1004 | Lazy | 0 | Airline food | +---------+-----------+-----------+--------------+
Vi kan se, at den passende værdi er i Dinner
kolonne.
CASE
i en ORDER BY
Klausul
CASE
udtryk kan bruges i enhver sætning eller klausul, der tillader et gyldigt udtryk. Derfor kan du bruge det i sætninger såsom SELECT
, UPDATE
, DELETE
og SET
, og i klausuler såsom IN
, WHERE
, ORDER BY
, GROUP BY
og HAVING
.
Brug af en CASE
udtryk i en sætnings ORDER BY
klausul kan være praktisk, når du vil gøre en særlig undtagelse for bestemte værdier, når du bestiller dine resultater.
Antag, at vi kører følgende forespørgsel mod en tabel, der indeholder musikgenrer.
SELECT Genre
FROM Genres
ORDER BY Genre ASC;
Resultat:
+---------+ | Genre | +---------+ | Blues | | Country | | Hip Hop | | Jazz | | Other | | Pop | | Punk | | Rap | | Rock | +---------+
Her sorterer vi resultaterne efter Genre
kolonne i stigende rækkefølge.
Det er fint bortset fra én ting. Genren kaldet Other
. Ville det ikke være rart, hvis vi kunne flytte Other
til bunden?
Vi kan opnå dette med CASE
udtryk ved at tage ovenstående forespørgsel og ændre den som følger.
SELECT Genre
FROM Genres
ORDER BY
CASE Genre
WHEN 'Other' THEN 1
ELSE 0
END
ASC, Genre ASC;
Resultat:
+---------+ | Genre | +---------+ | Blues | | Country | | Hip Hop | | Jazz | | Pop | | Punk | | Rap | | Rock | | Other | +---------+
COALESCE()
og NULLIF()
Funktioner
Afhængigt af scenariet kan vi bruge funktioner såsom COALESCE()
og NULLIF()
som en genvej i stedet for at bruge CASE
udtryk.
Disse to funktioner er SQL-standard, og de fungerer som følger:
NULLIF (V1, V2)
Er svarende til:
CASE WHEN V1=V2 THEN NULL ELSE V1 END
Og:
COALESCE (V1, V2)
Er svarende til:
CASE WHEN V1 IS NOT NULL THEN V1 ELSE V2 END
Også:
COALESCE (V1, V2, ..., Vn)
Er svarende til:
CASE WHEN V1 IS NOT NULL THEN V1 ELSE COALESCE (V2, ..., Vn) END