Spis treści:

Kategoria:SQL Server


Instrukcja IF THEN ELSE w sekcji SELECT SQL Server

Instrukcja IF THEN ELSE lub po prostu IF jest niesłychanie powszechna w różnych językach programowania, tak skryptowych, jak i zwykłych. Aż dziw bierze, że nie została jeszcze poruszona jej składnia w sekcji SELECT. Od razu zaznaczam, że nie będzie tutaj omawiana skłądnia tej instrukcji w skrypcie, procedurze, czy funkcji.

IF w SELECT

Smutna wiadomość jest taka, że nie ma prostej wersji instrukcji IF dla składni SELECT. Zamiast niej stosuje się pewien zamiennik w postaci instrukcji CASE WHEN ... THEN ... END. Jak to działa? Przyjrzyjmy się pierwszemu przykładowi zaprezentowanemu poniżej:

--IF (1 = 1) THEN 'Prawda'
SELECT CASEWHENTHEN 'Prawda' END

Składnia może się wydać dość dziwna, ale jest to chyba kwestia przyzwyczajenia. Można tę składnię stosować także w zapytaniach korzystających z tabel, ale zostanie to zaprezentowane w dalszej części. Co warte podkreślenia: jeżeli warunek nie jest spełniony, instrukcja zwróci NULL. Wartość nieokreślona zostanie zwrócona na przykład z następującej instrukcji:

--IF (1 = 2) THEN 'Prawda'
SELECT CASEWHENTHEN 'Prawda' END

Czasami zachodzi potrzeba zwrócenia czegoś innego w przypadku niezgodności warunku. W takim przypadku, korzystając z bardziej standardowego języka zapytań piszemy coś na kształt IF {A} THEN {B} ELSE {C}.

IF ELSE

Instrukcja IF ELSE w sekcji SELECT wygląda bardzo podobnie do zaprezentowanych wcześniej. Tu jednak mała niespodzianka. O ile odpowiednik IF w SQL Server znacząco się różni, o tyle ELSE jest bardzo podobne, a co za tym idzie, chaba bardziej intuicyjne. Przyjrzyjmy się zatem przykładowej instrukcji.

--IF (1 = 1) THEN 'Prawda' ELSE 'Fałsz'
SELECT CASEWHENTHEN 'Prawda' ELSE 'Fałsz' END

--IF (1 = 2) THEN 'Prawda' ELSE 'Fałsz'
SELECT CASEWHENTHEN 'Prawda' ELSE 'Fałsz' END

Tym razem obie instrukcje zostały zgrupowane, bo wydaje mi się, że są one dość łatwe do zapamiętania (jeżeli oczywiście zrozumieliśmy odpowienik składni IF ELSE).

Pusta sekcja CASE

Istnieje też możliwość przeniesienia warunku poza sekcję CASE, tzn. pozostawienie sekcji CASE pustej tak, jak w poniższych przykładach.

--IF (1 = 1) THEN 'Prawda'
SELECT CASE WHEN 1=1 THEN 'Prawda' END

--IF (1 = 2) THEN 'Prawda'
SELECT CASE WHEN 1=2 THEN 'Prawda' END

--IF (1 = 1) THEN 'Prawda' ELSE 'Fałsz'
SELECT CASE WHEN 1=1 THEN 'Prawda' ELSE 'Fałsz' END

--IF (1 = 2) THEN 'Prawda' ELSE 'Fałsz'
SELECT CASE WHEN 1=2 THEN 'Prawda' ELSE 'Fałsz' END

Takie podejście, daje nam trochę więcej swobody, bo warunek może być złożony i wyliczany w trakcie obliczania całego wyrażenia. Przyjrzyjmy się następującej kwerendzie:

--IF (1 = 1 AND 2*2=4) THEN 'Prawda' ELSE 'Fałsz'
SELECT
  CASE
    WHEN 1=1 AND 2*2=4 THEN 'Prawda'
    ELSE 'Fałsz'
  END

Jeżeli IF THEN ELSE nie jest wystarczające, wtedy być może przyda się składnia reprezentująca wyrażenie SWITCH, znane z języków C, C++, C# i nie tylko.

Instrukcja SWITCH

Zanim przejdę do krótkiego wyjaśnienia, przyjrzyjmy się fragmentowi zapytania:

--Instrukcja SWITCH
SELECT
  CASE 2
    WHENTHEN 'Jeden'
    WHENTHEN 'Dwa'
    WHENTHEN 'Trzy'
    ELSE 'Nie wiem'
  END

W sekcji CASE znajduje się zwykle pole pobierane z tabeli bazodanowej. Stała została tam wstawiona tylko dla potrzeb przykładów. Warto zauważyć, że instrukcja ELSE działa podobnie do instrukcji default w języku C - jeżeli żaden z wcześniejszych warunków nie jest spełniony, wtedy brana jest wartość z sekcji ELSE.

Przykład IF THEN ELSE w zwykłym zapytaniu

Przypuśćmy, że mamy tabelę, która zawiera nazwę towaru, ilość sprzedanych towarów i ich typ w postaci liczby całkowitej. Chcielibyśmy zamienić ten typ na konkretną nazwę. Przyjrzyjmy się zatem pełnemu przykładowi:

--Przykładowa tabela
CREATE TABLE IfTable(
Name nvarchar(32),
Quantity int,
ProductType int
)
--Trochę danych
INSERT INTO IfTable VALUES ('Ubezpieczenie na życie', 3, 1)
INSERT INTO IfTable VALUES ('Ubezpieczenie nieruchomości', 2, 1)
INSERT INTO IfTable VALUES ('Banan', 7, 2)
INSERT INTO IfTable VALUES ('Dorsz', 4, 3)

--Zapytanie właściwe
SELECT Name, Quantity,
  CASE ProductType WHENTHEN 'Ubezpieczenia'
                   WHENTHEN 'Owoce i warzywa'
                   WHENTHEN 'Ryby' END [Type]
FROM IfTable

Przyjrzyjmy się teraz przykładowi numer dwa. Zadanie podobne, ale kategorie zakodowane są w nieco inny sposób. Kategorie od 10000 do 20000 to ubezpieczenia, 20000 do 30000 to owoce i warzywa, 30000 do 40000 to ryby. Przykład czysto ćwiczeniowy, pewnie bez większego zastosowania, ale ma pokazać bardziej zaawansowane warunki. Przyjrzyjmy się zatem zapytaniu zaprezentowanemu poniżej:

--Przykładowa tabela
CREATE TABLE IfTable2(
Name nvarchar(32),
Quantity int,
ProductType int
)
--Trochę danych
INSERT INTO IfTable2 VALUES ('Ubezpieczenie na życie', 3, 10001)
INSERT INTO IfTable2 VALUES ('Ubezpieczenie nieruchomości', 2, 10002)
INSERT INTO IfTable2 VALUES ('Banan', 7, 20001)
INSERT INTO IfTable2 VALUES ('Dorsz', 4, 30001)
INSERT INTO IfTable2 VALUES ('Sum', 4, 30002)
INSERT INTO IfTable2 VALUES ('Samuraj', 4, 345)

--Zapytanie właściwe
SELECT Name, Quantity,
  CASE WHEN ProductType>=10000 AND ProductType<20000
         THEN 'Ubezpieczenia'
       WHEN ProductType>=20000 AND ProductType<30000
         THEN 'Owoce i warzywa'
       WHEN ProductType>=30000 AND ProductType<40000
         THEN 'Ryby'
       ELSE 'Niesklasyfikowane' END [Type]
FROM IfTable2

Kategoria:SQL Server

, 2013-12-20

Komentarze:

Vanguard (2014-12-15 11:09:47)
A co zrobić aby zależnie od warunku. Raz użyć jednego zapytania a w else drugiego. Podane przykłady pozwalają jedynie określić wynik w danym przypadku.
PD (2014-12-16 16:14:49)
Wtedy stosuje się standardową składnię znaną z większości proceduralnych języków programowania. Zapytanie może przyjąć na przykład taką postać:
IF EXISTS(SELECT * FROM Articles)
  SELECT TOP 5 Title FROM Articles
ELSE
  SELECT 'No articles found'
Przy tego typu zapytaniach należy mieć na uwadze plany wykonania wyliczane dla każdego z rozgałęzień. SQL Server może dobrać plan na podstawie tego rozgałęzienia, które zostanie wybrane jako pierwsze i być nieoptymalne dla wyrażenia przecinego.
~123 (2016-06-17 14:45:07)
Mam tabelę a w niej kolumnę z Id.
Chcę zrobić UPDATE jeżeli jest dane Id w tabeli, jeżeli nie ma to INSERT. Jak zrobić "If"a?
PD: Rozwiązanie pokazane jest w artykule UPSERT, czyli UPDATE+INSERT w SQL Server.
piotr (2017-03-28 20:07:44)
Czy po THEN może być blok instrukcji przypisujący kilka wartości do różnych kolumn?

Z góry Dziękuje za odpowiedź
Dodaj komentarz
Wyślij
Ostatnie komentarze
Dzieki za rozjasnienie zagadnienia upsert. wlasnie sie ucze programowania :).
Co się stanie gdy spróbuję wyszukać:
SELECT * FROM NV_Airport WHERE Code='SVO'
SELECT * FROM V_Airport WHERE Code=N'SVO'
(odwrotnie są te N-ki)
Będzie konwersja czy nie znajdzie żadnego rekordu?