I SQL Server, T-SQL CASE
expression är ett skalärt uttryck som returnerar ett värde baserat på villkorlig logik. Den utvärderar en lista med villkor och returnerar ett värde, baserat på resultatet av dessa villkor.
På vissa sätt, SQL Server CASE
uttryck liknar IF...ELSE
. Men CASE
låter dig söka efter flera villkor, medan IF...ELSE
inte.
I SQL Server, IF...ELSE
är ett flödesstyrt språknyckelord, medan CASE
är inte. CASE
expression kan inte användas för att styra flödet av exekvering av T-SQL-satser, programsatsblock, användardefinierade funktioner och lagrade procedurer.
De två formerna för CASE-uttryck
Det finns två former av CASE
uttryck i SQL Server:
- Enkelt
CASE
uttryck - Sökte i
CASE
uttryck
Dessa förklaras med exempel nedan.
Formulär 1 – Det enkla CASE-uttrycket
Det enkla CASE
expression jämför ett uttryck med en uppsättning enkla uttryck för att bestämma resultatet.
Här är ett grundläggande exempel för att visa hur ett CASE
uttryck fungerar i SQL Server.
DECLARE @stock_ticker varchar(4) ='V';SELECT Company =CASE @stock_ticker NÄR 'AAPL' SEN 'Apple' NÄR 'FB' SEN 'Facebook' NÄR 'V' SEN 'Visa' ANNAT ' Inte i portföljen' END
Resultat:
+------------+| Företag ||-----------|| Visa |+-----------+
I det här exemplet, mitt CASE
uttryck är en del av en SELECT
påstående. Den söker efter tre villkor och har en ELSE
för att tillgodose allt som inte omfattas av de tre villkoren.
I det här fallet är aktiekursen V
matchar den tredje WHEN
uttryck och uttrycket som tillhandahålls av THEN
returneras.
För att vara tydlig, det faktiska CASE
uttryck är denna del:
CASE @stock_ticker NÄR 'AAPL' SEDAN 'Apple' NÄR 'FB' SEN 'Facebook' NÄR 'MA' SEN 'Mastercard' NÄR 'V' SEN 'Visa' ANNARS 'Inte i portföljen' SLUT
Vad CASE
gör är att den kontrollerar värdet för varje WHEN
uttryck mot inmatningsuttrycket. I mitt exempel, @stock_ticker
variabel är inmatningsuttrycket. Därför kontrollerar den värdet för varje WHEN
uttryck mot @stock_ticker
variabel.
När/om den hittar en matchning, returnerar den uttrycket som tillhandahålls av THEN
.
Mitt exempel använder tre WHEN
uttryck, men det kunde ha varit fler och det kunde ha varit mindre, beroende på mina krav.
Formulär 2 – Det sökta CASE-uttrycket
Det sökta CASE
expression utvärderar en uppsättning booleska uttryck för att bestämma resultatet.
Här är ett exempel på ett sökt CASE
uttryck.
DECLARE @price int =1500;VÄLJ Prisvärdhet =CASE WHEN @price <100 DÅ "Billigt" NÄR @price>=100 OCH @price <500 DÅ "Prisvärd" ANNARS "Dyrt" SLUT
Resultat:
+----------------+| Prisvärd ||----------------|| Dyrt |+-----------------+
Ett sökt CASE
uttryck har inte ett inmatningsuttryck som det enkla CASE
uttryck.
Du kommer ihåg det i vårt enkla CASE
uttryck började det med CASE
@stock_ticker
, och därför visste vi att WHEN
alla uttryck utvärderades mot värdet på @stock_ticker
.
Med den sökta CASE
uttryck, vi tillhandahåller inte ett inmatningsuttryck i början på det sättet. Istället, varje WHEN
uttryck inkluderar ett booleskt uttryck som det ska utvärderas mot.
Ett databasexempel
Här är ett exempel som visar hur CASE
uttryck kan användas i en databasfråga.
ANVÄND WideWorldImporters;VÄLJ Stadsnamn SOM [Stad], LatestRecordedPopulation AS [Population], Size =CASE NÄR SenasteRecordedPopulation <2000000 SÅ "Small City" NÄR SenasteRecordedPopulation>=20000000 The RecordedP0Big. Really Big City' END FROM Application.CitiesWHERE LatestRecordedPopulation> 1000000;
Resultat:
+--------------+-------------+---------------- -+| Stad | Befolkning | Storlek ||--------------+--------------+---------------- || Brooklyn | 2565635 | Storstad || Chicago | 2695598 | Storstad || Dallas | 1197816 | Liten stad || Houston | 2099451 | Storstad || Los Angeles | 3792621 | Riktigt storstad || Manhattan | 1619090 | Liten stad || New York | 8175133 | Riktigt storstad || Philadelphia | 1526006 | Liten stad || Phoenix | 1445632 | Liten stad || Queens | 2272771 | Storstad || San Antonio | 1327407 | Liten stad || San Diego | 1307402 | Liten stad || Bronx | 1408473 | Liten stad |+--------------+-------------+---------------- -+
Det här exemplet använder ett sökt CASE
uttryck för att utvärdera resultaten från LatestRecordedPopulation
kolumnen i Application.Cities
tabell.
Datatyper
I SQL Server, datatypen för inmatningsuttrycket och WHEN
uttryck måste vara samma eller måste vara en implicit konvertering.
Så här händer om de inte är det:
DECLARE @stock_ticker varchar(4) ='V';SELECT Company =CASE @stock_ticker NÄR 1 DÅ "Apple" NÄR 2 DÅ "Facebook" NÄR 3 DÅ "Mastercard" NÄR 4 DÅ "Visa" ANNAT ' Inte i portföljen' END
Resultat:
Msg 245, Level 16, State 1, Line 3Conversion misslyckades vid konvertering av varchar-värdet 'V' till datatyp int.
Utvärderingsordning
T-SQL CASE
expression utvärderar dess villkor sekventiellt och slutar med det första villkoret vars villkor är uppfyllt.
För att demonstrera detta, låt oss använda flera WHEN
uttryck som delar samma värde:
DECLARE @stock_ticker varchar(4) ='V';SELECT Company =CASE @stock_ticker NÄR 'V' DÅ 'Visa 1' NÄR 'V' DÅ 'Visa 2' NÄR 'V' SEN 'Visa 3' ' ELSE 'Inte i portföljen' END
Resultat:
+------------+| Företag ||-----------|| Visa 1 |+-----------+
I det här fallet stannade det vid första NÄR
uttryck.
Det kan finnas ett enstaka scenario där ett uttryck utvärderas före ett CASE
expression tar emot resultatet av uttrycket som dess input. I sådana scenarier kan du få ett fel. Detta kan hända om du inkluderar ett aggregerat uttryck som WHEN
uttryck.
Av denna anledning rekommenderar Microsoft att:
Du bör bara bero på utvärderingsordningen för WHEN-villkoren för skalära uttryck (inklusive icke-korrelerade underfrågor som returnerar skalärer), inte för aggregerade uttryck.
ANNET är valfritt
ANNET
argument är valfritt. Därför skulle vi kunna skriva om vårt "överkomliga exempel" enligt följande:
DECLARE @price int =1500;VÄLJ Prisvärdhet =CASE NÄR @price <100 DÅ "Billigt" NÄR @price>=100 OCH @price <500 DÅ "Prisvärd" NÄR @price>=500 SEN "Dyrt" ' END
Resultat:
+----------------+| Prisvärd ||----------------|| Dyrt |+-----------------+
Tänk dock på att du kan sluta med NULL
om du utelämnar ELSE
argument.
Följande exempel resulterar i NULL
:
DECLARE @price int =1500;VÄLJ Prisvärdhet =CASE NÄR @price <100 SEN "Billigt" NÄR @price>=100 OCH @price <500 DÅ "Prisvärd" NÄR @price>=500 OCH @price <1000 SEN "Dyrt" SLUT
Resultat:
+----------------+| Prisvärd ||----------------|| NULL |+-----------------+
I sådana fall kan vi alltid lägga till en ELSE
argument, för säkerhets skull (förlåt om ordleken!):
DECLARE @price int =1500;VÄLJ Prisvärdhet =CASE NÄR @price <100 SEN "Billigt" NÄR @price>=100 OCH @price <500 DÅ "Prisvärd" NÄR @price>=500 OCH @price <1000 SEDAN 'Dyrt' ANDERS 'Okänd' SLUT
Resultat:
+----------------+| Prisvärd ||----------------|| Okänd |+-----------------+
Visserligen är nog det här exemplet lite konstruerat. När allt kommer omkring finns det inget behov av att sätta ett tak för "dyrt". Om något är dyrt under 1 000 USD är det också dyrt om det är över 1 000 USD.
Men poängen är att du kan använda ELSE
för att fånga allt som inte omfattas av NÄR
uttryck/s.
Kästade CASE-uttryck
Du kan kapsla CASE
uttryck vid behov.
DECLARE @price int, @on_sale bit;SET @price =1500;SET @on_sale =1;SELECT Prisvärdhet =CASE WHEN @price <100 DÅ "Billigt" NÄR @price>=100 THEN CASE @on_sale NÄR 0 SÅ "Dyrt (men det är inte till rea just nu)" NÄR 1 SÅ "Dyrt (och det är redan till rea!)" END END
Resultat:
+-----------------------------------------------+| Prisvärd ||----------------------------------------------|| Dyrt (och det är redan till rea!) |+---------------------------------------------------------- +
Det är dock viktigt att notera att endast 10 nivåer av kapsling är tillåtna för CASE
uttryck i SQL Server. Om du försöker kapsla fler än 10 nivåer får du ett felmeddelande.
CASE i en ORDER BY-klausul
Som nämnts, T-SQL CASE
uttryck kan användas i alla påståenden eller satser som tillåter ett giltigt uttryck. Därför kan du använda den i satser som SELECT
, UPPDATERA
, RADERA
och SET
, och i satser som IN
, VAR
, ORDER BY
, GRUPPER EFTER
, och HAVING
.
Använda en CASE
uttryck i en satss ORDER BY
klausul kan vara praktisk när du vill göra ett speciellt undantag för vissa värden när du beställer dina resultat.
Anta att vi kör följande fråga mot en tabell som innehåller musikgenrer.
VÄLJ genre FRÅN MusicGenresORDER BY Genre ASC;
Resultat:
+--------+| Genre ||--------|| Blues || Land || Hip Hop || Jazz || Metall || Övrigt || Pop || Rap || Rock |+---------+
Här sorterar vi resultaten efter Genre
kolumn, i stigande ordning.
Det här är bra förutom en sak. Genren som heter Övrigt . Skulle det inte vara trevligt om vi kunde flytta Annat till botten?
Vi kan uppnå detta med CASE
uttryck genom att ta ovanstående fråga och ändra den enligt följande.
VÄLJ genre FRÅN musikgenrerORDER BY CASE Genre WHEN 'Other' THEN 1 ELSE 0 END ASC, Genre ASC;
Resultat:
+--------+| Genre ||--------|| Blues || Land || Hip Hop || Jazz || Metall || Pop || Rap || Rock || Övrigt |+---------+
FALL i en UPPDATERING
Här är ett exempel på hur du använder ett CASE
uttryck i en UPPDATERING
uttalande.
Anta att vi har följande tabell:
+--------+------------+-----------+--------+| DogId | Hundnamn | GoodDog | Middag ||--------+-----------+-----------+--------|| 1 | Hämta | 1 | NULL || 2 | Fluffig | 0 | NULL || 3 | Wag | 0 | NULL || 1001 | Brian | 1 | NULL || 1002 | Rambo | 0 | NULL || 1003 | BamBam | 1 | NULL |+---------+------------+------------------+Vi har nyligen lagt till
Dinner
kolumn, och den är fortfarandeNULL
, väntar på att värden ska infogas.Men värdena som ska infogas beror på värdet på
GoodDog
kolumn.Vi skulle kunna använda en
CASE
uttryck i ett sådant scenario.UPPDATERA Hundar SET Middag =CASE GoodDog NÄR 1 DÅ "Sunday Roast" ANDERS "Flygbolagsmat" ENDSELECT * FROM Dogs;
Resultat:
+--------+------------+------------+---------------- --+| DogId | Hundnamn | GoodDog | Middag ||--------+------------+------------+------------- -|| 1 | Hämta | 1 | Söndagsstek || 2 | Fluffig | 0 | Flygbolags mat || 3 | Wag | 0 | Flygbolags mat || 1001 | Brian | 1 | Söndagsstek || 1002 | Rambo | 0 | Flygbolags mat || 1003 | BamBam | 1 | Söndagsstek |+---------+------------+-----------+------------ --+CASE i ett INSERT-uttalande
Vi kan ta tabellen från exemplet ovan och infoga ett nytt värde.
Och vi kan återigen dra nytta av
CASE
uttryck för att infoga lämpligt värde iDinner
kolumn.DECLARE @DogName nvarchar(60), @GoodDog bit;SET @DogName ='Lat';SET @GoodDog =0;INSERT I Hundar ( Hundnamn, GoodDog, Dinner )VÄRDEN ( @DogName, @GoodDog, CASE @GoodDog NÄR 1 DÅ "Sunday Roast" ANDERS "Flygbolagsmat" SLUT );SELECT * FROM Dogs;
Resultat:
+--------+------------+------------+---------------- --+| DogId | Hundnamn | GoodDog | Middag ||--------+------------+------------+------------- -|| 1 | Hämta | 1 | Söndagsstek || 2 | Fluffig | 0 | Flygbolags mat || 3 | Wag | 0 | Flygbolags mat || 1001 | Brian | 1 | Söndagsstek || 1002 | Rambo | 0 | Flygbolags mat || 1003 | BamBam | 1 | Söndagsstek || 1004 | Lata | 0 | Flygbolagsmat |+---------+------------+-----------+------------------ --+Den här gången
CASE
expression utvärderade värdet på en variabel som vi precis hade ställt in och infogade sedan lämpligt värde iDinner
kolumn.Är det ett CASE-uttryck eller CASE-uttryck?
I SQL hänvisas många saker till som ett "påstående" när de i själva verket är något annat. Detta verkar också vara sant för T-SQL "
CASE
uttalande”.Även om det ofta kallas
CASE
uttalande, är det mer korrekt att kalla detCASE
uttryck . Det är också så Microsofts dokumentation hänvisar till det.I SQL Server, snarare än att vara en sats i sig,
CASE
kan användas i alla påståenden eller satser som tillåter ett giltigt uttryck. Ett uttryck är en kombination av symboler och operatorer som utvärderas för att erhålla ett enda datavärde.Vissa DBMS:er skiljer dock mellan
CASE
satsen ochCASE
uttryck och har en något olika syntax för varje. MySQL skiljer mellanCASE
satsen ochCASE
operatorn, vilket i huvudsak är samma somCASE
uttryck.