Język PL/SQL

Transkrypt

Język PL/SQL
Wykład 4 – Struktury sterowania w języku PL/SQL – dr hab. prof. UŁ. Tadeusz Antczak
Struktury sterowania PL/SQL
Istnieje często potrzeba posiadania przez dany język programowania pewnych mechanizmów,
dzięki którym istnieje możliwość odpowiedniego reagowania na wszelkie możliwe sytuacje i
spełnienie określonych wymagań, które stoją przed programistą rozwiązującym programowo
jakiś problem. Język PL/SQL, jako język, który posiada cechy charakterystyczne dla innych
języków trzeciej generacji, odznacza się dużą różnorodność struktur sterowania, które
umożliwiają kontrolę funkcjonowania bloku podczas pracy programu. Do tych struktur zalicza
się instrukcje warunkowe (ang. conditional) i pętle (ang. loop). Dzięki tym strukturom oraz
zmiennym język PL/SQL jest bardzo wydajnym i elastycznym narzędziem programowania.
Instrukcja IF-THEN-ELSE
Podstawową instrukcją do konstruowania wyrażeń warunkowych jest instrukcja IF.
Składnia instrukcji IF-THEN-ELSE jest następująca:
IF wyrazenie_logiczne1 THEN
sekwencja_instrukcji;
[ELSIF wyrazenie_logiczne2 THEN
sekwencja_instrukcji;]
...
[ELSE
ostatnia_sekwencja_instrukcji;]
END IF;
gdzie:
wyrazenie_logiczne – dowolne wyrażenie, które w wyniku zwraca wartość logiczną
(wyrażenia logiczne zostały już omówione wcześniej). Zazwyczaj warunki wymienione w
instrukcji IF wykluczają się wzajemnie;
sekwencja_instrukcji – jedna lub większa liczba instrukcji, które są wykonywane, jeśli
odpowiadające im wyrazenie_logiczne jest prawdziwe. Jak zwykle, każda instrukcja musi
posiadać znak końca (znak średnika);
ostatnia_sekwencja_instrukcji – jedna lub większa liczba instrukcji wykonywanych, jeśli nie
jest prawdziwe żadne wyrazenie_logiczne i jeśli dodatkowo określono słowo kluczowe
ELSE;
klauzule ELSIF oraz ELSE są opcjonalne, a ponadto klauzule ELSIF mogą występować
wiele razy.
1
Wykład 4 – Struktury sterowania w języku PL/SQL – dr hab. prof. UŁ. Tadeusz Antczak
Ogólnie rzecz ujmując, działanie tej instrukcji pozwala na sprawdzenie dowolnej liczby
warunków logicznych i wykonanie instrukcji związanych z pierwszym, prawdziwym warunkiem
logicznym, ujętym w którymś z wyrażenie logicznych lub klauzulą ELSE, o ile ta ostatnia
występuje, a żaden z warunków nie był prawdziwy.
Poniższy przykład prezentuje przykładowy blok, w którym wykorzystano instrukcję IF-THENELSE z jedną klauzulą ELSIF i jedną klauzulą ELSE:
DECLARE
z_StanProduktu
towary.stan%TYPE;
z_Komentarz
VARCHAR(50);
BEGIN
/* Pobranie stanu produktu w magazynie dla produktu identyfikowanym przez id 10.
Zapamiętanie wyniku w zmiennej z_StanProduktu. */
SELECT stan_produktu
INTO z_StanProduktu
FROM towary
WHERE nr_produktu=10;
IF z_StanProduktu=0 THEN
z_Komentarz:=’Zapas produktu wyczerpany’;
ELSIF z_StanProduktu<=1000 THEN
z_Komentarz:=’Zapas produktu na wyczerpaniu’;
ELSE
z_Komentarz:=’Zapas produktu nie wymaga uzupełnień’;
END IF;
END;
Analiza i działanie powyższego bloku odzwierciedla to, co sugerują słowa kluczowe. Jeżeli
pierwszy warunek zostanie oceniony na wartość TRUE, to wykonywana jest pierwsza sekwencja
instrukcji. W omawianym przypadku pierwszym warunkiem jest:
z_StanProduktu=0,
natomiast pierwszą sekwencją instrukcji jest:
z_Komentarz:=’Zapas produktu wyczerpany’;
Gdy stan produktu w magazynie nie jest zerowy, wtedy oceniany jest drugi warunek:
2
Wykład 4 – Struktury sterowania w języku PL/SQL – dr hab. prof. UŁ. Tadeusz Antczak
z_StanProduktu<=1000
Jeżeli ten warunek zostanie oceniony na TRUE, to wykonywana jest druga sekwencja instrukcji:
z_Komentarz:=’Zapas produktu na wyczerpaniu’;
Na koniec, jeżeli stan produktu w magazynie będzie większy niż 1000, to zostanie wykonana
ostatnia (trzecia) sekwencja instrukcji:
z_Komentarz:=’Zapas produktu nie wymaga uzupełnień’;
Każda sekwencja instrukcji będzie wykonywana tylko wtedy, kiedy związany z nią warunek
logiczny zostanie oceniony na TRUE.
Powyżej przytoczony przykład wykorzystania instrukcji warunkowej IF dotyczył przypadku,
gdy każda sekwencja instrukcji zawiera tylko jedną instrukcję proceduralną. W zależności od
potrzeb można jednak skorzystać z dowolnej liczby instrukcji proceduralnych lub SQL.
Odzwierciedleniem tego typu sytuacji jest kolejny, przykładowy blok programu:
DECLARE
z_NrProduktu
towary.nr_t%TYPE;
z_StanProduktu
towary.stan%TYPE;
z_Komentarz
VARCHAR(50);
BEGIN
/* Pobranie stanu produktu w magazynie w produkcie identyfikowanym przez id 10.
Zapamiętanie wyniku w zmiennej z_StanProduktu. */
SELECT id, stan
INTO z_NrProduktu, z_StanProduktu
FROM towary
WHERE id = 10;
IF z_StanProduktu=0 THEN
z_Komentarz:=’Zapas produktu wyczerpany’;
INSERT INTO tabela_tymcz (kol_num, kol_znak)
VALUES (z_NrProduktu ‘Natychmiastowa dostawa’);
ELSIF z_StanProduktu<=1000 THEN
z_Komentarz:=’Zapas produktu na wyczerpaniu’;
INSERT INTO tabela_tymcz ((kol_num, kol_znak)
VALUES (z_NrProduktu, ‘Konieczna dostawa’);
ELSE
3
Wykład 4 – Struktury sterowania w języku PL/SQL – dr hab. prof. UŁ. Tadeusz Antczak
z_Komentarz:=’Zapas produktu nie wymaga uzupełnień’;
INSERT INTO tabela_tymcz ((kol_num, kol_znak)
VALUES (z_NrProduktu, z_Komentarz);
END IF;
END;
Warunki logiczne o wartości NULL w instrukcji warunkowej IF-THEN-ELSE
Sekwencja instrukcji, która występowała we wcześniej podanej składni instrukcji warunkowej
IF-THEN-ELSE, jest wykonywana tylko wtedy, gdy związany z nią warunek jest oceniany jako
wartość TRUE. Jeżeli ten warunek jest oceniany na wartość FALSE lub NULL, to sekwencja
instrukcji nie jest wykonywana.
Rozważmy następujące, przykładowe bloki programu:
/* Blok 1 */
DECLARE
z_Num1
NUMBER;
z_Num2
NUMBER;
z_Wynik
VARCHAR(10);
BEGIN
…
IF z_Num1 < z_Num2 THEN
z_Wynik:=’Tak’;
ELSE
z_Wynik:=’Nie’;
END IF;
END;
/* Blok 2 */
DECLARE
z_Num1
NUMBER;
z_Num2
NUMBER;
z_Wynik
VARCHAR(10);
BEGIN
…
IF z_Num1 >= z_Num2 THEN
z_Wynik:=’Nie’;
ELSE
z_Wynik:=’Tak’;
END IF;
END;
4
Wykład 4 – Struktury sterowania w języku PL/SQL – dr hab. prof. UŁ. Tadeusz Antczak
Przeanalizujemy sposób działania obydwu powyżej podanych bloków PL/SQL. Przyjmijmy, że
z_Num1=4 oraz z_Num2=9. Warunek w bloku 1 (4<9) jest oceniony na TRUE i zmienna
z_Wynik przyjmuje wartość ’Tak’. Analogicznie warunek w bloku 2 (4>=9) jest oceniony jako
wartość FALSE i zmienna z_Wynik przyjmuje wartość ‘Tak’. A zatem dla wszystkich wartości
zmiennych z_Num1 i z_Num2 różnych od NULL obydwa bloki zachowują się w ten sam
sposób.
Należy zastanowić się, co będzie gdy jedna ze zmiennych przyjmuje wartość NULL. Np.
przyjmijmy, że zmienna z_Num1=4, zaś zmienna z_Num2 przyjmuje wartość NULL. Teraz w
bloku 1 warunek 4>NULL jest oceniony jako wartość NULL, zatem jest wykonywana klauzula
ELSE, która przydziela zmiennej z_Wynik wartość ‘Nie’. Natomiast w bloku 2 warunek
4>=NULL jest również oceniony jako NULL, zatem musi być wykonana klauzula ELSE
poprzez przydzielenie zmiennej z_Wynik wartości ‘Tak’. W przypadku, gdy zmienna z_Num1
lub zmienna z_Num2 ma wartość NULL, obydwa bloki zachowują się w odmienny sposób.
Jeśli zachodzi potrzeba, aby omawiane dwa bloki zachowywały się w jednakowy sposób, należy
w kodzie programu uwzględnić sprawdzanie występowania wartości NULL:
/* Blok 1 */
DECLARE
z_Num1
NUMBER;
z_Num2
NUMBER;
z_Wynik
VARCHAR(10);
BEGIN
…
IF z_Num1 IS NULL OR
z_Num2 IS NULL THEN
z_Wynik:=’Nieznany’;
ELSIF z_Num1 < z_Num2 THEN
z_Wynik:=’Tak’;
ELSE
z_Wynik:=’Nie’;
END IF;
END;
/* Blok 2 */
5
Wykład 4 – Struktury sterowania w języku PL/SQL – dr hab. prof. UŁ. Tadeusz Antczak
DECLARE
z_Num1
NUMBER;
z_Num2
NUMBER;
z_Wynik
VARCHAR(10);
BEGIN
…
IF z_Num1 IS NULL OR
z_Num2 IS NULL THEN
z_Wynik:=’Nieznany’;
ELSIF z_Num1 >= z_Num2 THEN
z_Wynik:=’Nie’;
ELSE
z_Wynik:=’Tak’;
END IF;
END;
Przeanalizujmy teraz działanie obydwu bloków PL/SQL. Warunek IS NULL jest oceniany jako
wartość TRUE tylko wtedy, gdy zmienna, którą ten warunek sprawdza, ma wartość NULL.
Jeżeli zmienna przyjmuje wartość inną niż NULL, to warunek zostanie oceniony jako wartość
FALSE. Dzięki dodaniu tego sprawdzenia do powyższych bloków, następuje przydzielenie
wartości ‘Wynik nieznany’ zmiennej z_Wynik w przypadku, gdy którakolwiek z dwóch
badanych zmiennych ma wartość NULL. Sprawdzanie, czy zmienna z_Num1 jest większa od
zmiennej z_Num2, następuje tylko wtedy, gdy żadna z tych zmiennych nie ma wartości NULL.
W takim przypadku obydwa omawiane bloki zachowują się jednakowo.
Warto mieć na uwadze następujące wskazówki dotyczące używania instrukcji IF-THEN-ELSE
w blokach języka PL/SQL:
Słowem kluczowym oznaczającym warunek „w przeciwnym razie” jest klauzula ELSIF, a
nie ELSEIF spotykana w innych językach programowania. Taka pisownia tego słowa
kluczowego pochodzi z języka ADA.
Występujące po instrukcjach IF i ELSIF wyrażenia logiczne można ujmować w nawiasy, ale
nie jest to konieczne.
Jedynie słowo kluczowe END IF jest zakończone znakiem końca (średnikiem). Pozostałe
słowa kluczowe rozpoczynają się lub kontynuują instrukcję IF, ale jej nie kończą.
6
Wykład 4 – Struktury sterowania w języku PL/SQL – dr hab. prof. UŁ. Tadeusz Antczak
Instrukcja IF-THEN-ELSE kończy się zawsze wyrażeniem “END IF”, ze spacją pomiędzy
słowami END a IF. Użycie zapisu ENDIF, który jest często spotykany w innych językach
programowania, w języku PL/SQL jest niedopuszczalne i spowoduje powstanie błędu
kompilacji.
Instrukcja Case
W systemie Oracle9i wprowadzono nową instrukcję sterującą CASE (ang. CASE statement),
która może być stosowana jako prosta i efektywna alternatywa dla długich instrukcji IF-THENELSE. Istnieją dwie formy instrukcji CASE: sprawdzająca i wyszukująca. Rozważmy
następujący przykład kodu PL/SQL, w którym przydzielano nalepkę na samochód w zależności
od tego, w jakim kraju jest on zarejestrowany:
DECLARE
z_Kraj
kierowcy.kraj%TYPE;
z_Nalepka
VARCHAR(3);
BEGIN
-- Pobranie nazwy kraju dla określonego samochodu
SELECT kraj
INTO z_Kraj
FROM kierowcy
WHERE Nr_kierowcy = 1032;
-- Przypisanie nalepki na podstawie kraju
IF z_kraj = ‘Polska’ THEN
z_Nalepka := ‘PL’;
ELSIF z_kraj = ‘Włochy’ THEN
z_Nalepka := ‘I’;
ELSIF z_kraj = ‘Holandia’ THEN
z_Nalepka := ‘NL’;
ELSIF z_kraj = ‘Austria’ THEN
z_Nalepka := ‘A’;
ELSIF z_kraj = ‘Szwecja’ THEN
z_Nalepka := ‘S’;
ELSE
z_Nalepka:= ‘Nieznana’;
END IF;
DBMS_OUTPUT.PUT_LINE(z_Nalepka);
END; /
7
Wykład 4 – Struktury sterowania w języku PL/SQL – dr hab. prof. UŁ. Tadeusz Antczak
Powyższy kod kilkakrotnie sprawdza wartość zmiennej z_kraj, każdorazowo w osobnej
instrukcji ELSIF. Można wykorzystać prostszą metodę dostępną of wersji Oracle9i, aby
zrealizować to zadanie. Polega ona na zastosowaniu instrukcji CASE, która ma podobną
składnię do instrukcji SWITCH w języku C.
Sprawdzająca instrukcja CASE
Składnia instrukcji sprawdzającej CASE jest następująca:
CASE zm_testowa
WHEN wart_1 THEN sekwencja_instrukcji1;
WHEN wart_2 THEN sekwencja_instrukcji2;
...
WHEN wart_n THEN sekwencja_instrukcjin;
[ELSE sekwencja_else;]
END CASE;
gdzie:
zm_testowa – jest zmienną dowolnego typu lub nawet skomplikowanym wyrażeniem, które
określa porównywaną wartość. W każdym przypadku jest ona odczytywana (lub obliczana,
jeśli to konieczne) tylko raz – na początku wykonania instrukcji CASE;
wartości wart_1 do wart_n są wartościami porównywanymi z wartością zwracaną przez
zm_testową.Ważne jest, aby typy danych wartości wart1 do wartn były zgodne z typem
wartości wyrażenia testowego;
sekwencje instrukcji sekwencja_instrukcji1 do sekwencja_instrukcjin są wykonywane, jeśli
odpowiednia wart_i jest równa zm_testowej. Przykładowo, gdy zm_testowa przyjmie
wart_2, to zostanie wykonana sekwencja instrukcji sekwencja_instrukcji2;
sekwencja_else – jest pewną liczbą instrukcji, które są wykonywane w przypadku, gdy
zmienna zm_testowa będzie różna od wszystkich podanych wartości wart_i. Klauzula ELSE,
podobnie jak w przypadku instrukcji IF, jest opcjonalna.
A zatem jeśli wykorzystamy instrukcję CASE w powyżej podanym bloku programu, to jego
postać uprości się w następujący sposób:
DECLARE
z_Kraj
kierowcy.kraj%TYPE;
8
Wykład 4 – Struktury sterowania w języku PL/SQL – dr hab. prof. UŁ. Tadeusz Antczak
z_Nalepka VARCHAR(3);
BEGIN
-- Pobranie nazwy kraju dla określonego samochodu
SELECT kraj
INTO z_kraj
FROM kierowcy
WHERE Nr_kierowcy = 1032;
-- Przypisanie nalepki na podstawie kraju
CASE z_kraj
WHEN ‘Polska’ THEN z_Nalepka := ‘PL’;
WHEN ‘Włochy’ THEN z_Nalepka := ‘I’;
WHEN ‘Holandia’ THEN z_Nalepka := ‘NL’;
WHEN ‘Austria’ THEN z_Nalepka := ‘A’;
WHEN ‘Szwecja’ THEN z_Nalepka := ‘S’;
ELSE
z_Nalepka:= ‘Nieznana’;
END CASE;
DBMS_OUTPUT.PUT_LINE(z_Nalepka);
END;
Klauzula ELSE w instrukcji CASE jest opcjonalna. W sytuacji, gdy wyrażenie testowe nie jest
zgodne z żadną z wartości testowych, mechanizm PL/SQL zgłasza predefiniowany błąd
CASE_NOT_FOUND będący odpowiednikiem błędu ORA-6592.
Tego typu sytuacja została zaprezentowana w poniższej sesji programu SQL*Plus:
SQL> DECLARE
2
3
4
z_Kwartal NUMBER:=0
BEGIN
/* Ponieważ żadna z klauzul WHEN nie określa warunku dla wartości 0, to
wykonanie tego kodu spowoduje powstanie błędu ORA-6592.
5
CASE z_Kwartal
6
WHEN 1 THEN DBMS_OUTPUT.PUT_LINE(‘Kwartał 1’);
7
WHEN 2 THEN DBMS_OUTPUT.PUT_LINE(‘Kwartał 2’);
8
WHEN 3 THEN DBMS_OUTPUT.PUT_LINE(‘Kwartał 3’);
9
WHEN 4 THEN DBMS_OUTPUT.PUT_LINE(‘Kwartał 4’);
9
Wykład 4 – Struktury sterowania w języku PL/SQL – dr hab. prof. UŁ. Tadeusz Antczak
10
END CASE;
11 END;
12 /
DECLARE
*
BŁĄD w linii 1:
ORA-06592: Nie znaleziono wariantu CASE w czasie wykonywania instrukcji CASE
ORA-06512: w linii 6
Instrukcja CASE pokazana w przykładzie jest równoważna instrukcji CASE z klauzulą ELSE w
następującej postaci:
ELSE RAISE CASE_NOT_FOUND;
Instrukcja sprawdzająca CASE oznaczona etykietą
Instrukcja CASE, podobnie jak blok PL/SQL, może być opcjonalnie oznaczona etykietą. Później
omówimy podobną sytuację w przypadku pętli, które również mogą być oznaczone etykietami.
Jeżeli instrukcja CASE jest oznaczona etykietą, to taka sama etykieta może pojawić się także z
klauzulą END CASE, co pokazuje poniższy przykład:
DECLARE
z_Kwartal
NUMBER:=1;
BEGIN
-- Ta instrukcja CASE oznaczona jest etykietą.,
<<CaseKwartal>>
CASE z_Kwartal
WHEN 1 THEN DBMS_OUTPUT.PUT_LINE(‘Kwartał 1’);
WHEN 2 THEN DBMS_OUTPUT.PUT_LINE(‘Kwartał 2’);
WHEN 3 THEN DBMS_OUTPUT.PUT_LINE(‘Kwartał 3’);
WHEN 4 THEN DBMS_OUTPUT.PUT_LINE(‘Kwartał 4’);
END CASE CaseKwartal;
END;
Etykieta występująca za instrukcją END CASE jest poprawna tylko wtedy, gdy odpowiadająca
jej instrukcja CASE jest oznaczona etykietą. Obie etykiety muszą być takie same.
10
Wykład 4 – Struktury sterowania w języku PL/SQL – dr hab. prof. UŁ. Tadeusz Antczak
Niestety nie istnieje jakaś ogólna metoda zmiany wyrażeń warunkowych typu IF-THEN-ELSE
na instrukcję sprawdzającą CASE. Należy też wyraźnie podkreślić, iż jedynym rodzajem
operacji porównania, jaki można wykonać za pomocą sprawdzającej instrukcji CASE, jest po
prostu sprawdzenie równości wartości. Z tego powodu sprawdzająca instrukcja CASE jest mniej
użyteczna od wyszukującej wersji tej instrukcji, która zostanie omówiona poniżej.
Wyszukująca instrukcja CASE
Wyszukująca instrukcja CASE ma następującą składnię:
CASE
WHEN warunek_logiczny1 THEN sekwencja_instrukcji1;
WHEN warunek_logiczny2 THEN sekwencja_instrukcji2;
...
WHEN warunek_logicznyn THEN sekwencja_instrukcjin;
[ELSE sekwencja_else;]
END CASE;
W przeciwieństwie do sprawdzającej instrukcji CASE, w składni wyszukującej instrukcji CASE
nie ma wyrażenia testowego. Zamiast niego każda klauzula WHEN zawiera wyrażenia
boolowskie. Podobnie, jak w instrukcji IF-THEN, jeżeli wartość określonego warunku
logicznego przyjmuje wartość TRUE, to zostanie wykonana odpowiadająca mu
sekwencja_instrukcji.
Poniższy przykład ilustruje działanie wyszukującej instrukcji CASE:
SQL> DECLARE
2
z_Miesiac NUMBER:=4;
3
z_StatusPracownik CHAR(3):=’Tak’;
4
BEGIN
5
CASE
6
WHEN z_Miesiac = 4 THEN
7
DBMS_OUTPUT.PUT_LINE(‘Miesiąc rozliczenia podatku!’);
8
WHEN z_Miesiac > 4 THEN
9
DBMS_OUTPUT.PUT_LINE(‘Minął termin rozliczenia podatku!’);
10 WHEN z_SatusPracownik =’Tak’ THEN
11 DBMS_OUTPUT.PUT_LINE(‘Pracownik indywidualnie rozlicza swój podatek.’);
11
Wykład 4 – Struktury sterowania w języku PL/SQL – dr hab. prof. UŁ. Tadeusz Antczak
12 DBMS_OUTPUT.PUT_LINE(‘Zakład wystawia pracownikowi formularz podatkowy PIT
8B!’);
13 ELSE
14 DBMS_OUTPUT.PUT_LINE(‘Żaden z warunków nie jest spełniony’);
15 END CASE;
16 END;
17 /
Wynik działania powyższego bloku będzie w rozpatrywanym przypadku następujący:
Miesiąc rozliczenia podatku!
Należy zwrócić uwagę, iż w powyższym bloku wyrażenia logiczne, które są sprawdzane po
klauzulach WHEN nie są tego samego typu danych i nie muszą dotyczyć tych samych wyrażeń.
Ponadto, co również wynika z powyższego przykładu, każda klauzula WHEN może zawierać
więcej niż jedną instrukcję. Należy zwrócić uwagę, że warunki logiczne w poszczególnych
klauzulach WHEN nie. Jest również znamiennym, iż chociaż zmienna z_SatusPracownika ma
wartość „Tak” – dzięki czemu trzeci warunek WHEN przyjmuje wartość TRUE – to jednak
związana z nim sekwencja instrukcji nie zostanie wykonana, ponieważ wcześniej poprzedni
warunek przyjął wartość TRUE i wykonana została odpowiadająca mu sekwencja instrukcji.
Pętle języka PL/SQL
W programowaniu niejednokrotnie zachodzi konieczność powtórzenia tej samej sekwencji
instrukcji kilkakrotnie. Zadanie to jest przez programistów nazywane iteracją i jest ono podstawą
wszelkich proceduralnych języków programowania. Można je zrealizować przy wykorzystaniu
pętli dostępnych w danym języku programowania. Również język PL/SQL, mający charakter
języka proceduralnego, posiada cztery rodzaje pętli: pętle proste, pętle WHILE i pętle
numeryczne FOR oraz pętle kursora FOR.
Pętle proste
Pętla prosta jest najmniej skomplikowaną konstrukcją pętlową w języku PL/SQL. Jej składnia
jest następująca:
LOOP
sekwencja_instrukcji;
END LOOP;
12
Wykład 4 – Struktury sterowania w języku PL/SQL – dr hab. prof. UŁ. Tadeusz Antczak
gdzie:
sekwencja_instrukcji – jest pewną liczbą instrukcji wykonywanych w ramach pętli, inaczej
mówiąc, w ramach każdej iteracji.
Jak łatwo wywnioskować na podstawie składni pętli prostej, nie zdefiniowano w niej żadnego
warunku zatrzymania, więc sekwencja_instrukcji będzie wykonywana w nieskończoność. Stąd
też inna nazwa pętli prostej to pętla nieskończona (ang. infinite loop). Można w niektórych
przypadkach istotnie wykorzystywać pętle proste, np. w sytuacji, gdy program jest aktywowany
w określonym przedziale czasowym do sprawdzania poczty. Tym niemniej unika się stosowania
takich pętli, aby nie zawiesić sesji programu SQL*Plus. Aby zatem umożliwić opuszczenie pętli,
wprowadza się instrukcję EXIT, która ma następującą składnię:
EXIT [WHEN warunek];
Instrukcja ta powoduje zatrzymanie wykonywania pętli i przejście do następnej instrukcji
wykonywanej w programie. Istnieje możliwość warunkowego zatrzymania pętli prostej, jeśli w
konstrukcji instrukcji EXIT użyjemy klauzuli WHEN z pewnym warunkiem. Dopiero spełnienie
tego warunku powoduje opuszczenie pętli prostej. A zatem instrukcja EXIT WHEN warunek jest
równoważna sekwencji instrukcji:
IF warunek THEN
EXIT;
END IF;
Poniższy, przykładowy blok programu wstawia do tabeli tabela_tymcz 50 wierszy:
DECLARE
z_Licznik BINARY_INTEGER:=1;
BEGIN
LOOP
-- wstawienie wiersza do tabeli tabela_tymcz dla bieżącej wartości licznika pętli.
INSERT INTO tabela_tymcz
VALUES (z_Licznik, ‘Indeks pętli’);
z_Licznik:=z_Licznik + 1;
-- warunek wyjścia – kiedy licznik pętli > 50 działania wykonywane w pętli zostaną
zakończone
IF z_Licznik > 50 THEN
13
Wykład 4 – Struktury sterowania w języku PL/SQL – dr hab. prof. UŁ. Tadeusz Antczak
EXIT;
END IF;
END LOOP;
END;
Należy zauważyć, iż pętlą prosta zostanie wykonana przynajmniej jeden raz i kończy działanie,
wtedy gdy warunek w instrukcji warunkowej IF przyjmie wartość TRUE. Należy również
pamiętać, iż instrukcja EXIT może być wykorzystana tylko wewnątrz pętli.
Ponieważ, jak wynika to z definicji instrukcji EXIT, użycie w niej klauzuli WHEN z pewnym
warunkiem logicznym jest równoważne instrukcji IF z tym warunkiem, powyższy blok z pętlą
prostą możemy zapisać również w następującej, równoważnej postaci.
DECLARE
z_Licznik BINARY_INTEGER:=1;
BEGIN
LOOP
-- wstawienie wiersza do tabeli tabela_tymcz dla bieżącej wartości licznika pętli.
INSERT INTO tabela_tymcz
VALUES (z_Licznik, ‘Indeks pętli’);
z_Licznik:=z_Licznik + 1;
-- warunek wyjścia – kiedy licznik pętli > 50 działania wykonywane w pętli zostaną zakończone
EXIT WHEN z_Licznik>50;
END LOOP;
END;
Należy zaznaczyć, iż taka modyfikacja kodu nie spowoduje zmiany działania bloku języka
PL/SQL w stosunku do działania bloku PL/SQL, który był przedstawiony powyżej.
Jak to zatem wynika z konstrukcji i zasady działania, pętla prosta może być stosowana w
następujących przypadkach:
jeśli nie jest znana liczba powtórzeń wykonania instrukcji w pętli;
jeśli nie jest możliwe wyrażenie liczby iteracji pętli za pomocą wzoru lub zapytania;
jeśli instrukcje pętli mają być zawsze wykonane przynajmniej jeden raz. Wynika to z
konstrukcji pętli prostej, która zaczynając się słowem kluczowym LOOP nie zaprzestaje
swego działania, dopóki nie napotka instrukcji EXIT, która musi znajdować się wewnątrz
pętli.
14
Wykład 4 – Struktury sterowania w języku PL/SQL – dr hab. prof. UŁ. Tadeusz Antczak
Nie należy natomiast stosować pętli prostej w przypadkach, w których z jakiś powodów
wykonywanie pętli powinno być pominięte. W tego typu sytuacjach należy stosować inny rodzaj
pętli, a mianowicie pętlę WHILE.
Pętle WHILE
Pętla WHILE jest przykładem pętli, która jest wykonywana, dopóki warunek logiczny
występujący w jej składni ma wartość TRUE. Składnia pętli WHILE jest następująca:
WHILE warunek LOOP
sekwencja_instrukcji;
END LOOP;
gdzie:
sekwencja_instrukcji- pewna liczba instrukcji wykonywana w ramach każdej iteracji pętli;
warunek – jest wyrażeniem logicznym, które, dopóki ma wartość TRUE przed wykonaniem
kolejnej iteracji, powoduje, iż ta sekwencja instrukcji wewnątrz pętli zostanie wykonana.
Kiedy warunek zwraca FALSE lub NULL, wtedy wykonywanie pętli zostaje zakończone, a
sterowanie jest przekazywane do instrukcji następującej po END LOOP.
Jest oczywistym, iż należy przyjąć założenie, iż w trakcie wykonywania sekwencji_instrukcji
wartość wyrażenia logicznego, które jest umiejscowione w warunku, musi w jakimś momencie
ulec zmianie z wartości TRUE na FALSE lub NULL.
Poniżej został przedstawiony przykład zmodyfikowanego kodu PL/SQL, w którym pętlę prostą
zastąpiono pętlą WHILE:
DECLARE
z_Licznik BINARY_INTEGER:=1;
BEGIN
/* testowanie licznika pętli przed każdą iteracją pętli w celu ustalenia, czy jego wartość
jest w dalszym ciągu mniejsza lub równa 50. */
WHILE z_Licznik<=50 LOOP
INSERT INTO tabela_tymcz
VALUES (z_Licznik, ‘Indeks pętli’);
z_Licznik:=z_Licznik + 1;
END LOOP;
END; /
15
Wykład 4 – Struktury sterowania w języku PL/SQL – dr hab. prof. UŁ. Tadeusz Antczak
Należy również pamiętać o dość istotnym fakcie. Otóż, jeżeli na początku wykonywania pętli
WHILE jej warunek nie zostanie oceniony na wartość TRUE, to instrukcje zawarte w pętli nie
zostaną wykonane ani razu. Gdyby zatem w omawianym powyżej przykładzie usunąć instrukcję
inicjującą zmienną z_Licznik, wówczas warunek z_Licznik<=50 będzie oceniony na wartość
NULL, co spowoduje, że do tabeli tabela_tymcz nie zostaną wstawione wiersze.
W razie potrzeby także w pętli WHILE w celu wcześniejszego opuszczenia pętli można
wykorzystać instrukcje EXIT lub EXIT WHEN.
Porównanie pętli prostych i pętli WHILE
Jak wynika z analizy działania pętli prostych i pętli WHILE mogą one być wykorzystywane do
realizacji tych samych zadań – wykonania określonej sekwencji instrukcji na ogół niewiadomą z
góry liczbę razy. Celowym jest zatem określenie, kiedy efektywnym jest zastosowanie do tego
celu pętli prostej, a kiedy pętli WHILE.
Ogólnie rzecz biorąc, każdą pętlę prostą można zapisać jako pętlę WHILE i odwrotnie. Tym
niemniej konieczność napisania dodatkowego kodu lub też powtarzania istniejącego kodu, w
przypadku zastosowania takiego, a nie innego rodzaju pętli, powoduje, iż ważnym jest wybór
odpowiedniego rodzaju pętli, aby maksymalnie uprościć kod programu.
Jak wynika z analizy poprzednich dwóch przykładów kodu PL/SQL, zastosowanie pętli WHILE
może wydawać się nieco bardziej atrakcyjne, gdyż nie ma potrzeby stosowania w pętli WHILE
instrukcji EXIT, gdyż warunek wyjścia z pętli jest sprawdzany już na samym początku pętli. Nie
można jednak bazując tylko na tym jednym przykładzie wysnuć wniosek, iż zawsze
zastosowanie pętli WHILE jest bardziej efektywne, choćby dla uproszczenia kodu, niż
zastosowanie pętli prostej.
Poniżej przytoczymy dwa programy realizujące to samo zadanie polegające na wykonaniu
sekwencji pewnej liczby instrukcji określoną liczbę razy, z tym, iż w pierwszym z nich
zastosujemy pętlę prostą, zaś w drugim pętlę WHILE.
DECLARE
z_Licznik
BINARY_INTEGER;
z_zm1
NUMBER;
z_zm2
NUMBER:=0;
BEGIN
z_Licznik:=0;
LOOP
z_zm1:=z_zm2;
16
Wykład 4 – Struktury sterowania w języku PL/SQL – dr hab. prof. UŁ. Tadeusz Antczak
z_zm2:=z_zm1+1;
z_Licznik:=z_Licznik + 1;
EXIT WHEN z_Licznik = 100 OR z_zm2>99 ;
END LOOP;
END;
DECLARE
z_Licznik
BINARY_INTEGER;
z_zm1
NUMBER;
z_zm2
NUMBER:=0;
BEGIN
z_Licznik:=0;
z_zm1:=z_zm2;
z_zm2:=z_zm1+1;
WHILE z_Licznik = 100 OR z_zm2<99 LOOP
z_zm1:=z_zm2;
z_zm2:=z_zm1+1;
z_Licznik:=z_Licznik + 1;
END LOOP;
END;
Jak wynika z analizy powyższych dwóch przykładowych programów PL/SQL, w tym przypadku
wybór pętli prostej jest lepszym rozwiązaniem, gdyż w przypadku pętli WHILE trzeba
dwukrotnie napisać ten sam fragment kodu programu, gdyż należy ustalić wartości początkowe
zmiennych, a potem wykorzystać je wewnątrz pętli w kolejnych iteracjach.
I właśnie tego rodzaju powtórzenia, choć w powyższych przykładach bardzo proste, są
charakterystyczne dla pętli WHILE, gdyż w ich przypadku należy ustalić najpierw warunki
początkowe, a ponadto na ogół ten sam fragment kodu jest później wykorzystywany w końcowej
części kodu pętli. Oczywiście powyższy przykład jest bardzo prosty, ale w bardziej
skomplikowanych przypadkach taka inicjalizacja warunków początkowych dla pętli WHILE
może wymagać kilku „dodatkowych” linijek kodu przed samym uruchomieniem pętli, a potem
jeszcze raz te linie kodu występują w pętli WHILE. Może to prowadzić do pojawienia się
pewnych problemów z efektywnym zarządzaniem tak skonstruowanego kodu programu.
17
Wykład 4 – Struktury sterowania w języku PL/SQL – dr hab. prof. UŁ. Tadeusz Antczak
Powyższa analiza prowadzi do następującego wniosku odnośnie używania tego typu pętli w
PL/SQL: Jeśli w razie zastosowania pętli WHILE okaże się, że zachodzi konieczność
powtarzania fragmentu kodu, należy spróbować zastosować konstrukcję pętli prostej.
Tym niemniej na podstawie powyższych faktów nie można wysnuć zbyt pochopnie wniosku, iż
pętle proste są zawsze prowadzą do konstrukcji bardziej efektywnego kodu niż pętle WHILE.
Świadczy o tym także wcześniej rozpatrywana własność pętli prostych, które mogą być
opuszczone dopiero po zastosowaniu dodatkowej instrukcji EXIT. W przypadku, gdy ta
instrukcja zostanie pominięta w konstrukcji pętli prostej działanie jej może trwać w nieskończoność. W rzeczywistości oczywiście takie „nieskończone” działanie pętli prostej może zostać
zakończone, ale dopiero poprzez np. anulowanie operacji, zakończenie sesji działania programu
lub zamknięcie systemu bazy danych zatrzymuje działanie tak skonstruowanej pętli. Nazywanie
więc pętli prostej „nieskończoną” jest nieco przesadzone. Tym niemniej chociażby na podstawie
powyżej podanych sposobów przerwania tak działającej pętli prostej widać, iż skonstruowanie
takiej pętli prostej, a później jej uruchomienie prowadzi do pewnych komplikacji.
Pętle numeryczne FOR
Poprzednio omówione typy pętli dotyczyły przypadków wykonywania powtórnego pewnej
sekwencji instrukcji, przy czym liczba iteracji (powtórzeń) nie jest znana przed ich wykonaniem,
lecz zależy od pewnych warunków. W przypadku pętli numerycznych FOR mamy do czynienia
z liczbą iteracji, która z góry jest znana. Nie oznacza to jednak w ścisłym tego słowa znaczeniu,
iż należy znać dokładną liczbę powtórzeń. Dla tego typu pętli wystarcza podanie wartości
początkowej i końcowej, które to wartości określają pierwszą i ostatnią iterację. Pętle
numeryczne FOR pozwalają na określenie liczby iteracji.
Składnia pętli numerycznej FOR jest następująca:
FOR licznik_pętli IN [REVERSE] dolna_granica …gorna_granica LOOP
sekwencja_instrukcji;
END LOOP;
gdzie:
licznik_pętli – jest to identyfikator, który daje możliwość sprawdzenia, w której iteracji
znajduje się aktualne wykonywanie pętli. Deklaracja tego identyfikatora nie jest konieczna w
części deklaracji bloku PL/SQL.
dolna_granica – jest to wyrażenie liczbowe, które służy do obliczenia najmniejszej wartości
przypisywanej do zmiennej licznik_pętli;
18
Wykład 4 – Struktury sterowania w języku PL/SQL – dr hab. prof. UŁ. Tadeusz Antczak
gorna_granica – jest to wyrażenie liczbowe, które służy do obliczenia najmniejszej wartości
przypisywanej do zmiennej licznik_pętli. Aby instrukcje zawarte w pętli zostały wykonane,
gorna_granica musi być większa bądź przynajmniej równa wartości wyrażenia
dolna_granica;
sekwencja_instrukcji jest pewną liczbą instrukcji zawartą i wykonywaną w ramach pętli;
REVERSE – jeśli to słowo kluczowe nie jest uwzględnione w składni pętli numerycznej, to
licznik pętli jest zwiększany o jeden po wykonaniu każdej iteracji pętli, poczynając od dolnej
aż po górną wartość. Wprowadzenie tego słowa kluczowego do konstrukcji pętli powoduje,
że licznik jest zmniejszany o jeden, poczynając od górnej, a skończywszy na dolnej wartości.
Indeks pętli dla pętli FOR jest niejawnie deklarowany jako dana typu BINARY_INTEGER. Nie
jest zatem konieczne jego deklarowanie przed samym kodem pętli w programie. Jeżeli jednak
zmienna o takiej samej nazwie jak indeks pętli zostanie zadeklarowana, to inicjacja pętli
spowoduje ukrycie tej zmiennej wewnątrz pętli w taki sam sposób, jak deklaracja zmiennej w
bloku wewnętrznym może ukryć deklarację zmiennej o tej samej nazwie w bloku zewnętrznym.
Ilustracją takiego przypadku jest poniższy przykład:
DECLARE
z_Licznik NUMBER:=7;
BEGIN
-- Wstawienie wartości 7 do tabeli tabela_tymcz.
INSERT INTO tabela_tymcz(kol_num)
VALUES (z_Licznik, ‘Indeks pętli’);
/* Poniższa pętla ponownie deklaruje zmienną z_Licznik jako daną typu BINARY_INTEGER, gdyż
zmienna ta jest licznikiem pętli numerycznej, co ukrywa deklarację zmiennej z_Licznik
zadeklarowanej na zewnątrz pętli jako danej typu NUMBER */
FOR z_Licznik IN 20…30 LOOP
-- Wewnątrz pętli zmienna z_Licznik ma wartość w zakresie od 20 do 30.
INSERT INTO tabela_tymcz (kol_num)
VALUES (z_Licznik);
END LOOP;
/* Wstawienie do tabeli tabela_tymcz wartości 7 zmiennej z_Licznik zadeklarowanej jako
zmiennatypu NUMBER w bloku deklaracji */
INSERT INTO tabela_tymcz (kol_num)
VALUES (z_Licznik);
END;
19
Wykład 4 – Struktury sterowania w języku PL/SQL – dr hab. prof. UŁ. Tadeusz Antczak
Granice pętli są wyznaczone tylko raz. Na ich podstawie jest ustalana całkowita liczba iteracji,
którą przyjmie indeks licznik_petli na podstawie wartości parametrów dolna_granica oraz
gorna_granica. Wartość indeksu pętli będzie zwiększana o 1 po każdej iteracji (w przypadku
uzycia słowa kluczowego zmniejszanie o jeden), dopóki wykonywanie pętli nie zostanie
zakończone. Należy również pamiętać o tym, iż wykorzystując słowo kluczowe REVERSE w
składni pętli FOR nie należy zmieniać miejscami granicy dolnej i górnej wartości licznika pętli.
Ilustruje to poniższy fragment kodu dla pętli numerycznej z wykorzystaniem słowa kluczowego
REVERSE:
FOR i IN REVERSE 1..5 LOOP
…
END LOOP;
Jest to poprawna składnia pętli numerycznej, której licznik przyjmuje kolejno wartości 5, 4, 3, 2,
1.
Ponadto dolna i górna granica wartości licznika w pętli FOR nie muszą być literałami, o czym
przekonuje nas poniższy fragment kodu:
FOR z_Miesiac IN 1..TO_NUMBER(TO_CHAR(SYSDATE, ‘MM’)) LOOP
IF TO_NUMBER(TO_CHAR(data_wystawienia, ‘MM’))=z_Miesiac THEN
DBMS_OUTPUT.PUT_LINE(nr||’ ‘||data_wystawienia);
END IF;
END LOOP;
W powyższej składni pętli FOR wyrażenie TO_NUMBER(TO_CHAR(SYSDATE, ‘MM’))
zostało użyte do wyznaczenia górnej wartości licznika pętli. W ten sposób, jeśli aktualnym
miesiącem jest marzec, to pętla umożliwi wyświetlenie wszystkich faktur wystawionych w
styczniu, lutym i marcu. Taki sposób podawania dolnej i górnej granicy zakresu indeksu pętli
pozwala na ich dynamiczne określanie.
Etykiety pętli
Pętlom języka PL/SQL mogą być przydzielane etykiety w celu określenia, której pętli dotyczą
działania. Etykiety są ujmowane w podwójne, ostre nawiasy. Jeżeli pętlom nadano etykietę, to
nazwa etykiety może opcjonalnie występować po instrukcji END LOOP. Ponadto taka etykieta
może zostać np. wykorzystana w instrukcji EXIT w celu wskazania, z której pętli ma nastąpić
wyjście. Ilustruje to poniższy przykładowy blok PL/SQL:
20
Wykład 4 – Struktury sterowania w języku PL/SQL – dr hab. prof. UŁ. Tadeusz Antczak
BEGIN
<<e_Zewnetrzna>>
FOR v_IndeksZewnetrzny IN 1..30 LOOP
…
<<e_Wewnetrzna>>
FOR v_IndeksWewnetrzny IN 2..5 LOOP
…
IF v_IndeksZewnetrzny > 10 THEN
EXIT e_Zewnetrzna;
-- Wyjście z obydwu pętli
END IF;
END LOOP e_Wewnetrzna;
END LOOP e_Zewnetrzna;
END;
Instrukcja skoku GOTO
W języku PL/SQL mamy możliwość użycia tzw. instrukcji skoku GOTO o składni:
GOTO etykieta;
gdzie:
etykieta jest etykietą definiowaną w bloku PL/SQL.
Po rozpoczęciu wykonywania instrukcji GOTO sterowanie zostaje natychmiast przekazane do
instrukcji określonej etykietą. Poniższy przykład kodu ilustruje możliwość wykorzystani
instrukcji GOTO i wstawiania etykiet do programu:
DECLARE
z_Licznik
BINARY_INTEGER:=1;
BEGIN
LOOP
INSERT INTO tabela_tymcz
VALUES (z_Licznik, ‘Licznik pętli’);
z_Licznik:= z_Licznik + 1;
IF z_Licznik > 10 THEN
GOTO e_KoniecPetli;
END IF;
END LOOP;
21
Wykład 4 – Struktury sterowania w języku PL/SQL – dr hab. prof. UŁ. Tadeusz Antczak
<<e_Koniec_Pętli>>
INSERT INTO tabela_tymcz(kol_znak)
VALUES(‘Operacja wykonana!’);
END; /
Ograniczenia instrukcji GOTO
Język PL/SQL nakłada ograniczenia na korzystanie z instrukcji GOTO.
Niedozwolone jest przekazywanie sterowania:
 do bloków wewnętrznych,
 do pętli,
 do instrukcji IF,
 między klauzulami IF,
 z procedury obsługi wyjątków z powrotem do bieżącego bloku.
Gdyby te zastosowania były dozwolone, wówczas niektóre z zasad dotyczących działania
instrukcji warunkowych, pętli i zagnieżdżonych bloków mogłyby być złamane. Przypuśćmy, iż
przekazywanie sterowania za pomocą instrukcji GOTO jest możliwe w przypadku instrukcji
warunkowej IF. Wówczas instrukcje wewnątrz instrukcji IF mogłyby być wykonywane nawet w
przypadku, gdy warunek logiczny IF nie zostałby oceniony jako wartość TRUE, co jest
niezgodne z zasadą działania tej instrukcji. Przykład niedozwolonego użycia instrukcji GOTO
ilustruje poniższy przykład:
BEGIN
GOTO e_BlokWewnetrzny;
/* Niedozwolone użycie GOTO, gdyż nie można przekazywać sterowania do bloku
wewnętrznego */
BEGIN
...
<<e_BlokWewnetrzny>>
...
END;
GOTO e_WewnatrzIF
-- Niedozwolone uzycie GOTO, gdyż nie można przekazywać sterowania do instrukcji IF
IF x > 5 THEN
22
Wykład 4 – Struktury sterowania w języku PL/SQL – dr hab. prof. UŁ. Tadeusz Antczak
...
<<e_WewnatrzIF>>
...
END IF;
END;
Wskazówki dotyczące instrukcji GOTO
Podczas stosowania instrukcji GOTO należy zachować ostrożność. Wprowadzenie
niepotrzebnych instrukcji GOTO może spowodować powstanie kodu niestrukturalnego – kodu,
w którym następują skoki sterowania wykonywaniem programu z jednego miejsca do drugiego
bez wyraźnej przyczyny. Może to doprowadzić do nieoczekiwanych i błędnych zachowań
programu.
Uwaga: Wykorzystanie instrukcji GOTO świadczy na ogół o niedopracowaniu konstrukcji
programu. Prawie we wszystkich przypadkach wykorzystania instrukcji GOTO istnieje
możliwość jej zastąpienia innymi strukturami sterowania PL/SQL, takimi jak pętle lub instrukcje
warunkowe. Również w celu opuszczenia głęboko zagnieżdżonych pętli zamiast przekazania
sterowania na koniec kodu można zastosować wyjątki.
Wartości NULL w języku PL/SQL
Często zdarza się, iż początkujący użytkownik systemu Oracle ma w początkowym okresie
wykorzystania jego języków programowania, tj. SQL i PL/SQL, pewne kłopoty dotyczące
zrozumienia zagadnień związanych z wartością NULL.
Kiedy zmienna, wartość w kolumnie tabeli lub stała ma wartość NULL, oznacza to, że dana
wartość jest albo niezdefiniowana, albo nieznana, co wcale nie oznacza, iż jest to wartość zerowa
lub o wartości FALSE. Wartość nieznana oznacza, że zmienna o tej wartości w ogóle nie ma
wartości, a zatem nie może być bezpośrednio porównywana z innymi zmiennymi.
Uwaga: W celu sprawdzenie, czy jakaś zmienna ma wartość NULL nie należy używać do tego
celu operatora równości (=), gdyż może to prowadzić do otrzymania dziwnych wyników. Należy
w tym celu używać operatora IS NULL lub operatora IS NOT NULL.
Należy pamiętać, iż każda zmienna deklarowana bez wartości początkowej posiada wartość
NULL. A zatem nie jest możliwe np. jej porównanie za pomocą operatora równości. Należy
zachować szczególną ostrożność, jeśli zmienna ta jest typu numerycznego, gdyż działania
arytmetyczne wykonywane na takiej zmiennej dają w wyniku NULL.
23
Wykład 4 – Struktury sterowania w języku PL/SQL – dr hab. prof. UŁ. Tadeusz Antczak
Ponieważ takie zachowanie, w której jedna wartość NULL zmienia wynik na wartość NULL
choćby w działaniach arytmetycznych, jest bardzo niekorzystne, w celu otrzymania sensownego
wyniku można dokonać pewnej konwersji wartości NULL. Można w tym celu wykorzystać
wbudowana funkcję NVL o składni:
NVL(wyrazenie1, wyrazenie2);
gdzie:
wyrazenie1 – wyrażenie, którego wartość jest konwertowana w przypadku, gdy posiada
wartość NULL;
wyrazenie2 – wyrażenie, na które jest konwertowane wyrażenie1 w przypadku, gdy posiada
wartość NULL.
Funkcja NVL sprawdza wyrażenie1 i w przypadku, gdy jego wartość jest inna niż NULL,
zwraca wartość równą wartości wyrazenia1. W przypadku, gdy wyrazenie1 posiada wartość
NULL, funkcja NVL zwraca jako wartość, wartość wyrazenia2.
Należy również pamiętać o tym, iż w systemie Oracle, a zatem w językach SQL i PL/SQL mamy
do czynienia z logiką trójwartościową, a zatem należy uwzględnić ten fakt również dla działań
logicznych. Wartość NULL nie jest równoważna ani wartości logicznej TRUE, ani wartości
logicznej FALSE i wpływa ona znacząco na wynik działania operatorów logicznych.
Instrukcja NULL
Czasami występuje potrzeba jawnego wskazania, że nie będzie wykonywana żadna operacja. Do
tego celu można wykorzystać instrukcję NULL, która nie wykonuje żadnych operacji – służy
jako znak-wypełniacz.
DECLARE
z_Tym
NUMBER:=5;
BEGIN
IF z_Tym < 3 THEN
INSERT INTO tabela_tym(kol_znak)
VALUES (‘Wartość zmiennej jest za mała!’);
ELSIF z_Tym >= 3 AND z_Tym<=7 THEN
INSERT INTO tabela_tym(kol_znak)
VALUES (‘Wartość zmiennej jest dobra!’);
ELSE
NULL;
END IF;
END;
24

Podobne dokumenty