sql >> Databasteknik >  >> RDS >> Sqlserver

SQL Server CASE-uttryck

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 fortfarande NULL , 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 i Dinner 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 i Dinner 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 det CASE 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 och CASE uttryck och har en något olika syntax för varje. MySQL skiljer mellan CASE satsen och CASE operatorn, vilket i huvudsak är samma som CASE uttryck.


  1. Kod för att validera SQL-skript

  2. Lagrad procedur i Oracle-exempel med IN OUT-parameter

  3. Vad är en kandidatnyckel i databasdesign?

  4. Återställa MySQL-databas från fysiska filer