Struktury sterowania PL/SQL

Podobne dokumenty
Bloki anonimowe w PL/SQL

Pętle. Dodał Administrator niedziela, 14 marzec :27

Opis: Instrukcja warunkowa Składnia: IF [NOT] warunek [AND [NOT] warunek] [OR [NOT] warunek].

DECLARE <nazwa_zmiennej> typ [(<rozmiar> )] [ NOT NULL ] [ { := DEFAULT } <wartość> ];

Plan wykładu BAZY DANYCH II WYKŁAD 3. Zasięg zmiennych. Zasięg zmiennych

Pętla for. Wynik działania programu:

Uwagi dotyczące notacji kodu! Moduły. Struktura modułu. Procedury. Opcje modułu (niektóre)

1 Podstawy c++ w pigułce.

1. ELEMENTY JĘZYKA PL/SQL

for (inicjacja_warunkow_poczatkowych; wyrazenie_warunkowe; wyrazenie_zwiekszajace) { blok instrukcji; }

Wstęp do programowania

PL/SQL. Część 1 Bloki PL/SQL. Piotr Medoń

Podstawy Programowania C++

Liczby losowe i pętla while w języku Python

Jak zawsze wyjdziemy od terminologii. While oznacza dopóki, podczas gdy. Pętla while jest

for (inicjacja_warunkow_poczatkowych(końcowych); wyrazenie_warunkowe; wyrazenie_zwiekszajace(zmniejszające)) { blok instrukcji; }

PODSTAWY INFORMATYKI 1 PRACOWNIA NR 6

Instrukcje sterujące. wer. 11 z drobnymi modyfikacjami! Wojciech Myszka :53:

1 Kursory 1. 2 Wyjątki Wyjątki predefiniowane Wyjątki niezdefiniowane wcześniej Definiowanie własnych wyjątków...

Wstęp do informatyki- wykład 7

PODSTAWY BAZ DANYCH 13. PL/SQL

Instrukcje SQL można podzielić na pięć kategorii, które zostały przedstawione w poniższej tabeli.

Pętla for. Matematyka dla ciekawych świata -19- Scilab. for i=1:10... end. for k=4:-1:1... end. k=3 k=4. k=1. k=2

Plan wykładu Projekt fizyczny bazy danych Wprowadzenie PL/SQL PL/SQL Cechy PL/SQL

Nazwa implementacji: Nauka języka Python wyrażenia warunkowe. Autor: Piotr Fiorek. Opis implementacji: Poznanie wyrażeń warunkowych if elif - else.

Podstawy programowania skrót z wykładów:

Język JAVA podstawy. Wykład 3, część 3. Jacek Rumiński. Politechnika Gdańska, Inżynieria Biomedyczna

1 Podstawy c++ w pigułce.

Oracle PL/SQL. Paweł Rajba.

Oracle PL/SQL. Paweł Rajba.

METODY KOMPUTEROWE W OBLICZENIACH INŻYNIERSKICH

7. Pętle for. Przykłady

Język PL/SQL. Rozdział 2. Kursory

DECLARE VARIABLE zmienna1 typ danych; BEGIN

Instrukcje cykliczne (pętle) WHILE...END WHILE

Kursory - pobieranie danych z baz danych do programów PL/SQL

Procedury składowane. Funkcje vs. procedury Funkcja. Procedura. zazwyczaj ma parametry tylko typu IN; można wywoływać z poziomu

Programowanie w SQL. definicja bloku instrukcji BEGIN...END, warunkowe wykonanie instrukcji IF...ELSE, wyrażenie CASE,

Deklarowanie kursora

Pętle. for, while, do... while, foreach. Materiał pomocniczy do kursu Podstawy programowania Autor: Grzegorz Góralski ggoralski.

Kursor jawny. Rozdział 10a Kursory. Deklarowanie kursora (1) Deklarowanie kursora (2)

Plan wykładu BAZY DANYCH II WYKŁAD 4. Co to jest kursor? Rodzaje kursorów

Podstawy programowania w języku C

Październik Instytut Informatyki Teoretycznej i Stosowanej Politechnika Częstochowska. Systemy baz danych - wykład III. dr inż.

Pętle instrukcje powtórzeo

15. Funkcje i procedury składowane PL/SQL

ORACLE (Wykład 1) aragorn.pb.bialystok.pl/~aonisko. Typy rozproszonych baz danych. Systemy klient-serwer. Klient-serwer: Przykład

Widoczność zmiennych Czy wartości każdej zmiennej można zmieniać w dowolnym miejscu kodu? Czy można zadeklarować dwie zmienne o takich samych nazwach?

Instrukcje sterujące

Wydział Zarządzania AGH. Katedra Informatyki Stosowanej. Pętle. Programowanie komputerowe

Informatyka I. Wykład 3. Sterowanie wykonaniem programu. Instrukcje warunkowe Instrukcje pętli. Dr inż. Andrzej Czerepicki

KURS C/C++ WYKŁAD 2. char znak; znak = a ; Program 2 #include<stdio.h> void main() { char znak; while( (znak = getchar() )!= t ) putchar(znak); }

Kursory i wyjątki. (c) Instytut Informatyki Politechniki Poznańskiej 1

Podstawy Programowania Podstawowa składnia języka C++

Wydział Zarządzania AGH. Katedra Informatyki Stosowanej. Podstawy VBA cz. 1. Programowanie komputerowe

Podstawy programowania w języku Visual Basic dla Aplikacji (VBA)

Po uruchomieniu programu nasza litera zostanie wyświetlona na ekranie

3. Instrukcje warunkowe

LibreOffice Calc VBA

Skrypty powłoki Skrypty Najcz ciej u ywane polecenia w skryptach:

Pakiety podprogramów Dynamiczny SQL

Kursor. Rozdział 10a Kursory. Otwieranie kursora. Deklarowanie kursora

Podstawy programowania. Wykład Pętle. Tablice. Krzysztof Banaś Podstawy programowania 1

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

Pętle i tablice. Spotkanie 3. Pętle: for, while, do while. Tablice. Przykłady

Język C zajęcia nr 5

Schematy blokowe I. 1. Dostępne bloki: 2. Prosty program drukujący tekst.

Laboratorium Wstawianie skryptu na stroną: 2. Komentarze: 3. Deklaracja zmiennych

Operacje wykonywane są na operandach (argumentach operatorów). Przy operacji dodawania: argumentami operatora dodawania + są dwa operandy 2 i 5.

41. Zmienne lokalne muszą mieć nazwę, którą poprzedza (maksymalnie 128 znaków) oraz typ (każdy z wyjątkiem: text, ntext oraz image)

Java Podstawy. Michał Bereta

Pascal - wprowadzenie

Procedury i funkcje składowane

Algorytmy i struktury danych

Podstawy programowania Laboratorium. Ćwiczenie 2 Programowanie strukturalne podstawowe rodzaje instrukcji

OBSŁUGA WYJĄTKÓW. Mechanizm języka PL/SQL. Wyjątki:

Deklarowanie kursora. CURSOR nazwa [ ( param1 typ1 [,param2 typ2]... ) ] [RETURN typ zwracany] IS zapytanie SQL;

PL/SQL. Lidia Małkiewicz i Cezary Skubała

Bloki anonimowe w PL/SQL

Plan wykładu PL/SQL. PL/SQL - historia TWORZENIE APLIKACJI BAZODANOWYCH

Wprowadzenie do programowania w języku C

Programowanie w Turbo Pascal

Skrypty i funkcje Zapisywane są w m-plikach Wywoływane są przez nazwę m-pliku, w którym są zapisane (bez rozszerzenia) M-pliki mogą zawierać

Przykład 1 -->s="hello World!" s = Hello World! -->disp(s) Hello World!

Programowanie komputerowe. Zajęcia 3

Struktura pliku projektu Console Application

Politechnika Gdańska Wydział Elektrotechniki i Automatyki Katedra Inżynierii Systemów Sterowania

Wprowadzenie do języka PL/SQL. Język PL/SQL Wprowadzenie. Struktura blokowa programu. Przykładowy program w PL/SQL. Zmienne rekordowe.

PL/SQL. Zaawansowane tematy PL/SQL

Składowane procedury i funkcje

Cheatsheet PL/SQL Andrzej Klusiewicz 1/9

Wstęp do Programowania Lista 1

Zapis algorytmów: schematy blokowe i pseudokod 1

Algorytmika i Programowanie VBA 1 - podstawy

SQL (ang. Structured Query Language)

Programowanie w języku C++ Grażyna Koba

SQL - Structured Query Language -strukturalny język zapytań SQL SQL SQL SQL

Programowanie strukturalne. Opis ogólny programu w Turbo Pascalu

Każde wykonanie bloku instrukcji nazywamy pojedynczym przebiegiem lub iteracją pętli.

PHP w-3. Sterowanie w PHP

Transkrypt:

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;] 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

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-THEN- ELSE z jedną klauzulą ELSIF i jedną klauzulą ELSE: z_stanproduktu z_komentarz towary.stan%type; VARCHAR(50); /* 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 kod_t =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ń ; 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

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: z_kodproduktu towary.kod_t%type; z_stanproduktu towary.stan%type; z_komentarz VARCHAR(50); /* 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 kod_t = 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

z_komentarz:= Zapas produktu nie wymaga uzupełnień ; INSERT INTO tabela_tymcz ((kol_num, kol_znak) VALUES (z_nrproduktu, z_komentarz); 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 */ z_num1 NUMBER; z_num2 NUMBER; z_wynik VARCHAR(10); IF z_num1 < z_num2 THEN z_wynik:= Tak ; ELSE z_wynik:= Nie ; /* Blok 2 */ z_num1 NUMBER; z_num2 NUMBER; z_wynik VARCHAR(10); IF z_num1 >= z_num2 THEN z_wynik:= Nie ; ELSE z_wynik:= Tak ; 4

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 */ z_num1 NUMBER; z_num2 NUMBER; z_wynik VARCHAR(10); 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 ; /* Blok 2 */ 5

z_num1 NUMBER; z_num2 NUMBER; z_wynik VARCHAR(10); 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 ; 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

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-THEN- ELSE. 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: z_kraj kierowcy.kraj%type; z_nalepka VARCHAR(3); -- 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 ; DBMS_OUTPUT.PUT_LINE(z_Nalepka); / 7

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: z_kraj kierowcy.kraj%type; 8

z_nalepka VARCHAR(3); -- 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); 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> 2 z_kwartal NUMBER:=0 3 4 /* 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

10 END CASE; 11 12 / * 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: z_kwartal NUMBER:=1; -- 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; 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

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> 2 z_miesiac NUMBER:=4; 3 z_statuspracownik CHAR(3):= Tak ; 4 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

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 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

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; Poniższy, przykładowy blok programu wstawia do tabeli tabela_tymcz 50 wierszy: z_licznik BINARY_INTEGER:=1; 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

EXIT; END LOOP; 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. z_licznik BINARY_INTEGER:=1; 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; 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

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: z_licznik BINARY_INTEGER:=1; /* 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; / 15

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. z_licznik BINARY_INTEGER; z_zm1 NUMBER; z_zm2 NUMBER:=0; z_licznik:=0; LOOP z_zm1:=z_zm2; 16

z_zm2:=z_zm1+1; z_licznik:=z_licznik + 1; EXIT WHEN z_licznik = 100 OR z_zm2>99 ; END LOOP; z_licznik BINARY_INTEGER; z_zm1 NUMBER; z_zm2 NUMBER:=0; 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; 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

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

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: z_licznik NUMBER:=7; -- 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); 19

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 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

<<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 LOOP e_wewnetrzna; END LOOP e_zewnetrzna; 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: z_licznik BINARY_INTEGER:=1; 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 LOOP; 21

/ <<e_koniec_pętli>> INSERT INTO tabela_tymcz(kol_znak) VALUES( Operacja wykonana! ); 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: GOTO e_blokwewnetrzny; /* Niedozwolone użycie GOTO, gdyż nie można przekazywać sterowania do bloku wewnętrznego */... <<e_blokwewnetrzny>>... GOTO e_wewnatrzif -- Niedozwolone uzycie GOTO, gdyż nie można przekazywać sterowania do instrukcji IF IF x > 5 THEN 22

... <<e_wewnatrzif>>... 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

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. z_tym NUMBER:=5; 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; 24