In SQL Server is de T-SQL CASE
expressie is een scalaire expressie die een waarde retourneert op basis van voorwaardelijke logica. Het evalueert een lijst met voorwaarden en retourneert een waarde, gebaseerd op de uitkomst van die voorwaarden..
In sommige opzichten is de SQL Server CASE
uitdrukking lijkt op IF...ELSE
. Echter, CASE
stelt u in staat om te controleren op meerdere voorwaarden, terwijl IF...ELSE
niet.
In SQL Server, IF...ELSE
is een trefwoord voor controle van de stroomtaal, terwijl CASE
is niet. De CASE
expressie kan niet worden gebruikt om de uitvoeringsstroom van T-SQL-instructies, instructieblokken, door de gebruiker gedefinieerde functies en opgeslagen procedures te regelen.
De 2 vormen van CASE-expressie
Er zijn twee vormen van CASE
uitdrukking in SQL Server:
- Eenvoudige
CASE
uitdrukking - Gezocht
CASE
uitdrukking
Deze worden hieronder toegelicht met voorbeelden.
Formulier 1 – De eenvoudige CASE-expressie
De eenvoudige CASE
uitdrukking vergelijkt een uitdrukking met een reeks eenvoudige uitdrukkingen om het resultaat te bepalen.
Hier is een eenvoudig voorbeeld om te demonstreren hoe een CASE
expressie werkt in 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
Resultaat:
+-----------+ | Company | |-----------| | Visa | +-----------+
In dit voorbeeld is mijn CASE
expressie maakt deel uit van een SELECT
uitspraak. Het controleert op drie voorwaarden en heeft een ELSE
om te voorzien in alles wat niet onder de drie voorwaarden valt.
In dit geval is de aandelenticker V
komt overeen met de derde WHEN
uitdrukking, en de uitdrukking geleverd door THEN
wordt geretourneerd.
Voor alle duidelijkheid:de eigenlijke CASE
uitdrukking is dit deel:
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
Wat CASE
doet is, het controleert de waarde van elke WHEN
expressie tegen de invoerexpressie. In mijn voorbeeld, de @stock_ticker
variabele is de invoerexpressie. Daarom controleert het de waarde van elke WHEN
uitdrukking tegen de @stock_ticker
variabel.
Wanneer/als het een overeenkomst vindt, retourneert het de uitdrukking die wordt gegeven door THEN
.
Mijn voorbeeld gebruikt drie WHEN
uitdrukkingen, maar het had meer en minder kunnen zijn, afhankelijk van mijn vereisten.
Formulier 2 – De gezochte CASE-expressie
De gezochte CASE
expression evalueert een set Booleaanse expressies om het resultaat te bepalen.
Hier is een voorbeeld van een gezochte CASE
uitdrukking.
DECLARE @price int = 1500;
SELECT Affordability =
CASE
WHEN @price < 100 THEN 'Cheap'
WHEN @price >= 100 AND @price < 500 THEN 'Affordable'
ELSE 'Expensive'
END
Resultaat:
+-----------------+ | Affordability | |-----------------| | Expensive | +-----------------+
Een gezochte CASE
expressie heeft geen invoerexpressie zoals de eenvoudige CASE
uitdrukking.
U herinnert zich dat in onze eenvoudige CASE
uitdrukking, het begon met CASE
@stock_ticker
, en daarom wisten we dat de WHEN
uitdrukkingen evalueerden allemaal tegen de waarde van @stock_ticker
.
Met de gezochte CASE
expressie, bieden we aan het begin geen invoerexpressie op die manier. In plaats daarvan wordt elke WHEN
expressie bevat een Booleaanse expressie waarvoor geëvalueerd moet worden.
Een databasevoorbeeld
Hier is een voorbeeld dat laat zien hoe de CASE
expressie kan worden gebruikt binnen een databasequery.
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;
Resultaat:
+--------------+--------------+-----------------+ | 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 | +--------------+--------------+-----------------+
Dit voorbeeld gebruikt een gezochte CASE
expressie om de resultaten van de LatestRecordedPopulation
. te evalueren kolom van de Application.Cities
tafel.
Gegevenstypen
In SQL Server, het gegevenstype van de invoerexpressie en de WHEN
uitdrukkingen moeten hetzelfde zijn of moeten een impliciete conversie zijn.
Dit is wat er gebeurt als ze dat niet zijn:
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
Resultaat:
Msg 245, Level 16, State 1, Line 3 Conversion failed when converting the varchar value 'V' to data type int.
Orde van evaluatie
De T-SQL CASE
expressie evalueert zijn voorwaarden opeenvolgend en stopt met de eerste voorwaarde waarvan aan de voorwaarde is voldaan.
Laten we om dit te demonstreren meerdere WHEN
. gebruiken uitdrukkingen die dezelfde waarde delen:
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
Resultaat:
+-----------+ | Company | |-----------| | Visa 1 | +-----------+
In dit geval stopte het bij de eerste WHEN
uitdrukking.
Er kan zich een incidenteel scenario voordoen waarbij een uitdrukking wordt geëvalueerd vóór een CASE
expressie ontvangt de resultaten van de expressie als invoer. In dergelijke scenario's kunt u een fout krijgen. Dit kan gebeuren als u een geaggregeerde expressie opneemt als de WHEN
uitdrukking.
Om deze reden adviseert Microsoft dat:
U mag alleen afhankelijk zijn van de evaluatievolgorde van de WHEN-voorwaarden voor scalaire expressies (inclusief niet-gecorreleerde subquery's die scalaire waarden retourneren), niet voor geaggregeerde expressies.
ELSE is optioneel
De ELSE
argument is optioneel. Daarom zouden we ons voorbeeld van "betaalbaarheid" als volgt kunnen herschrijven:
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
Resultaat:
+-----------------+ | Affordability | |-----------------| | Expensive | +-----------------+
Houd er echter rekening mee dat u kunt eindigen met NULL
als u de ELSE
. weglaat argument.
Het volgende voorbeeld resulteert in 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
Resultaat:
+-----------------+ | Affordability | |-----------------| | NULL | +-----------------+
In dergelijke gevallen kunnen we altijd een ELSE
. toevoegen argument, voor het geval dat (sorry voor de woordspeling!):
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
Resultaat:
+-----------------+ | Affordability | |-----------------| | Unknown | +-----------------+
Toegegeven, dit voorbeeld is waarschijnlijk een beetje gekunsteld. Het is tenslotte niet nodig om "duur" te begrenzen. Als iets duur is voor minder dan $ 1000, dan is het ook duur als het meer dan $ 1000 is.
Maar het punt is dat je ELSE
. kunt gebruiken om iets te vangen dat niet onder de WHEN
. valt uitdrukking/en.
Geneste CASE-expressies
U kunt CASE
nesten uitdrukkingen indien nodig.
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
Resultaat:
+---------------------------------------+ | Affordability | |---------------------------------------| | Expensive (and it's already on sale!) | +---------------------------------------+
Het is echter belangrijk op te merken dat er slechts 10 niveaus van nesting zijn toegestaan voor CASE
expressies in SQL Server. Als je meer dan 10 niveaus probeert te nesten, krijg je een foutmelding.
GEVAL in een ORDER BY-clausule
Zoals gezegd, de T-SQL CASE
expressie kan worden gebruikt in elke instructie of clausule die een geldige expressie toestaat. Daarom kunt u het gebruiken in instructies zoals SELECT
, UPDATE
, DELETE
en SET
, en in clausules zoals IN
, WHERE
, ORDER BY
, GROUP BY
, en HAVING
.
Een CASE
gebruiken uitdrukking in de ORDER BY
. van een instructie clausule kan handig zijn wanneer u een speciale uitzondering wilt maken voor bepaalde waarden bij het bestellen van uw resultaten.
Stel dat we de volgende query uitvoeren op een tabel met muziekgenres.
SELECT Genre
FROM MusicGenres
ORDER BY Genre ASC;
Resultaat:
+---------+ | Genre | |---------| | Blues | | Country | | Hip Hop | | Jazz | | Metal | | Other | | Pop | | Rap | | Rock | +---------+
Hier rangschikken we de resultaten op Genre
kolom, in oplopende volgorde.
Dit is prima, op één ding na. Het genre genaamd Overig . Zou het niet mooi zijn als we Overig . konden verplaatsen naar beneden?
We kunnen dit bereiken met de CASE
expressie door de bovenstaande query te nemen en deze als volgt aan te passen.
SELECT Genre
FROM MusicGenres
ORDER BY
CASE Genre
WHEN 'Other' THEN 1
ELSE 0
END
ASC, Genre ASC;
Resultaat:
+---------+ | Genre | |---------| | Blues | | Country | | Hip Hop | | Jazz | | Metal | | Pop | | Rap | | Rock | | Other | +---------+
CASE in een UPDATE-instructie
Hier is een voorbeeld van het gebruik van een CASE
uitdrukking in een UPDATE
verklaring.
Stel dat we de volgende tabel hebben:
+---------+-----------+-----------+----------+ | 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 | +---------+-----------+-----------+----------+
We hebben onlangs het Dinner
. toegevoegd kolom, en het is nog steeds NULL
, wachtend op het invoegen van waarden.
Maar de in te voegen waarden zijn afhankelijk van de waarde van de GoodDog
kolom.
We zouden een CASE
kunnen gebruiken uitdrukking in een dergelijk scenario.
UPDATE Dogs
SET Dinner =
CASE GoodDog
WHEN 1 THEN 'Sunday Roast'
ELSE 'Airline food'
END
SELECT * FROM Dogs;
Resultaat:
+---------+-----------+-----------+--------------+ | 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 in een INSERT-instructie
We kunnen de tabel uit het bovenstaande voorbeeld nemen en een nieuwe waarde invoegen.
En we kunnen weer profiteren van de CASE
expressie om de juiste waarde in te voegen in het Dinner
kolom.
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;
Resultaat:
+---------+-----------+-----------+--------------+ | 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 | +---------+-----------+-----------+--------------+
Deze keer de CASE
expressie evalueerde de waarde van een variabele die we zojuist hadden ingesteld en voegde vervolgens de juiste waarde toe aan het Dinner
kolom.
Is het een CASE-statement of CASE-expressie?
In SQL worden veel dingen een "statement" genoemd, terwijl ze in feite iets anders zijn. Dit lijkt ook te gelden voor de T-SQL “CASE
verklaring”.
Hoewel er vaak naar wordt verwezen als de CASE
statement, is het nauwkeuriger om het de CASE
. te noemen uitdrukking . Dit is ook hoe de Microsoft-documentatie ernaar verwijst.
In SQL Server is CASE
. geen instructie zelf, maar kan worden gebruikt in elke instructie of clausule die een geldige expressie toestaat. Een uitdrukking is een combinatie van symbolen en operatoren die worden geëvalueerd om een enkele gegevenswaarde te verkrijgen.
Sommige DBMS'en maken echter onderscheid tussen de CASE
statement, en de CASE
expressie, en hebben voor elk een iets andere syntaxis. MySQL maakt onderscheid tussen de CASE
statement en de CASE
operator, die in wezen hetzelfde is als de CASE
uitdrukking.