PL/SQL dla hobbystów. Instrukcje warunkowe.

Dodajmy trochę logiki do naszej aplikacji, a właściwie poznajemy sposób w jaki PL/SQL realizuje instrukcje warunkowe.

Każdy język programowania ma narzędzia, które umożliwiają dodawanie do kodu pewnej logiki, dzięki której można kontrolować, jakie instrukcje zostaną wykonane w następnej kolejności. Skoro użyłem w poprzednim zdaniu kwantyfikatora “każdy” i wspomniałem o logice, to logicznym się staje się, że PL/SQL nie jest wyjątkiem w tym zakresie, skoro aspiruje do miana języka programowania. Tym samym występują tutaj podstawowe elementy koderskiego rzemiosła takie jaki pętle czy instrukcje warunkowe. Dzisiejszy wpis poświęcony będzie tym ostatnim.

INSTRUKCJA IF…THEN

Najbardziej podstawowa i wszechobecna forma instrukcji warunkowych składa się z dwóch słów kluczowych IF oraz THEN. Składnia tej konstrukcji jest bardzo prosta i w przypadku PL/SQL wygląda następująco:

IF warunek

THEN

…list instrukcji…

END IF;

Rzecz jasna w tym wypadku lista potencjalnych instrukcji po słowie kluczowym THEN zostanie wykonana tyłko i wyłącznie wówczas, jeśli warunek po słowie kluczowym IF jest prawdziwy (TRUE). Całość zawsze kończymy przy pomocy END IF, po której następuje średnik. Z resztą średniki należy stawiać po każdej instrukcji umieszczonej po słowie THEN – jak po każdej instrukcji z resztą, co powinniśmy już wiedzieć.

Ilekroć dla warunku zostanie zwrócona wartość NULL, PL/SQL potraktuje to wystąpienie jako scenariusz FALSE.

Oczywiście jest to najprostsza forma instrukcji warunkowej, zaś w pełnej krasie dodaje dwa słowa kluczowe (i zapewne oczywiste dla kogoś z jakimkolwiek koderskim backgroundem).

IF warunek_1

THEN

…pierwsza list instrukcji…;

[ELSIF warunek_2

THEN

…druga list instrukcji…;]

[ELSE

…trzecia list instrukcji…;]

END IF;

Na początek przypominam, że nawiasy kwadratowe w tym przypadku mówią, że dany blok/element nie jest obowiązkowy. W przypadku instrukcji warunkowej muszą wystąpić trzy słowa kluczowe IF, THEN oraz END IF. Dla pełnej jasności zamieszam poniżej jak wygląadć może kod wpisujący się w widoczną wyżej strukturę. 

DECLARE

v_liczba number := 20;

BEGIN

IF v_liczba < 10

THEN dbms_output.put_line('Liczba jest mniejsza od 10');

ELSIF v_liczba < 15

THEN dbms_output.put_line('Liczba jest mniejsza od 15');

ELSE dbms_output.put_line('Liczba jest większa lub równa 15');

END IF;

END;

Logika tego przypływu jest raczej dość oczywista i sprowadza się do następujących kroków:

  • jeśli spełniony jest pierwszy warunek (zmianna v_liczba jest mniejsz niż 10), to wykonywana jest pierwsza instrukcja, która wypisuje do konsoli odpowiedni komunikat. 
  • w takiej sytuacji pozostałe warunki nie byłyby już sprawdzane – program wówczas poszedłby dalej. 
  • ponieważ liczba 20 jest większa niż 10 to lecimy do kolejnego warunku, tym razem po słowie kluczowym ELSIF, 
  • ten nowy warunek też nie jest spełniony, więc przeskakujemy do kolejnego bloku instrukcji warunkowej tym razem zaczynającej się od słowa kluczowego ELSE
  • to ostatnie oznacza mniej więcej tyle: skoro wykonywanie programu dotarło do mnie, jest to równoznaczne z tym, że żaden z poprzedzających moje wystąpie warunków nie okazał się prawdziwy – skoro tak jest, to ja już niczego nie sprawdzam, tylko po prostu wykonuję mój własny kod,
  • w efekcie w konsoli zobaczymy komunikat “Liczba jest większa lub równa 15”.

INSTRUKCJA CASE

Dla środowiska Oracle istnieje jeszcze inny mechanizm spełniający analogiczną rolę. Muszę w tym miejscu napisać, że osobiście bardzo chętnie i dość często używam go w zwykłych zapytaniach SQL, dlatego zastanawiałem się na początku, czy w ogóle o nim w tym tekście wspominać. Ponieważ praktycznie we wszystkich materiałach, z których korzystałem przygotowując ten wpis, jest jednak mowa, poczułem się jednak zobligowany. Chodzi o instrukcję CASE, która występuje w dwóch wariantach (choć osobiście uważam, że w pewnym sensie jest to trochę dzielenie włosa na dwoje):

  • z selektorem,
  • z wyszukiwaniem.

Osobiście używam wyłącznie tego drugiego, ale dla porządku zacznę od przypadku CASE z selektorem. Ogólny schemat wygląda następująco:

CASE selektor

WHEN kryterium_1 THEN

instrukcja_1

[WHEN kryterium_2 THEN

instrukcja _2

[WHEN … THEN

… ]]

[ELSE

instrukcje_dla_else;]

END CASE;

Selektor po słowie CASE w tym wypadku oznacza jakąś wartość, którą będziemy testować w kolejnych krokach. Zazwyczaj będzie to jakaś zmienna, do której wcześniej przypisaliśmy jakąś wartość (np. w wyniku wykonania zapytania lub jakieś funkcji). Następnie wartość ta jest porównywana po kolei ze wszystkimi wartościami w klauzulach WHEN, jedna po drugiej, aż do znalezienia dopasowania. Jeśli jakakolwiek klauzula WHEN zostanie “wykonana”, działanie całej instrukcji zostaje zakończone.

DECLARE

v_dzien_tygodnia number := 3;

BEGIN

    CASE v_dzien_tygodnia

        WHEN 6

        THEN dbms_output.put_line ('Sobota');

        WHEN 7

        THEN dbms_output.put_line ('Niedziela');

        ELSE

        dbms_output.put_line ('Dzień roboczy');

    END CASE;

END;

Tym niemniej warto jednak zwrócić szczególną uwagę na klauzulę ELSE, która w  instrukcji CASE działa identycznie jak w instrukcji IF, ale mimo to mamy tutaj jedną zasadniczą różnicę. W przypadku instrukcji IF…THEN, jeśli nie użyjemy instrukcji ELSE, a przy okazji żaden warunek nie zostanie spełniony, to nic się nie stanie – program pójdzie po prostu dalej. Dla instrukcji CASE nie ma tak dobrze, tj. jeśli żaden warunek po słowie WHEN nie okaże się spełniony, a jednocześnie brakuje instrukcji ELSE, wówczas wykonanie całej instrukcji kończy się niepowodzeniem. Innymi rzecz ujmując: jeśli zmienna v_dzien_tygodnia przyjmowałby zawsze wartości 6 oraz 7, to moglibyśmy odpuścić sobie słowo kluczowe ELSE. Ponieważ tak nie jest i w naszym wypadku wartość jest równa 3, to brak ostatniej klauzuli spowodowałby, że baza danych Oracle zgłosiłaby nam błąd.

Jeśli chodzi o instrukcje CASE z wyszukiwaniem, to w tym przypadku po prostu nie podajemy żadnego selektora, który następnie chcemy dopasować do warunków zawartych w instrukcji. W takiej sytuacji instrukcja CASE działa identycznie jak IF…THEN (oczywiście z uwzględnieniem tego, o czym wcześniej była mowa a kontekście klauzuli ELSE). Niżej zaprezentowałem jakiś wydumany kawałek kodu.

BEGIN

    CASE 

        WHEN 1+2=5

        THEN dbms_output.put_line ('Pierwszy warunek został spełniony');

        WHEN 3=3 AND 'pies' = 'pies'

        THEN dbms_output.put_line ('Drugi warunek został spełniony');

        ELSE

        dbms_output.put_line ('Nie został spełniony żaden warunek');

    END CASE;

END;

To na co zwróciłbym jeszcze uwagę na sam koniec, to możliwość używania operatorów OR oraz AND, tak jak to zwyczajowo robimy w przypadku zwykłych zapytań, gdy chcemy sprawdzić na raz kilka warunków.

W kolejnym wpisie pochylimy się nad pętlami.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *