Excepțiile în PL/SQL au asociate coduri de eroare și pot apare în timpul execuției unui bloc.
Dacă excepția nu este tratată, adică nu se specifică secvența de cod care trebuie executată în cazul apariției, sistemul de gestiune a bazei de date va încheia automat execuția blocul respectiv.
Sunt trei tipuri de excepții:
Sunt excepțiile cele mai uzuale care sunt interpretate și tratate automat de SGBD.
Sintaxa generală are forma:
DECLARE ... BEGIN ... EXCEPTION WHEN exception_1 [OR exception_2 ...] THEN statements_1; ... WHEN exception_k [OR exception_k+1 ...] THEN statements_k; [WHEN OTHERS THEN statements_n;] END;
Unde:
Atunci când este tratată o excepție, o singură ramură WHEN din secțiunea EXCEPTION este tratată.
Găsiți toate excepțiile la următoarele adresa: http://docs.oracle.com/database/121/ERRMG/toc.htm
Ex. 1 Să se introducă un ID de departament de la tastatură și să se afișeze la terminal numele acestuia:
Se observă că pentru idDepartament = 10 blocul funcționează normal.
Pentru idDepartament = 1 se generează o eroare ORA-01403 deoarece în tabela departments nu există acest departament.
Ex. 2 Tratarea excepție no_data_found pentru blocul precedent:
Rezultatul execuției pentru idDepartament = 1 este:
Sunt excepții pe care nu le tratează automat sistemul de gestiune dar pot fi tratate prin interceptarea codului de eroare ORA-….. și executarea unui cod de program dorit.
Sintaxa erorilor nedefinite este:
DECLARE ... exception_name EXCEPTION; PRAGMA EXCEPTION_INIT(exception_name, exception_code); ... BEGIN ... EXCEPTION ... WHEN exception_name THEN statements; ... END;
Unde:
Pentru interpretarea erorilor se folosește funcția de sistem SQLCODE, care returnează următoarele valori:
Ex. 3 În următorul exemple, se dorește să se facă o inserare în tabelul employees a unui nou angajat, dar fără să i se atribuie un employee_id, care este o coloană definită de tip not null.
Rezultatul execuției este:
Se observă că funcția SQLCODE a generat eroarea ORA-01400 cu mesajul cannot insert NULL into (“SYSTEM”.”EMPLOYEES”.”EMPLOYEE_ID”).
Codul de eroare a fost interceptat de excepția insert_angajat, tratarea acesteia fiind înfăptuită prin afișarea mesajului ‘Nu se accepta inregistrari noi in tabela employees fara employee_id’.
Motorul PL/SQL generează propriile coduri de eroare în formatul PLS-xxxxx, unde xxxxx este codul de eroare. Acest cod este diferit de codul ORA-yyyyy generat de SGBD. Un cod de eroare PL/SQL este prefațat de literele PLS și urmat de un număr unic. Cu ajutorul acestui număr se poate identifica definiția erorii folosindu-se documentația ORACLE.
Ex. 4 Se modifică exemplul 3 adăugându-se în secțiunea EXCEPTION tratarea unei excepții care nu a fost declarată.
Rezultatul execuției este:
Un program PL/SQL își încetează execuția la detectarea unei erori interne de execuție, cu excepția cazului în care sunt tratate excepțiile în alt mod de catre programator. În anumite cazuri, programul nu trebuie să-și înceteze execuția atunci când apare o eroare. Se pot include secvențe de program care să trateze erorile astfel încât procesarea să continue și după detectarea erorilor de execuție.
Sunt excepții care nu se bazează pe codurile de eroare generate de sistem și au următoarea sintaxă:
DECLARE ... exception_name EXCEPTION ... BEGIN ... IF condition THEN RAISE exception_name END IF; ... EXCEPTION ... WHEN exception_name THEN statements; ... END;
Unde:
Limbajul PL/SQL permite astfel programatorului să-și definească propriile excepții. Excepțiile definite de programator trebuie declarate în secțiunea DECLARE și trebuie generate în mod explicit cu instrucțiunea RAISE.
Declararea și interceptarea excepțiilor definite de programator impun următoarele acțiuni:
Ex. 5 Pentru angajații dintr-un departament, al cărui ID se introduce de la tastatură, care au comision null, să se genereze o excepție definită.
Rezultatul execuției pentru idDepartament = 20 este:
Excepția definită se numește lipsaComision și se tratează prin afișarea mesajului ‘lipsa comision’. Se observă că excepția nu se declanșează pe o eroare ci se verifică în secvența IF dacă comisionul angajatului este null. Dacă o excepție este generată într-un bloc, iar acesta nu are secțiunea EXCEPTION, sau nu se dorește tratarea ei în blocul în care este generată, atunci excepția poate fi tratată în blocul superior sau în blocul apelant.
Ex. 6 Să se trateze excepția lipsaComision din exercițiul 5 în blocul principal.
Rezultatul execuției pentru idDepartament = 20 este:
Se observă că execuția se oprește în momentul în care apare primul angajat fără comision. Această funcționalitate anormală apare din cauza faptului că excepția care apare în sub-bloc este tratată în blocul principal, astfel se face o ieșire forțată din buclă.
Această procedură permite transmiterea erorilor din proceduri stocate, dar poate fi folosită și în alte situații pentru transmiterea excepțiilor către procedurile apelate. Sintaxa este:
raise_application_error(error_number, message [, {TRUE | FALSE}])
Unde:
Ex. 7 Pentru un angajat care nu are comision să se definească o eroare care este tratată în momentul generării excepției și care are codul de eroare -20100.
Rezultatul execuției pentru ecuson = 100 este:
Sunt situații când un program PL/SQL poate avea o funcționalitate diferită, în privința excepțiilor, din cauza erorilor generate de catre sistemul de gestiune.
Ex. 8 Să se calculeze suma veniturilor angajaților dintr-un departament care au o anumită funcție.
Rezultatul execuției pentru idDepartament = 80 și functie = SA_REP este:
Rezultatul execuției pentru idDepartament = 10 și functie = SA_REP este:
Rezultatul execuției pentru idDepartament = 1 și functie = SA_REP este:
Dacă din prima cerere SELECT se scoate clauza GROUP BY, adică:
Rezultatul execuției blocului fără cererea group by pentru idDepartament = 80 și functie = SA_REP este:
Rezultatul execuției blocului fără cererea group by pentru idDepartament = 10 și functie = SA_REP este:
Rezultatul execuției blocului fără cererea group by pentru idDepartament = 1 și functie = SA_REP este:
Se observă că de data aceasta excepția s-a declanșat numai pentru departamentul 1, cu toate că departamentul 10 nu are niciun angajat cu funcția SA_REP. În mod normal, SELECT ar trebui să declanșeze o excepție, dar funcția SUM întoarce o valoare null, astfel încât nu se declanșează excepția predefinită no_data_found.