Laboratorul 03 - PL/SQL Tratarea excepțiilor

Conținut

  • Excepții predefinite
  • Excepții nedefinite
  • Excepții definite

Tratarea excepțiilor

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:

  • Predefinite = sunt excepții tratate automat de către sistemul de gestiune;
  • Nedefinite = sunt excepții tratate de către sistemul de gestiune, au coduri de eroare tip ORA-…. Aceste erori pot fi interceptate și tratate de programator daca li se atașează un nume;
  • Definite = sunt excepții definite și tratate de o secvență de program specificată de programator.

Excepții predefinite

Sunt excepțiile cele mai uzuale care sunt interpretate și tratate automat de SGBD.

Interpretarea excepțiilor se realizează în secțiunea EXCEPTION.

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:

  • exception_i reprezintă numele excepției
  • statements_i reprezintă secvența de instrucțiuni care tratează excepția.

Clauza WHEN OTHERS se specifică întotdeauna ultima, pentru ca ramura să preia toate excepțiile netratate.

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.

Pentru a evita o astfel de situație trebuie să fie tratată excepția no_data_found.

Ex. 2 Tratarea excepție no_data_found pentru blocul precedent:

Rezultatul execuției pentru idDepartament = 1 este:

Excepții nedefinite

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:

  • exception_name reprezintă numele excepției
  • error_code reprezintă codul de eroare pentru care se declanșează excepția
  • statements reprezintă secvența de instrucțiuni care tratează excepția

În cazul acestor excepții trebuie asociat codul de eroare cu numele excepției în secțiunea DECLARE a blocului prin cuvintele cheie rezervate PRAGMA EXCEPTION_INIT.

Pentru interpretarea erorilor se folosește funcția de sistem SQLCODE, care returnează următoarele valori:

  • 0 – dacă nu s-a întâlnit o eroare
  • 1 – excepție definită de utilizator
  • +100 – excepția NO_DATA_FOUND
  • Valori negative – pentru alte erori ale bazei

Mesajul erorii se afișează cu funcția SQLERRM.

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.

Excepții definite

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:

  • exception_name – reprezintă numele atribuit excepției
  • RAISE – reprezintă instrucțiunea de interpretare și generare a excepției;
  • statements – reprezintă secvența de instrucțiuni care tratează excepția;

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:

  • Declararea excepției în secțiunea DECLARE.
  • Utilizarea instrucțiunii RAISE pentru generarea excepției în secțiunea de execuție a blocului: RAISE exception_name
  • Tratarea excepției în secțiunea EXCEPTION.

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.

Trebuie tratate cu atenție excepțiile deoarece funcționalitatea programului se poate schimba în funcție de locul unde este tratată o excepție.

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

Pentru a intercepta erorile de sistem există procedura stocată RAISE_APPLICATION_ERROR.

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:

  • error_number reprezintă codul ORA atribuit excepției (diferit de cele alocatei bazei de date, cu valori între -20000 și -20999);
  • message este mesajul aferent excepției cu lungimea maximă de 2048 caractere;
  • TRUE|FALSE este opțional și permite adăugarea mesajului la stiva de mesaje (pentru TRUE) alocată excepției (se adună mesajele de la mai multe niveluri. Implicit opțiunea este FALSE și în stivă rămâne mesajul singular pentru eroare, fără a mai prelua mesaje de la alte niveluri.

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.

Anomalia apare datorită modului de funcționare a cererii SELECT, din cauza aceasta, trebuie să se construiacă cu mare atenție o cerere DML.

Bibliografie

bd2/laboratoare/03.txt · Last modified: 2020/10/22 13:21 by ciprian.truica
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0