Sunteți pe pagina 1din 13

TRATAREA EXCEPTIILOR

Obiective :

Dupa terminarea acestei prezentari veti fi în stare sa realizati urmatoarele :


- definirea exceptiilor PL/SQL
- recunoasterea exceptiilor netratate
- afisarea si folosirea diferitelor tipuri de tratari ale exceptiilor în PL/SQL
- detectarea erorilor neanticipate
- descrierea efectelor propagarii exceptiilor în blocuri imbricate
- modificarea în functie de necesitati a mesajelor de exceptie ale PL/SQL

Scopul prezentarii :
În aceasta prezentare veti învata ce sunt exceptiile PL/SQL si cum se poate lucra cu ele
folosind tratari predefinite, non-predefinite, si definite de utilizator .

Tratarea exceptiilor în PL/SQL

Ce este o exceptie ?
- Un identificator în PL/SQL care apare în timpul unei executii.
Cum apare ?
- La aparitia unei erori.
- Este apelata explicit.
Cum se trateaza ?
- Este capturata într-o rutina de tratare a exceptiei.
- Este propagata spre mediul apelant.

O exceptie este un identificator în PL/SQL , care apare în timpul executiei unui bloc care îsi
încheie partea principala de instructiuni. Un bloc se termina întodeauna când PL/SQL genereaza o
exceptie, dar pot fi specificate rutine utilizator de tratare a acestora în care se pot executa actiuni
finale.

Exista doua metode pentru generarea unei exceptii :


- O eroare ORACLE apare si exceptia asociata este generata automat. De
exemplu, daca eroarea ORA-01403 apare când nici o coloana nu este returnata dintr-o baza de date
ca urmare a unei instructiuni SELECT, atunci PL/SQL genereaza exceptia NO_DATA_FOUND.
- Utilizatorul genereaza explicit o exceptie introducând instructiunea RAISE în
interiorul blocului. Exceptia generata poate fi fie definita de utilizator, fie predefinita.
Capturarea exceptiei Propagarea exceptiei

DECLARE DECLARE

BEGIN BEGIN
Este generata Este generata
exceptia exceptia

EXCEPTION EXCEPTION
Exceptia este Exceptia nu este
capturata capturata

END; END;

Exceptia se propaga în mediul apelant

Capturarea unei exceptii

Daca exceptia este generata în partea executabila a blocului, programul sare în rutina de
tratare corespunzatoare din sectiunea de bloc alocata exceptiilor. Daca PL/SQL trateaza cu succes
atunci aceasta nu se propaga în blocul superior. Blocul PL/SQL se termina cu succes.

Propagarea unei exceptii

Se poate trata o exceptie prin propagarea ei spre mediul apelant. Daca exceptia este generata
în portiunea executabila a blocului si nu exista nici o rutina de tratare corespondenta atunci blocul
PL/SQL se termina cu eroare.

Tipuri de exceptii

Predefinite ale ORACLE Generate implicit


Non-predefinite ale ORACLE
Definite de utilizator Generate explicit

Exceptiile se pot programa pentru a evita întreruperile din program. Exista trei tipuri :

Exceptie Descriere Modul tratarii


Eroare predefinita ORACLE Una din cele aproximativ 20 de Nu se declara. Se lasa sa fie
erori care apar cel mai des în generata implicit de ORACLE
PL/SQL
Eroare non-predefinita Oricare alta eroare standard Se declara în sectiunea
ORACLE ORACLE declarativa. Se lasa sa fie
generata implicit de ORACLE
Eroare definita de utilizator O conditie pe care utilizatorul o Se declara în sectiunea decla-
considera anormala rativa. Se genereaza explicit.
Nota : Câteva aplicatii cum ar fi Developer/2000 Forms au exceptiile lor proprii.

Capturarea exceptiilor

Sintaxa
EXCEPTION
WHEN exception1 [ OR exception2 . . .] THEN
statement1;
statement2;
. . .
[ WHEN exception3 [ OR exception4 . . .] THEN
statement1;
statement2;
. . .]
[ WHEN OTHERS THEN
statement1;
statement2;
. . .]

Se poate captura orice eroare prin includerea unei rutine corespunzatoare în cadrul sectiunii
de tratare a exceptiilor dintr-un bloc PL/SQL . Fiecare tratare consta într-o clauza WHERE , care
specifica exceptia, urmata de o secventa de instructiuni care vor fi executate când exceptia este
generata.
În cadrul sintaxei,
exception este numele standard a unei exceptii predefinite sau numele unei exceptii definite de
utilizator si declarata în cadrul sectiunii declarative
statement reprezinta una sau mai multe instructiuni ale PL/SQL sau SQL
OTHERS este o tratare de exceptii optionala si trateaza clauze care captureaza exceptiile
nespecificate

Tratarea exceptiilor WHEN OTHERS

Sectiunea de tratare a exceptiilor captureza numai acele exceptii care au fost specificate ;
orice alte exceptii nu sunt capturate decat daca se foloseste tratarea cu OTHERS. Aceasta
captureaza orice expresie care nu a fost înca tratata. Din acest motiv OTHERS este ultima tratare
definita.
Tratarea OTHERS captureaza toate expresiile care nu au fost tratate. Câteva instrumente
ORACLE au propriile exceptii predefinite care pot fi generate de utilizator pentru provocarea
anumitor evenimente în aplicatii. Aceste exceptii sunt de asemenea capturate de OTHERS.

Observaţii asupra tratării excepţiilor :

- WHEN OTHERS este ultima clauză.


- Secţiunea de tratare a excepţiilor începe cu EXCEPTION.
- .Sunt permise mai multe rutine de tratare.
- Doar o singură rutina este procesată înainte de părăsirea blocului
Observatii asupra tratarii exceptiilor :

- se începe sectiunea de tratare a exceptiilor dintr-un bloc cu EXCEPTION.


- se pot defini mai multe rutine pentru un bloc, fiecare cu actiunile ei specifice.
- când este generata o exceptie, PL/SQL proceseaza doar o rutina înainte de a parasi
blocul.
- clauza OTHERS trebuie plasata dupa toate clauzele de tratare a exceptiilor.
- pot exista mai multe clauze OTHERS.
- exceptii nu pot apare în instructiuni de asignare sau în instructiuni SQL.

Captarea erorilor predefinite ale serverului de ORACLE

- trebuie să se indice numele standard în rutina de tratare a excepţiilor.


- câteva exemple de excepţii predefinite :
- NO_DATA_FOUND
- TOO_MANY_ROWS
- INVALID_CURSOR
- ZERO_DIVIDE
- DUP_VAL_ON_INDEX

Captarea erorilor predefinite ale serverului de ORACLE

O eroare predefinita poate fi capturata prin asignarea numelui ei cu o rutina de


tratare corespunzatoare.
Pentru o lista completa a erorilor predefinite vezi PL/SQL User’s Guide and Reference,
Release 8, “Error Handling”.

NOTA : PL/SQL declara exceptiile predefinite în pachetul STANDARD.


Este un lucru extrem de util sa tratam întotdeauna exceptiile NO_DATA_FOUND si
TOO_MANY_ROWS care sunt cele mai întâlnite.

Exceptii predefinite :

Numele exceptiei No. Descriere


Exceptiei
ACCESS_INTO_NULL ORA-06530 Se încearca asignarea unei valori unui obiect
neinitializat
COLLECTION_IS_NULL ORA-06531 Se încearca aplicarea unei metode de tip
collection alta decât EXISTS unei tabele
imbricate sau varray
CURSOR_ALREADY_OPEN ORA-06511 Se încearca deschiderea unui cursor deja deschis
DUP_VAL_ON_INDEX ORA-00001 Se încearca introducerea unei valori duplicat
INVALID_CURSOR ORA-01001 Operatiune ilegala asupra unui cursor
INVALID_NUMBER ORA-01722 Esec în conversia unui string în numar
LOGIN_DENIED ORA-01017 Nume utilizator neexistent sau parola incorecta la
login
NO_DATA_FOUND ORA-01403 SELECT nu întoarce nici o data
NOT_LOGGED_ON ORA-01012 PL/SQL apeleaza o baza de date fara a fi conectat
la server
PROGRAM_ERROR ORA-06501 PL/SQL are o problema interna
ROWTYPE_MISMATCH ORA-06504 Variabila cursor gazda si cursorul PL/SQL întorc
tipuri diferite
STORAGE_ERROR ORA-06500 PL/SQL nu mai are memorie sau aceasta este
corupta
SUBSCRIPT_BEYOND_COUNT ORA-06533 Apelarea unei tabele sau varray folosind un
numar de index mai mare decât numarul
elementelor obiectului.
SUBSCRIPT_OUTSIDE_LIMIT ORA-06532 Apelarea unei tabele sau varray folosind un
numar de index care este incorect (ex : -1)
TIMEOUT_ON_RESOURCE ORA-00051 Apare time-out în timp ce ORACLE asteapta o
resursa
TOO_MANY_ROWS ORA-01422 SELECT întoarce mai mult de o coloana
VALUE_ERROR ORA-06502 Eroare de tip aritmetic, trunchiere, conversie, sau
de constrângere de marime
ZERO_DIVIDE ORA-01476 Încercare de împârtire la 0

Exceptii Predefinite

Sintaxa :

BEGIN
SELECT . . . COMMIT;
EXCEPTION
WHEN NO_DATA_FOUND THEN
statement1;
statement2;
WHEN TOO_MANY_ROWS THEN
statement1;
WHEN OTHERS THEN
statement1;
statement2;
statement3;
END;

Captarea Erorilor Non-Predefinite ale Serverului Oracle

Declarare Asociere Referinţă

Sectiunea declarativa Sectiunea de tratare


a exceptiei
Se denumeste Se programeaza Se trateaza exceptia
exceptia PRAGMA_EXCEPTION_INIT

Captarea erorilor Non-Predefinite ale Serverului Oracle

Se poate captura o eroare non-predefinita fie prin a o declara sau prin folosirea handlerului
OTHERS. Exceptia declarata este generata implicit. În PL/SQL, constrângerea (PRAGMA)
EXCEPTION_INIT comanda compilatorului sa asocieze numele unei exceptii cu un numar de
exceptie ORACLE. Acest lucru permite ca sa putem referi orice exceptie interna cu numele ei si sa
o putem trata într-un handler specific.

Nota : PRAGMA (denumita si pseudoinstructiune) este cuvântul care semnifica faptul ca


expresia este o directiva compilator, care nu este procesata cand se executa un bloc PL/SQL. Mai
mult, ea spune compilatorului PL/SQL sa interpreteze toate aparitiile din cadrul blocului a exceptiei
numite ca fiind numarul de eroare asociat de serverul ORACLE.

Erori Non-Predefinite
Captarea erorii -2292 a serverului Oracle - încălcarea unei constrângeri

DECLARE
e_products_invalid EXCEPTION; 1
PRAGMA EXCEPTION_INIT ( e_products_invalid, -2292); 2
v_message VARCHAR2(50);
BEGIN
. . .
EXCEPTION
WHEN e_products_invalid THEN
:g_message := ‘Product code specified is not valid.’; 3
. . .
END;

Captarea unei exceptii Non-predefinite a serverului Oracle

1. Se declara numele exceptiei în sectiunea declarativa.

Sintaxa :

exception EXCEPTION;

unde exception este numele exceptiei.

2. Asocierea exceptiei declarate cu numarul standard de eroare a serverului de Oracle


folosind instructiunea PRAGMA EXCEPTION_INIT.
Sintaxa :

PRAGMA EXCEPTION_INIT(exception, error_number);

unde exception este exceptia declarata anterior


error_number este numarul standard de eroare a serverului Oracle.

3. Se asociaza exceptia declarata cu rutina de tratare corespunzatoare.

Captarea exceptiilor definite de utilizator

Declarare Apelare Referinţă

Sectiunea declarativa Sectiunea executabila Sectiunea de tratare

Se numeste exceptia Se apeleaza explicit exceptia Se trateaza exceptia

Exceptiile definite de utilizator

Exemplu :

[DECLARE]
e_amount_remaining EXCEPTION;
1
. . .
BEGIN
. . .
RAISE e_amount_remaining;
2
. . .
ECXEPTION
WHEN e_amount_remaining THEN
:g_message := ‘There is still an amount in stock.’;
3
. . .
END;

Captarea exceptiilor definite de utilizator :

Se capteaza o exceptie definita de utilizator declarând exceptia si apelând-o explicit.

1. Se declara numele pentru exceptia utilizator în cadrul sectiunii declarative.

Sintaxa :
exception EXCEPTION;

unde exception este numele exceptiei.

2. Folosind instructiunea RAISE se apeleaza explicit exceptia în sectiunea executabila.

Sintaxa :

RAISE exception;

unde exception este exceptia definita anterior.

3. Se creaza o referinta la exceptia declarata în cadrul sectiunii executabile.

În exemplul de mai sus : Acest client are o ‘regula’ de afaceri care spune ca un produs nu poate fi
sters din baza de date daca mai exista inventar din acest produs în stoc. Cum nu exista nici o
constrângere care sa reglementeze acest lucru, se trateaza evenimentul explicit în cadrul aplicatiei.
Înainte de executarea unui DELETE în tabela PRODUCT, blocul interogheaza tabela
INVENTORY sa verifice daca exista stoc pentru produsul respectiv. Daca da, se apeleaza exceptia.

Funcţii pentru captarea excepţiilor

- SQLCODE returnează valoarea numerică a codului de eroare


- SQLERRM returnează mesajul asociat cu numărul erorii

Functii de captare a erorilor

Când apare o exceptie , se poate identifica codul de eroare asociat sau mesajul de eroare
folosind doua functii. În functie apoi de valoarea codului sau de mesaj se pot decide masurile
aferente care vor trebui luate.
SQLCODE întoarce numarul de eroare Oracle pentru exceptiile interne. Se poate transmite
numarul erorii functiei SQLERRM, care returneaza apoi mesajul asociat cu numarul erorii.

Functia Descriere
SQLCODE Returneaza valoarea numerica pentru codul erorii ( se poate asigna unei
variabile d etip NUMBER ).
SQLERRM Returneaza data de tip sir de caractere continând mesajul asociat cu
numarul erorii.
Exemple de valori ale SQLCODE :

Valori SQLCODE Descriere


0 Nu s-a întâlnit nici o exceptie
1 Exceptie definita de utilizator
+100 Exceptia NO_DATA_FOUND
numar negativ Alt numar de eroare al serverului Oracle

Funcţii pentru captarea excepţiilor

Exemple :

DECLARE
v_error_code NUMBER;
v_error_message VARCHAR2(255);
BEGIN
. . .
EXCEPTION
. . .
WHEN OTHERS THEN
ROLLBACK;
v_error_code := SQLCODE;
v_error_message := SQLERRM;
INSERT INTO errors VALUES (v_error_code, v_error_message);
END;
Functii de captare a exceptiilor :

Când o exceptie este captata în sectiunea WHEN OTHERS, se poate folosi un set de functii
generice pentru identificarea acestor erori.
În exemplu se prezinta asignarea valorilor SQLCODE si SQLERRRM unor variabile care ai
apoi sunt folosite în instructiuni SQL.

Mediile apelante

SQL*PLUS Afiseaza mesajul si numarul de eroare pe ecran


Procedure Builder Afiseaza mesajul si numarul de eroare pe ecran
Developer/2000 Forms Acceseaza mesajul si numarul de eroare prin pachetul de functii
ERROR_CODE si ERROR_TEXT
Precompilarea Acceseaza numarul exceptie direct prin structura de date SQLCA
aplicatiilor
Un bloc final(imbricat) Capturarea exceptiei în rutina de tratare a exceptiei în blocul final
PL/SQL (imbricat)
În loc de capturarea unei exceptii în cadrul blocului PL/SQL, se permite transmiterea
exceptie mediului apelant pentru a o trata. Fiecare mediu apelant are propriul mod de afisare si
accesare a erorilor.

Transmiterea exceptiilor

DECLARE
. . .
e_no rows exception;
e_integrity exception;
PRAGMA EXCEPTION INIT ( e_integrity ,
-2992 );
BEGIN
FOR c_record IN emp_cursor LOOP
BEGIN
SELECT . . .
Subblocurile pot trata o exceptie UPDATE . . .
sau o pot transmite blocului IF SQL %NOTFOUND THEN
final(imbricat) RAISE e_no_rows;
END IF;
EXCEPTION
WHEN e_integrity THEN . . .
WHEN e_no_rows THEN . . .
END;

END LOOP;
EXCEPTION
WHEN NO_DATA_FOUND THEN . . .
WHEN TOO_MANY_ROWS THEN . . .

Când un subbloc trateaza o exceptie, el se termina normal, si controlul se preia automat de


blocul final(imbricat) dupa expresia END a subbocului.
În orice caz, daca în PL/SQL apare o exceptie si blocul curent nu are o solutie pentru
aceasta, exceptia parcurge succesiv blocuri finale(imbricate) pâna gaseste o tratare a ei. Daca nici
unul dintre blocuri nu trateaza exceptia, apare ca rezultat o exceptie netrata în mediul curent.
Când exceptia parcurge un bloc final(imbricat), actiunile ramase de executat în acest bloc
sunt ocolite(sarite).
Un avantaj al acestui comportament este ca se pot include expresii care necesita propriile
tratari a erorilor din blocurile în care se gasesc, permitând tratarea mai general a exceptiei în blocul
final(imbricat).

RAISE_APPLICATION_ERROR

Sintaxa :
raise_application_error ( error_number,
message [ , { TRUE | FALSE } ] ) ;

- o procedura care permite sa emiti mesaje de eroare definite de utilizator din


subprogramele stocate.
- se apeleaza numai din executia(executabilul) subprogramului stocat.

Procedura RAISE_APPLICATION_ERROR se foloseste interactiv pentru comunicarea unei


exceptii predefinite prin returnarea unui cod de eroare nestandar si a unui mesaj de eroare. Cu
RAISE_APPLICATION_ERROR se pot prezenta erorile dintr-o anume aplicatie si se poate evita
returnarea unei exceptii netratate.
În cadrul sintaxei:
- error number este un specificator de numar pentru exceptia cuprinsa între
–20000 si –20999
- message este un mesaj specificat de utilizator pentru exceptie. Este un
sir de caractere de 2048 biti lumgime.
- TRUE | FALSE este un parametru Boolean optional. Daca este TRUE, atunci
eroarea se afla în lista(stiva) erorilor precedente. Daca este
FALSE, eroarea va înlocui toate erorile anterioare.
Exemplu :
. . .
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE_APPLICATION_ERROR_( -20201 ,
‘ Manager-ul nu este un angajat valid . ’ ) ;
END ;

RAISE_APPLICATION_ERROR se utilizeaza în doua locuri diferite :


- sectiunea de executie
- sectiunea exceptiei
RAISE_APPLICATION_ERROR întoarce conditiile de eroare în conformitate cu erorile
Server-ului Oracle.

Exemplu :
. . .
DELETE FROM emp
WHERE mgr = v_mgr ;
IF SQL%NOTFOUND THEN
RAISE_APPLICATION_ERROR ( -20202 , ‘ Acesta nu este un manager
valid ’ ) ;
END IF ;
. . .

Sumar :

* Tipuri de exceptii :
- erori predefinite de Server-ul Oracle
- erori nepredefinite de Server-ul Oracle
- erori definite de utilizator
* Capturarea exceptiilor
* Tratarea exceptiilor :
- capturarea exceptiilor în interiorul unui bloc PL/SQL
- propagarea exceptiei
Exercitii :

În aceste exercitii trebuie sa tratati exceptii pentru situatii specifice.

1. Scrieti un bloc PL/SQL care sa selecteze numele angajatului cu o valoare data a


salariului :
a. Daca salariul introdus returneaza mai mult de un rând, tratati exceptia cu o
exceptie tratata asemanatoare si introduceti în tabloul MESSAGES, mesajul “ Mai mult de un
angajat cu salariul < salariu > ”.
b. Daca salariul introdus nu returneaza nici un rând, tratati exceptia cu o
exceptie tratata asemanatoare si introduceti în tabloul MESSAGES, mesajul “ Nu este nici un
angajat cu salariul < salariu > ”.
c. Daca salariul introdus returneaza numai un rând, introduceti în tabloul
MESSAGES numele angajatului si valoarea salariului.
d. Tratati orice alta exceptie cu o exceptie tratata asemanatoare si introduceti
în tabloul MESSAGES, mesajul “ S-au mai produs alte erori ”.
e. Testati blocul pentru mai multe cazuri ( situatii ).

RESULTS
--------------------------------------------------------
SMITH – 800
More than one employee with a salary of 3000
No employee with a salary of 6000

2. Modificati programul pl8q3.sql adaugând o tratare de exceptie :

a. Scrieti o tratare de exceptie pentru eroarea care transmite utilizatorului ca


departamentul specificat nu exista.
b. Executati blocul PL/SQL prin introducerea unui departament care nu exista.

Please enter the departament number : 50


Please enter the departament location : HOUSTON

PL/SQL procedure successfully completed.

G_MESSAGE
-------------------------------------------------
Departament 50 is an invalid department

3. Scrieti un bloc PL/SQL care tipareste numele angajatilor care au cu 100$ mai mult sau
mai putin la salar fata de valoarea salariului introdus :

a. Daca nu este nici un angajat al carui salar sa se încadreze în acesta valoare, tipariti
un mesaj utilizatorului indicându-i acest lucru. Folositi o exceptie pentru acest caz.
b. Daca sunt unul sau mai multi angajati ale caror salarii se încadreaza în acesta
valoare, mesajul va trebui sa indice câti angajati au un salar ce se încadreaza în valoarea respectiva.
c. Tratati orice alta exceptie cu o exceptie asemanatoare, mesajul va trebui sa indice
daca au mai aparut si alte erori.
Please enter the salary : 800
PL/SQL procedure successfully completed.

G_MESSAGE
----------------------------------------------------------------------
There is 1 employee (s) with a salary between 700 and 900

Please enter the salary : 3000


PL/SQL procedure successfully completed.

G_MESSAGE
---------------------------------------------------------------------------
There are 3 employee (s) with a salary between 2900 and 3900

Please enter the salary : 6000


PL/SQL procedure successfully completed.

G_MESSAGE
-----------------------------------------------------------------
There are no employee salary between 5900 and 6100

S-ar putea să vă placă și