Professional Documents
Culture Documents
Spis treci
Od autora ......................................................................................... 5
Cz I
Cz II
Spis treci
Rozdzia 7.
Procedury skadowane
Zamiast tworzy bloki anonimowe, wygodniej jest organizowa kod w nazwane procedury. W rodowisku baz danych nosz one miano procedur skadowanych. W przypadku jzykw wyszego rzdu taka organizacja kodu podyktowana jest chci utrzymania jego przejrzystoci jeli jego fragment ma by wykonywany wielokrotnie,
warto go umieci w procedurze i odwoywa si do niego tylko przez jej wywoywanie.
Take rne funkcjonalnoci, zadania kodu s argumentem za jego podziaem. Podstawowa skadnia polecenia tworzcego procedur ma posta:
CREATE PROCEDURE nazwa
IS
BEGIN
-- ciao procedury
END;
Zamiast sowa kluczowego IS mona stosowa tosame sowo kluczowe AS. Ciaem
procedury moe by dowolny zestaw instrukcji PL/SQL oraz dowolne zapytania SQL,
za wyjtkiem zapytania wybierajcego SELECT.
W przypadku rodowisk baz danych wydaje si jednak, e argumenty zwizane z organizacj kodu nie s tu najwaniejsze. Dla procedur skadowanych najpniej przy
pierwszym ich wykonaniu generowany jest plan wykonania zapyta wchodzcych w ich
skad, ich kod jest wstpnie optymalizowany, a nastpnie s one prekompilowane. W ten
sposb na serwerze przechowywana jest procedura w dwch postaciach: przepisu na
jej utworzenie CREATE PROCEDURE oraz skompilowanego kodu. Przy kadym nastpnym
wykonaniu odwoujemy si ju do postaci skompilowanej. Sprawia to, e procedury s
wykonywane szybciej i wydajniej ni ten sam kod w formie skryptu. Sprawa nie jest tak
oczywista w przypadku czsto wykonywanych zapyta. Plany wykonania kadego zapytania przechowywane s w pamici wspdzielonej (SGA System Global Area) i jeeli wykonamy je ponownie, wykorzystana zostanie jego przetworzona posta. Naley
jednak pamita, e zgodno dwch zapyta sprawdzana jest z dokadnoci do znaku,
nie jest natomiast analizowana semantyka. Poza tym informacje o planach zapyta s
nadpisywane na stare definicje w momencie wyczerpania zasobw pamici wspdzielonej. Bez wzgldu na te uwagi moemy jednak przyj, e wydajno przetwarzania
procedury skadowanej jest wiksza ni w przypadku rwnowanego jej skryptu (bloku
anonimowego). Jeeli chcemy usun definicj procedury, moemy uy nastpujcego
polecenia:
Cz II ORACLE PL/SQL
164
DROP PROCEDURE nazwa;
Wielokrotnie moemy chcie modyfikowa kod procedury. Ponowne wykonanie polecenia CREATE PROCEDURE spowoduje wykrycie obiektu o tej samej nazwie i wywietlenie komunikatu o bdzie. W zwizku z tym musimy najpierw usun definicj procedury, a nastpnie utworzy j ponownie. Zamiast tego moemy posuy si skadni
CREATE OR REPLACE PROCEDURE, ktra, w zalenoci od tego, czy procedura o danej nazwie ju istnieje, czy te nie, stworzy j od podstaw lub nadpisze na istniejcej now
definicj. Z punktu widzenia programisty nie da si rozrni, ktra z tych akcji zostaa
wykonana (taki sam komunikat Procedura zostaa pomylnie utworzona), dlatego,
korzystajc z tej skadni, naley si upewni, czy nadpisujemy kod waciwej procedury! Przykadem moe by utworzenie procedury, ktrej zadaniem bdzie zamiana
wszystkich nazwisk w tabeli Osoby na pisane duymi literami.
CREATE OR REPLACE PROCEDURE up
IS
BEGIN
UPDATE Osoby SET Nazwisko=UPPER(Nazwisko);
END;
Jak wida, ciao procedury zawiera zapytanie aktualizujce UPDATE zgodne ze skadni
SQL. Jej wywoanie moe odby si na przykad z wntrza bloku anonimowego o postaci:
BEGIN
up;
END;
Zamy, e w ramach tego samego skryptu chcielibymy sprawdzi poprawno wykonania procedury zapytaniem wybierajcym SELECT. Zgodnie z wczeniejsz uwag,
zamieszczenie go w ciele bloku anonimowego jest niedozwolone. Rwnie umieszczenie zapytania wybierajcego bezporednio po sowie kluczowym END; zakoczy
si komunikatem o bdzie. Std konieczno podzielenia skryptu na dwie czci, ktre
z punktu widzenia serwera stanowi bd osobne fragmenty. Znakiem odpowiedzialnym za taki podzia jest slash (/), przy czym czci bd traktowane jako fragmenty
kodu PL/SQL lub zapytania SQL, w zalenoci od zawartoci. Skrypt moe zosta
podzielony w ten sposb na dowoln liczb niezalenych fragmentw.
BEGIN
up;
END;
/
SELECT Nazwisko FROM Osoby;
Innym przykadem realizacji procedury skadowanej jest zastosowanie jej do przepisywania nazwisk i wzrostu osb do tabeli wys_tab, przy czym rekordy posortowane
bd malejco wedug wzrostu. Naley zauway, e tabela wys_tab o odpowiedniej
strukturze musi ju istnie w schemacie uytkownika.
CREATE OR REPLACE PROCEDURE wysocy
IS
BEGIN
INSERT INTO wys_tab(Nazwisko,Wzrost)
SELECT Nazwisko, Wzrost FROM Osoby
ORDER BY Wzrost DESC;
END wysocy;
165
W przedstawionym przykadzie definicja tworzonej procedury jest koczona poleceniem END nazwa;, gdzie nazwa jest jej nazw. Pominicie jej w tym poleceniu nie pociga za sob adnych zmian. Koczenie definicji procedury w prezentowany sposb
jest wskazane ze wzgldw organizacyjnych, porzdkowych, zwaszcza wtedy, kiedy
skrypt zawiera wiksz liczb zoonych procedur, co utrudnia znalezienie kocw definicji przy jego poprawianiu.
Dotychczas prezentowane przykady byy procedurami niepobierajcymi adnych danych z wywoujcego je skryptu byy bezparametrowe. Brak parametrw wywoania jest szczeglnie widoczny w drugim przypadku, gdzie do tabeli wys_tab trafiaj
wszyscy pracownicy wszyscy s traktowani jako wysocy. Zmodyfikujmy t procedur tak, aby do tabeli docelowej przepisywane byy tylko osoby wysze od pewnego
progu danego w postaci parametru.
CREATE OR REPLACE PROCEDURE wysocy
(mm number)
IS
BEGIN
INSERT INTO wys_tab(Nazwisko,wzrost)
SELECT Nazwisko, wzrost FROM Osoby
WHERE wzrost > mm
ORDER BY wzrost DESC;
END wysocy;
Jak pokazano, parametry procedury definiowane s w nawiasie po jej nazwie, a na minimaln definicj skada si nazwa i typ parametru, przy czym typ podawany jest bez
definiowania rozmiaru, czyli number, a nie number(10). Podanie rozmiaru w tym miejscu powoduje wywietlenie komunikatu o bdzie. Zdefiniowanie parametru procedury
sprawia, e jest on traktowany tak jak zadeklarowana zmienna i nie moe zosta zadeklarowany ponownie w jej ciele. Moe on zosta uyty w dowolnym miejscu definicji
procedury; w przedstawionym przykadzie zosta wykorzystany do sformuowania warunku w klauzuli WHERE zapytania wstawiajcego wiersze.
Jeeli chcemy uy w definicji procedury wicej ni jednego parametru, ich lista powinna by rozdzielona przecinkami. W przykadzie przedstawiono procedur, ktra
wstawia do tabeli Dodatki wiersze zawierajce sum wartoci brutto i staej danej drugim parametrem procedury Dodatek dla osoby, ktrej identyfikator zawiera pierwszy
z parametrw Num.
CREATE OR REPLACE PROCEDURE Dodaj
(Num number, Dodatek number)
IS
BEGIN
INSERT INTO Dodatki
SELECT Brutto+Dodatek FROM Zarobki
WHERE IdOsoby = Num;
END;
Jak przedstawiono to w dotychczasowych przykadach, zawarto procedury mog stanowi wszystkie zapytania modyfikujce dane, ale rwnie zapytania tworzce lub modyfikujce struktur bazy. Czasami jednak, zamiast wykonywa jakie operacje na danych, chcemy dokona operacji zwracajcej wynik w postaci zmiennej, np. policzy czy
Cz II ORACLE PL/SQL
166
Wywoanie tak zdefiniowanej procedury z bloku anonimowego wymaga zadeklarowania zmiennej, do ktrej zostanie przypisany parametr typu OUT. Musi ona mie typ
zgodny z parametrem formalnym, ale wymagane jest te podanie jego rozmiaru, o ile
typ nie oferuje rozmiaru domylnego. W prezentowanym przykadzie zadeklarowano
zmienn ile jako number (bo domylnie number number(10)). W przypadku zmiennych znakowych rozmiar pola musi by dany jawnie (varchar(11)). Wywoania procedury dokonujemy przez podanie jej nazwy oraz zdefiniowanie wartoci parametrw
czyli podanie listy parametrw aktualnych. Do parametrw typu IN moemy przypisywa zarwno zmienne, jak i stae, natomiast do parametrw typu OUT musimy
przypisa zmienne. W prezentowanym przykadzie nazwa zmiennej oraz parametru
w definicji procedury jest taka sama, co jest powszechnie stosowan notacj, cho ze
wzgldw skadniowych zgodno nazw nie jest wymagana.
SET SERVEROUTPUT ON;
DECLARE
ile number;
BEGIN
wysocy(1.8, ile);
DBMS_OUTPUT.PUT_LINE(ile);
END;
Oczywicie procedura moe zawiera wicej ni jeden parametr typu OUT. Zamy,
e oprcz liczby osb o wzrocie wikszym od wartoci progowej chcemy wyznaczy
ich redni wzrost. Moemy zastosowa dwa zapytania agregujce, ktre okrel interesujce nas wartoci, jednak bardziej wydajne jest uycie podwjnego przypisania w zapytaniu SELECT ... INTO. Jeli zwraca ono jeden wiersz, to po sowie kluczowym INTO musimy umieci tyle zmiennych, ile wyrae jest wyznaczanych w jego pierwszej czci.
167
Dla procedury ze zdefiniowan wartoci domyln poprawne jest wywoanie, w ktrym podajemy warto posiadajcego j parametru. Wwczas warto podana przy
wywoaniu nadpisuje si na domyln.
SET SERVEROUTPUT ON;
DECLARE
ile number;
BEGIN
wysocy(1.8,ile);
DBMS_OUTPUT.PUT_LINE(ile);
END;
Jeeli jednak chcemy przy tak zdefiniowanych parametrach odwoa si do wartoci domylnej, to musimy zastosowa wywoanie nazewnicze o postaci parametr=>zmienna,
gdzie parametr jest nazw parametru formalnego procedury, a zmienna jest wartoci
aktualn tego parametru w miejscu, z ktrego j wywoujemy. Notacj t moemy
odczytywa jako parametr staje si zmienn. W przypadku takiego wywoania
zmienna, ktra nie zostaa w nim wymieniona, bdzie miaa przypisan warto domyln.
Gdyby w definicji procedury pominita w wywoaniu zmienna nie miaa zdefiniowanej
wartoci domylnej, to takie wywoanie spowodowaoby wywietlenie komunikatu
o bdzie.
SET SERVEROUTPUT ON;
DECLARE
ile number;
BEGIN
wysocy(ile => ile);
DBMS_OUTPUT.PUT_LINE(ile);
END;
W definicji procedury zmieniamy kolejno parametrw tak, e drugi z nich ma przypisan warto domyln. Reszta procedury pozostaje bez zmian.
Cz II ORACLE PL/SQL
168
CREATE OR REPLACE PROCEDURE wysocy
(ile OUT NUMBER, mm NUMBER DEFAULT 1.7)
IS
BEGIN
SELECT COUNT(wzrost) INTO ile FROM Osoby
WHERE wzrost > mm;
END wysocy;
Oczywicie bardziej oglne jest wywoanie nazewnicze, ktre, bez wzgldu na to, na
ktrych pozycjach znajduj si wartoci domylne, jest zawsze poprawne.
SET SERVEROUTPUT ON;
DECLARE
ile number;
BEGIN
wysocy(ile => ile);
DBMS_OUTPUT.PUT_LINE(ile);
END;
Wywoanie nazewnicze jest dopuszczalne rwnie wtedy, kiedy podajemy peny zestaw parametrw. W takim przypadku kolejno ich wymieniania nie odgrywa adnej roli.
SET SERVEROUTPUT ON;
DECLARE
ile number;
BEGIN
wysocy(mm=>1.8, ile=>ile);
DBMS_OUTPUT.PUT_LINE(ile);
END;
Do wersji 11. moliwe byo stosowanie albo tylko wywoania pozycyjnego, albo nazewniczego jednoczesne uycie obu tych typw nie byo dozwolone. Od wersji 11.
istnieje ju taka moliwo. Przeanalizujmy to na przykadzie procedury o trzech parametrach numerycznych. Pierwsze dwa s typu IN, a trzeci typu OUT. W ciele procedury warto parametru wyjciowego c jest wyznaczana w postaci ilorazu dwch pierwszych parametrw.
CREATE OR REPLACE PROCEDURE dziel
(a real, b real, c OUT real)
AS
BEGIN
c:=a/b;
END;
169
|| res);
|| res);
|| res);
|| res);
Nie kade wywoanie mieszane jest jednak dopuszczalne. Dozwolone s tylko takie
przypadki, w ktrych pierwsze na licie parametry podstawiane s pozycyjnie, a pozostae nazewniczo. Kolejny przykad pokazuje niepoprawne uycie wywoania mieszanego, gdzie bd polega na tym, e rodkowy parametr jest dany nazewniczo, czyli,
inaczej mwic, e po parametrze danym nazewniczo istnieje cho jeden dany pozycyjnie.
DECLARE
res real;
BEGIN
dziel(10, b => 9, res);
DBMS_OUTPUT.PUT_LINE('Wynik ' || res);
END;
Cz II ORACLE PL/SQL
170
Przy okazji prezentowania tego przykadu chc przedstawi nieco archaiczne wywoanie procedury z zastosowaniem polecenia CALL. Poprawnymi parametrami s tu nazwy funkcji operujcych na zmiennych acuchowych: UPPER przepisanie acucha
do postaci pisanej tylko duymi literami, LOWER przepisanie acucha do postaci pisanej tylko maymi literami, INITCAP przepisanie acucha do postaci pisanej od
duej litery. Poprawne jest rwnie uycie pustego cigu znakw '' lub cigu ska'. Zalet tego typu wywoania jest moliwo zadajcego si z samych spacji '
stosowania bezporednio po nim zapytania wybierajcego, ktre ma za zadanie sprawdzi poprawno wykonania procedury.
CALL exe_tekst('UPPER');
SELECT * FROM osoby;
Kolejny przykad przedstawia zastosowanie w definicji procedury wywoania wbudowanej procedury RAISE_APPLICATION_ERROR, ktra powoduje wygenerowanie (ustanowienie) bdu uytkownika o numerze danym pierwszym parametrem oraz komunikacie stanowicym drugi z parametrw. Naley zauway, e numeracja bdw w Oracle
przebiega przez wartoci ujemne, a dla bdw uytkownika zarezerwowano przedzia
<29999, 20001>. Wywoanie powyszej procedury powoduje przerwanie dziaania
programu i wywietlenie komunikatu o bdzie.
171
Bardziej zoonym przykadem zastosowania RAISE_APPLICATION_ERROR jest wykorzystanie jej podczas wykonywania procedury o ograniczonym zestawie danych wejciowych, co ma miejsce np. w opracowanej poprzednio procedurze exe_tekst. Jeeli
parametr wejciowy nie jest jednym z dopuszczalnych elementw wymienionych na
licie, generowany jest bd z odpowiednim komentarzem. W przeciwnym przypadku
wykonywane jest za pomoc polecenia EXECUTE IMMEDIATE zapytanie. Naley zwrci
uwag na fakt, e do porwnania z elementami listy uyto zmiennej przetworzonej do
postaci pisanej duymi literami UPPER(typ), gdy przy porwnywaniu acuchw
Oracle rozrnia ich wielko. Pozwala to na podanie w wywoaniu procedury nazwy
funkcji modyfikujcej acuch pisanej w dowolny sposb (literami maymi, duymi oraz
rnej wielkoci).
CREATE OR REPLACE PROCEDURE exe_tekst
(typ varchar2)
IS
BEGIN
IF UPPER(typ) NOT IN('UPPER', 'LOWER', 'INITCAP') THEN
RAISE_APPLICATION_ERROR (-20205, 'Za funkcja');
ELSE
EXECUTE IMMEDIATE
'UPDATE osoby SET Nazwisko=' || typ || '(Nazwisko)';
END IF;
END exe_tekst;
Moemy przeksztaci procedur, tak aby w jej ciele uy wywoania poprzednio utworzonej procedury generujcej bd przetwarzania o nazwie Blad.
CREATE OR REPLACE PROCEDURE exe_tekst
(typ varchar2)
IS
zap varchar2(111);
BEGIN
IF UPPER(typ) NOT IN('UPPER', 'LOWER', 'INITCAP') THEN
Blad;
ELSE
zap:= 'UPDATE osoby SET Nazwisko=' || typ || '(Nazwisko)';
EXECUTE IMMEDIATE zap;
END IF;
END exe_tekst;
Bdy mog si jednak pojawia podczas przetwarzania nie tylko na skutek celowej
dziaalnoci programisty, ale mog by te spowodowane nie zawsze dajcymi si
przewidzie zdarzeniami, bdnymi wywoaniami, nieodpowiednimi parametrami etc.
Moemy mwi wtedy o sytuacji wyjtkowej o powstaniu wyjtku. Takie zdarzenia
mog zosta w PL/SQL obsuone, oprogramowane.
Cz II ORACLE PL/SQL
172
Rozwamy przykad procedury, ktrej zadaniem jest okrelenie, czy pracownik o danym
numerze identyfikacyjnym IdOsoby, wskazanym parametrem num, istnieje w tabeli
Osoby. Jeli tak, drugi z parametrw (status) ma przyj warto 1; w przypadku
przeciwnym 0. W celu realizacji tego zadania zastosowano zapytanie wybierajce zwracajce do zmiennej pomocniczej kto identyfikator osoby. Jeeli pracownik o danym
identyfikatorze istnieje, warto zwrcona przez zapytanie i warto parametru bd
takie same, jeli jednak takiego pracownika nie ma, zapytanie wybierajce nie zwrci
adnego wiersza. Spowoduje to, e prba podstawienia pod zmienn kto zakoczy si
bdem przetwarzania: Nie znaleziono adnych wierszy. Stan ten moemy wykorzysta, wprowadzajc sekcj EXCEPTION i oprogramowujc wyjtek NO_DATA_FOUND, ktrego obsuga wykonywana jest wedug schematu WHEN nazwa_wyjtku THEN instrukcje.
W naszym przypadku obsuga wyjtku zawiera podstawienie odpowiedniej wartoci pod
zmienn status oraz wypisanie komunikatu.
CREATE OR REPLACE PROCEDURE czy_jest
(num IN NUMBER, status OUT NUMBER)
IS
kto NUMBER;
BEGIN
SELECT IdOsoby INTO kto
ROM Osoby WHERE IdOsoby = num;
IF (kto = num) THEN
status := 1;
DBMS_OUTPUT.PUT_LINE ('Pracownik istnieje');
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
status := 0;
DBMS_OUTPUT.PUT_LINE('Pracownik nie istnieje');
WHEN OTHERS THEN
NULL;
END;
W rodowisku Oracle zdefiniowano wiele wyjtkw, ktrych nazwy symboliczne i przyczyny wystpienia zawiera tabela 7.1. Jeeli gdziekolwiek w ciele procedury wystpuje
sytuacja wyjtkowa, przetwarzanie przenoszone jest do sekcji obsugi wyjtkw. Najpierw sprawdzane jest to, czy wyjtek, ktry przerwa przetwarzanie, jest zgodny z nazw
symboliczn wystpujc w sekcji EXCEPTION. Nastpnie wykonywane s instrukcje znajdujce si po sowie kluczowym THEN jego obsugi, po czym przerywane jest przetwarzanie procedury i nastpuje powrt do miejsca, z ktrego zostaa ona wywoana. Jeli
w trakcie przetwarzania procedury pojawi si jednoczenie dokadnie dwa wyjtki,
co jest moliwe, chocia mao prawdopodobne, to obsuony zostanie tylko ten, ktry
wystpuje jako pierwszy na licie w sekcji obsugi wyjtkw. Na szczegln uwag
zasuguje wyjtek o nazwie OTHERS, ktry obsuguje wszystkie inne, dotd nieobsuone. Gdyby znalaz si on na pierwszym miejscu listy obsugi wyjtkw, to bez wzgldu
na to, jakie zdarzenie powodowaoby wystpienie sytuacji wyjtkowej, wykonywana
byaby zawsze ta sama sekcja znajdujca si po OTHERS. Od wersji 9. Oracle umieszczanie obsugi wyjtku OTHERS przed obsug jakiegokolwiek innego jest zabronione
skadniowo. Innymi sowy, jego obsuga musi by ostatnim elementem sekcji obsugi
wyjtkw. W prezentowanym przykadzie zastosowano minimaln obsug wyjtku
(sekcja nie moe by pusta) NULL, nie rb nic. Bez wzgldu na to, czy wyjtki s w procedurze obsugiwane, czy te nie, zasady jej wywoania pozostaj bez zmian.
173
Numer bdu
Opis
NO_DATA_FOUND
ORA-01403
TOO_MANY_ROWS
ORA-01422
INVALID_CURSOR
ORA-01001
ZERO_DIVIDE
ORA-01476
DUP_VAL_ON_INDEX
ORA-00001
INVALID_NUMBER
ORA-01722
CURSOR_ALREADY_OPEN
ORA-06511
LOGIN_DENIED
ORA-01017
NOT_LOGGED_ON
ORA-01012
PROGRAM_ERROR
ORA-06501
STORAGE_ERROR
ORA-06500
TIMEOUT_ON_RESOURCE
ORA-00051
ACCESS_INTO_NULL
ORA-06530
CASE_NOT_FOUND
ORA-06592
Cz II ORACLE PL/SQL
174
Przedstawiony poprzednio przykad jest niewtpliwie akademicki, poniewa wykorzystuje sekcj obsugi wyjtkw do wyznaczania parametru OUT. W praktyce, jeli
w tym miejscu jest wyznaczany jaki parametr wyjciowy, to jest on odpowiedzialny
za kodowanie sposobu zakoczenia przetwarzania, np. 0 przetwarzanie zakoczone
sukcesem, <>0 przetwarzanie zakoczone niepowodzeniem; konkretna warto koduje przyczyn. Nasz procedur moglibymy wic doprowadzi do postaci, w ktrej
wykorzystywalibymy funkcj agregujc COUNT.
CREATE OR REPLACE PROCEDURE czy_jest
(num IN NUMBER, status OUT NUMBER, ok OUT NUMBER)
IS
BEGIN
ok:=0;
SELECT COUNT(IdOsoby) INTO status
FROM Osoby WHERE IdOsoby = num;
IF (status = 1) THEN
DBMS_OUTPUT.PUT_LINE ('Pracownik istnieje');
ELSE
DBMS_OUTPUT.PUT_LINE('Pracownik nie istnieje');
END IF;
EXCEPTION
WHEN OTHERS THEN
ok := 99;
DBMS_OUTPUT.PUT_LINE('Bd przetwarzania');
END;
175
ok := 11;
DBMS_OUTPUT.PUT_LINE('Bd wartoci');
WHEN OTHERS THEN
ok := 99;
DBMS_OUTPUT.PUT_LINE('Bd przetwarzania');
END;
Nie zawsze jest tak, e wyjtek musi wiza si z formalnym bdem przetwarzania.
Czasami wygodnym jest, aby pewne sytuacje nieprowadzce do bdw formalnych
byy traktowane jako wyjtkowe. Mwimy wtedy o wyjtkach uytkownika, ktre musz
zosta zdefiniowane, wykryte i ktre powinny zosta obsuone. W prezentowanym
przykadzie za sytuacj wyjtkow bdziemy chcieli uzna fakt, e nie ma osb o wzrocie wyszym od progu danego parametrem. Jak wida, taka sytuacja nie spowoduje
powstania bdu przetwarzania trzeba wic j wykry.
CREATE OR REPLACE PROCEDURE licz
(mini NUMBER, ile out INT)
IS
brakuje EXCEPTION;
BEGIN
SELECT COUNT(IdOsoby) INTO ile FROM Osoby
WHERE Wzrost > mini;
IF (ile = 0) THEN
RAISE brakuje;
END IF;
EXCEPTION
WHEN brakuje THEN
RAISE;
WHEN OTHERS THEN
NULL;
END;
Deklaracji wyjtku uytkownika, tak samo jak kadej innej zmiennej, dokonujemy
w sekcji deklaracji i nadajemy mu typ EXCEPTION (jak wida, to sowo kluczowe peni
podwjn rol: jest okreleniem typu oraz sygnalizuje pocztek sekcji obsugi wyjtkw).
W przykadzie zdefiniowano wyjtek o nazwie brakuje. Po zliczeniu osb o wzrocie
wyszym od wartoci progowej instrukcj warunkow sprawdzono, czy ich liczba jest
rwna 0, po czym dla takiego przypadku poleceniem RAISE nazwa_wyjtku ustawiono
(wygenerowano) bd uytkownika. Obsugi wyjtku uytkownika dokonujemy na takich samych zasadach jak wyjtkw wbudowanych (systemowych). W przykadzie zastosowano drug, po minimalnej obsudze NULL, najczciej spotykan metod uycie
polecenia RAISE, ktre odpowiada za wygenerowanie wyjtku. Spowoduje to propagacj wyjtku do miejsca, z ktrego procedura zostaa wywoana. Mona powiedzie,
e nie da si z sekcji obsugi wyjtkw przenie si do tej samej sekcji, wic wyjtek
zgoszony w sekcji obsugi wyjtkw musi zosta obsuony pitro wyej w procedurze wywoujcej.
Bardzo czsto wykorzystujemy przy obsudze wyjtkw dwie wbudowane funkcje
PL/SQL: SQLCODE zwracajc numer wyjtku (bdu), oraz SQLERRM wywietlajc zwizany z tym bdem (wyjtkiem) komunikat. Sposb ich zastosowania ilustruje
nastpny przykad.
Cz II ORACLE PL/SQL
176
CREATE OR REPLACE PROCEDURE licz
(mini NUMBER, ile out INT)
IS
brakuje EXCEPTION;
BEGIN
SELECT COUNT(IdOsoby) INTO ile FROM Osoby
WHERE Wzrost > mini;
IF (ile = 0) THEN
RAISE brakuje;
END IF;
EXCEPTION
WHEN brakuje THEN
DBMS_OUTPUT.PUT_LINE('Nie ma takich');
DBMS_OUTPUT.PUT_LINE('kod - ' || SQLCODE);
DBMS_OUTPUT.PUT_LINE('opis - ' || SQLERRM);
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLCODE);
END;
Takie rozwizanie ma t wad, e musimy dopasowywa komunikat systemowy do wasnych potrzeb, co nie zawsze jest atwe. Pozostaje wic zrezygnowa z definiowania bdu
uytkownika na rzecz stosowania bezporednio polecenia RAISE_APPLICATION_ERROR
lub opisanej poprzednio procedury Blad, ktra to polecenie zawiera wtedy obsuga
nastpi w sekcji OTHERS. Moliwe jest rwnie korzystanie przy obsudze bdu uytkownika z polecenia RAISE_APPLICATION_ERROR w sekcji obsugi wyjtkw.
177
Z czasem, kiedy bdziemy tworzyli coraz bardziej skomplikowane elementy proceduralne PL/SQL (procedury, funkcje), coraz wiksze bdzie ryzyko, e podczas ich generowania popenimy bdy formalne, skadniowe. Standardowo, jeli w procedurze
znajd si takie bdy, otrzymamy komunikat: Procedura utworzona z bdami kompilacji. Jeli chcemy otrzyma bardziej zoon informacj o popenionych podczas
tworzenia ostatniego elementu proceduralnego bdach, moemy wykona polecenie:
SHOW ERRORS;
Pomimo e wygenerowana w ten sposb informacja jest zdecydowanie bardziej szczegowa, naley z duym dystansem podchodzi do wskazywanych linii kodu, w ktrych
wykryto nieprawidowoci. Bardzo czsto wskazanie to wynika z wczeniej popenionych bdw. Prostym wnioskiem jest ten, e procedur powinnimy poprawia, poczwszy od bdw najwczeniej wykrytych, co w wikszoci przypadkw daje poprawne rezultaty.