Spis treści:

Kategoria:SQL Server


Nowe IF THEN ELSE w SQL Server 2012

Jak drzewiej bywało

Zauważyłem, że wsród osób sporadycznie zajmujących się bazami danych często pojawiają się pytania o instrucje IF ...THEN ... ELSE znane z innych języków programowania. Programiści obiektowych i proceduralnych języków są tak do nich przyzwyczajeni, że wręcz nie wyobrażają sobie życia bez nich. W poprzednich wersjach SQL Server służyła do tego instukcja CASE WHEN THEN, o czym pisałem w artykule Instrukcja IF THEN ELSE w sekcji SELECT SQL Server. Muszę wszystkich uspokoić - stara konstrukcja nie wychodzi z użycia. Więcej, nie jest nawet uznana za przestarzałą jak typ image, który został natychmiast zastąpiony przez varbinary(MAX). Zaraz po pojawieniu się odpowiednika przestarzałymi ogłoszono również typy text i ntext, o czym pisałem w artykule Porównanie ntext i nvarchar(max).

Osobiście uważam, że instrukcja CASE WHEN THEN nie zginie tak prędko, bo chyba lepiej nadaje się do implementacji znanej z innych języków instrukcji SWITCH.

Jaki jest ten nowy IF ELSE?

Instrukcja znana jest użytkownikom Accessa od wielu dobrych lat i zaskakujące jest to, że SQL Server jej nie miał. Na szczęście już ma i można ją zobaczyć na poniższym listingu:

DECLARE @wskaznik decimal=1.3
SELECT IIF(@wskaznik>2.5,'Stan alarmowy''Prawidłowy') Stan

Wynikiem działania skrytpu będzie taki oto rezultat:

Stan
Prawidłowy

Sama konstrukcja wyrażenia jest bardzo prosta:

IIF(warunekLogiczny, wartośćJeżeliTak, wartośćJeżeliNie)

Zapis jest trochę podobny do znanej też konstrukcji operatora warunkowego ? (a==5 ? OK : ZLE).

Funckję IIF można wstawiać wszędzie tam, gdzie wszystkie inne funkcje. Spokojnie można jej używać w sekcji SELECT, w sekcji GROUP BY, w sekcji WHERE.

Przykład bardziej zaawansowany

Tym razem warunek IF będzie stosowany dla trzech stanów i dla każdego rekordu z tabeli. Popatrzmy na pokazany poniżej przykład:

--Przygotuj tabelę
SELECTINTO #table FROM (VALUES (1),(2),(3)) V(N)

--IF (N == 1) THEN 'Mało'
--ELSE IF (N == 2) THEN 'Średnio'
--ELSE 'Dużo'
SELECT IIF(N=1,'Mało',IIF(N=2,'Średnio','Dużo')) Stan
FROM #table

--dla SQL Server 2008 i wcześniejszych
SELECT CASE WHEN N=1 THEN 'Mało'
            WHEN N=2 THEN 'Średnio'
        ELSE 'Dużo' END Stan
FROM #table

--Posprzątaj
DROP TABLE #table

Jak widać, nowy zapis jest krótszy, ale czy jest bardziej czytelny? Dla dwóch wartości (klasyczne IF ELSE) funkcja IIF jest mniejsza i czytelniejsza. Dla trzech, a tym bardziej dla czterech (klasyczny SWITCH), przynajmniej moim zdaniem, zapis CASE WHEN THEN jest bardziej przejrzysty.

Funckja IIF i NULL

NULL jest bardzo niewdzięcznym składnikiem SQL Server. W wielu miejscach zachowuje się inaczej niż tradycyjne konstrukcje. Przyjrzyjmy się poniższemu listingowi:

DECLARE @null int

--Msg 4145, Level 15, State 1, Line 3
--An expression of non-boolean type specified in a context where a condition is expected, near '('.
--SELECT IIF(NULL,'TAK','NIE')
--SELECT IIF(@null,'TAK','NIE')

--Msg 8133, Level 16, State 1, Line 6
--At least one of the result expressions in a CASE specification must be an expression other than the NULL constant.
--SELECT IIF(1<2,NULL,NULL)

--To zadziała
SELECT IIF(1<2,@null,NULL)

--To też zadziała
SELECT IIF(1<NULL,'TAK','NIE')
SELECT IIF(NULL=NULL,'TAK','NIE')
--Jaki będzie wynik?

Instrukcje, które są błędne, zostały zakomentowane, a nad nimi umieściłem komunikat o błędzie. Myślę, że nie będzie problemu z samodzielną nalizą.

Dlaczego nie mozna w warunku umieścić NULL? Bo nie wiadomo, jak to zinterpretować. Czy NULL to prawda? Czy NULL to fałsz? Żeby podkreślić trudność takich decyzji zamieściłem na końcu dwie ciekawe instrukcje, które zadziałają. Jaki będzie ich wynik?Wynikiem obu operacji będzie NIE.

Wartości wyrażeń i operacji z NULL mogą zaskakiwać. O ile w tym prostym przykładzie nie ma problemu, o tyle w przypadku większego zapytania, różnych złączeń i warunków, mogą doprowadzić do nieprawidłowych wyników. Wychwycenie tego typu błędów może być większym wyzwaniem.

Które IF ELSE jest szybsze?

Odpowiedź jest prosta: żadne. Tak prawdę mówiąc, IIF jest tylko skróconym zapisem CASE WHEN THEN. Wewnętrznie jest on przetwarzany dokładnie tak samo jak CASE WHEN THEN. Co więcej, jeżeli wykonamy zapytanie zdalne, nasz IIF zostaje przetworzony na równoważne zapytanie CASE WHEN THEN!

Reasumując: IIF to tylko skrót. To ułatwienie dla tych, którym nie chce się pisać (swoją drogą komu się chce). Dlatego też nie było tej instrukcji w poprzednich wersjach SQL Server - można się było bez niej obejść.

Kategoria:SQL Server

, 2013-12-20

Brak komentarzy - bądź pierwszy

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?