Tratarea excepțiilor în Oracle PL/SQL (Exemple)

⚡ Rezumat inteligent

Tratarea excepțiilor în Oracle PL/SQL capturează erorile de execuție care opresc execuția unui bloc, permițând motorului să transfere controlul către o secțiune EXCEPTION unde rutine predefinite, definite de utilizator și OTHERS răspund, generează sau propagă erori în siguranță.

  • ⚙️ Erori de execuție: O excepție apare atunci când motorul PL/SQL întâlnește o instrucțiune pe care nu o poate executa, cum ar fi împărțirea unui număr la zero.
  • 🧱 Structura blocurilor: Excepțiile sunt tratate în secțiunea EXCEPTION folosind clauzele WHEN, WHEN OTHERS plasând întotdeauna ultima.
  • 📚 Excepții predefinite: Oracle numește erori comune precum NO_DATA_FOUND și ZERO_DIVIDE în pachetul STANDARD, gata de detectare directă.
  • 🛠️ Excepții definite de utilizator: Programatorii declară propriile variabile EXCEPTION și le generează explicit cu ajutorul cuvântului cheie RAISE.
  • ⬆️ Propagare: O excepție netratată trece la blocul încapsulant, iar RAISE o resemnalează unui program părinte.
  • 🤖 Asistență AI: Instrumentele de codare AI redactează blocuri EXCEPȚII și semnalează căile de eroare netratate în timpul revizuirii.

Tratarea excepțiilor în Oracle PL / SQL

Ce este gestionarea excepțiilor în PL/SQL?

O excepție apare atunci când motorul PL/SQL întâlnește o instrucțiune pe care nu o poate executa din cauza unei erori care apare la momentul execuției. Aceste erori nu sunt detectate la momentul compilării și, prin urmare, trebuie gestionate doar la momentul execuției.

De exemplu, dacă motorul PL/SQL primește o instrucțiune de împărțire a unui număr la zero, acesta generează eroarea ca excepție. Excepția este generată doar în timpul execuției de către motorul PL/SQL.

O excepție oprește executarea ulterioară a programului, așa că, pentru a evita o astfel de condiție, eroarea trebuie capturată și tratată separat. Acest proces se numește tratarea excepțiilor, în care programatorul gestionează eroarea care poate apărea în timpul execuției.

Sintaxa de gestionare a excepțiilor

Excepțiile sunt gestionate la nivel de bloc. Odată ce apare o excepție într-un bloc, controlul părăsește partea de execuție a acelui bloc, iar excepția este apoi gestionată în partea de gestionare a excepțiilor a blocului. După ce excepția este gestionată, controlul nu se poate întoarce la secțiunea de execuție a aceluiași bloc.

Ilustrația de mai jos arată cum secțiunea de execuție și secțiunea de gestionare a excepțiilor se află într-un singur bloc PL/SQL:

Structura unui bloc PL/SQL cu o secțiune de execuție și una de excepții

Sintaxa de mai jos explică cum se prinde și se gestionează o excepție.

BEGIN
<execution block>
.
.
EXCEPTION
WHEN <exceptionl_name>
THEN
  <Exception handling code for the “exception 1 _name’' >
WHEN OTHERS
THEN
  <Default exception handling code for all exceptions >
END;

Explicația sintaxei:

  • În sintaxa de mai sus, blocul de tratare a excepțiilor conține o serie de condiții WHEN pentru a gestiona excepțiile.
  • Fiecare condiție WHEN este urmată de un nume de excepție care se așteaptă să fie generată la momentul execuției.
  • Când o excepție este generată în timpul execuției, motorul PL/SQL caută în partea de tratare a excepțiilor acea excepție specifică, începând de la prima clauză WHEN și continuând secvențial.
  • Dacă găsește un handler pentru excepția ridicată, execută codul respectiv.
  • Dacă nicio clauză WHEN nu corespunde excepției generate, motorul PL/SQL execută partea WHEN OTHERS, dacă este prezentă. Acest handler este comun tuturor excepțiilor.
  • După ce handler-ul rulează, controlul părăsește blocul curent.
  • Doar un singur handler de excepții poate fi executat pentru un bloc în timpul execuției. După ce rulează, motorul sare peste handlerele rămase și părăsește blocul curent.

Notă: Funcția WHEN OTHERS ar trebui plasată întotdeauna ultima în secvență. Orice handler scris după WHEN OTHERS nu rulează niciodată, deoarece controlul părăsește blocul odată ce funcția WHEN OTHERS a fost executată.

Tipuri de excepție

Există două tipuri de excepții în PL / SQL.

  • Excepții predefinite
  • Excepții definite de utilizator

Excepții predefinite

Oracle are predefinite câteva excepții comune. Fiecare excepție predefinită are un nume unic și un număr de eroare, iar toate sunt declarate în pachetul STANDARD din OracleÎn cod, puteți utiliza aceste nume de excepții predefinite direct pentru a gestiona erorile corespunzătoare. Multe dintre ele se mapează direct la erori comune SQL greșeli pe care le întâlnești zi de zi.

Mai jos sunt câteva excepții predefinite:

Excepție Eroare Code Motivul excepției
ACCESS_INTO_NULL ORA-06530 Atribuirea unei valori atributelor unui obiect neinițializat
CASE_NOT_FOUND ORA-06592 Niciuna dintre clauzele WHEN dintr-o instrucțiune CASE nu este satisfăcută și nu este specificată nicio clauză ELSE.
COLLECTION_IS_NULL ORA-06531 Utilizarea metodelor de colecție (cu excepția EXISTS) sau accesarea atributelor colecției pe o colecție neinițializată
CURSOR_DEJA_DESCHIS ORA-06511 Încercarea de a deschide a cursor care este deja deschis
DUP_VAL_ON_INDEX ORA-00001 Stocarea unei valori duplicate într-o coloană a bazei de date care este constrânsă de un index unic
INVALID_CURSOR ORA-01001 Operațiuni ilegale cu cursorul, cum ar fi închiderea unui cursor nedeschis
NUMAR INVALID ORA-01722 Conversia unui caracter într-un număr a eșuat din cauza unui caracter numeric nevalid
NU S-AU GASIT DATE ORA-01403 O instrucțiune SELECT care conține o clauză INTO nu preia rânduri
ROW_MISMATCH ORA-06504 Tipul de date al variabilei cursor este incompatibil cu tipul de date returnat de cursor.
SUBSCRIPT_BEYOND_COUNT ORA-06533 Referirea la o colecție printr-un număr de index mai mare decât dimensiunea colecției
SUBSCRIPT_OUTSIDE_LIMIT ORA-06532 Referirea la o colecție printr-un număr de index în afara intervalului legal (de exemplu, -1)
TOO_MANY_ROWS ORA-01422 O instrucțiune SELECT cu o clauză INTO returnează mai mult de un rând
VALUE_ERROR ORA-06502 O eroare aritmetică sau de constrângere de dimensiune (de exemplu, atribuirea unei valori mai mari decât variabila size)
ZERO_DIVIDE ORA-01476 Împărțirea unui număr la zero

Excepție definită de utilizator

Pe lângă excepțiile predefinite de mai sus, un programator poate crea excepții personalizate și le poate gestiona. Acestea sunt create la nivel de subprogram în partea de declarație și sunt vizibile numai în interiorul subprogramului respectiv. O excepție definită într-o specificație de pachet este o excepție publică și este vizibilă oriunde poate fi accesat pachetul.

Sintaxă: La nivel de subprogram

DECLARE
<exception_name> EXCEPTION;
BEGIN
<Execution block>
EXCEPTION
WHEN <exception_name> THEN
<Handler>
END;
  • În sintaxa de mai sus, variabila „name_excepție” este definită ca fiind de tipul EXCEPȚIE.
  • Apoi poate fi utilizată în același mod ca o excepție predefinită.

Sintaxă: La nivel de specificație a pachetului

CREATE PACKAGE <package_name>
 IS
<exception_name> EXCEPTION;
.
.
END <package_name>;
  • În sintaxa de mai sus, variabila „nume_excepție” este definită ca tipul EXCEPȚIE în specificația pachetului .
  • Poate fi utilizat în baza de date oriunde poate fi apelat pachetul „nume_pachet”.

PL/SQL ridică excepție

Toate excepțiile predefinite sunt generate implicit ori de câte ori apare eroarea corespunzătoare. Excepțiile definite de utilizator, însă, trebuie generate explicit folosind cuvântul cheie RAISE. RAISE poate fi utilizat în modurile prezentate mai jos.

Dacă RAISE este utilizată independent în interiorul unui handler, aceasta propagă excepția deja generată către blocul părinte. Poate fi utilizată doar în interiorul unui bloc de excepții, așa cum se arată mai jos.

Captura de ecran de mai jos arată RAISE folosită singură pentru a re-raisi o excepție la blocul inclus:

Propagarea unei excepții la blocul părinte cu un RAISE simplu

CREATE [ PROCEDURE | FUNCTION ]
 AS
BEGIN
<Execution block>
EXCEPTION
WHEN <exception_name> THEN
             <Handler>
RAISE;
END;

Explicația sintaxei:

  • În sintaxa de mai sus, cuvântul cheie RAISE este utilizat în interiorul blocului de tratare a excepțiilor.
  • Ori de câte ori programul întâlnește excepția „nume_excepție”, excepția este gestionată și se finalizează normal.
  • Cuvântul cheie RAISE din handler propagă apoi aceeași excepție către programul părinte.

Notă: Când se ridică o excepție la blocul părinte, excepția ridicată trebuie să fie vizibilă și în blocul părinte; altfel Oracle aruncă o eroare.

De asemenea, puteți utiliza cuvântul cheie RAISE urmat de un nume de excepție pentru a genera acea excepție definită de utilizator sau predefinită. Acest formular poate fi utilizat atât în ​​partea de execuție, cât și în partea de gestionare a excepțiilor.

Captura de ecran de mai jos arată RAISE urmată de un nume de excepție pentru a genera o anumită excepție:

Dezvoltarea unei excepții specifice cu RAISE urmată de numele excepției

CREATE [ PROCEDURE | FUNCTION ]
AS
BEGIN
<Execution block>
RAISE <exception_name>
EXCEPTION
WHEN <exception_name> THEN
<Handler>
END;

Explicația sintaxei:

  • În sintaxa de mai sus, cuvântul cheie RAISE este utilizat în partea de execuție, urmat de excepția „name_excepție”.
  • Aceasta ridică acea excepție particulară în timpul execuției și apoi trebuie gestionată sau ridicată în continuare.

Exemplu 1: În acest exemplu, vom vedea:

  • Cum se declară o excepție
  • Cum se ridică excepția declarată
  • Cum să-l propagă în blocul principal

Captura de ecran de mai jos prezintă blocul complet care declară excepția sample_exception, o generează în interiorul unui bloc imbricat și o propagă în blocul principal:

Exemplu PL/SQL de declarare și ridicare a unei excepții definite de utilizator într-un bloc imbricat

Următoarea captură de ecran prezintă același exemplu în continuare, unde blocul principal capturează în final excepția propagată:

Rezultatul arată excepția capturată mai întâi în blocul imbricat și apoi în blocul principal

DECLARE
Sample_exception EXCEPTION;
PROCEDURE nested_block
IS
BEGIN
Dbms_output.put_line('Inside nested block');
Dbms_output.put_line('Raising sample_exception from nested block');
RAISE sample_exception;
EXCEPTION
WHEN sample_exception THEN
Dbms_output.put_line ('Exception captured in nested block. Raising to main block');
RAISE;
END;
BEGIN
Dbms_output.put_line('Inside main block');
Dbms_output.put_line('Calling nested block');
Nested_block;
EXCEPTION
WHEN sample_exception THEN
Dbms_output.put_line ('Exception captured in main block');
END;
/

Code Explicaţie:

  • Code linia 2: Declararea variabilei „sample_exception” ca tip EXCEPȚIE.
  • Code linia 3: Declararea procedurii nested_block.
  • Code linia 6: Afișarea instrucțiunii „În interiorul unui bloc imbricat”.
  • Code linia 7: Afișarea instrucțiunii „Găsirea excepției_exemplarului dintr-un bloc imbricat”.
  • Code linia 8: Ridicarea excepției folosind „RAISE sample_exception”.
  • Code linia 10: Tratament de excepții pentru excepția sample_exception din blocul imbricat.
  • Code linia 11: Afișarea instrucțiunii „Excepție capturată în blocul imbricat. Se ridică la blocul principal”.
  • Code linia 12: Ridicarea excepției la blocul principal (propagarea acesteia).
  • Code linia 15: Afișarea instrucțiunii „În interiorul blocului principal”.
  • Code linia 16: Tipărirea instrucțiunii „Apelarea blocului imbricat”.
  • Code linia 17: Apelarea procedurii nested_block.
  • Code linia 19: Managerul de excepții pentru sample_exception în blocul principal.
  • Code linia 20: Afișarea instrucțiunii „Excepție capturată în blocul principal”.

Puncte importante de remarcat în Excepție

  • Într-o funcție, o excepție ar trebui întotdeauna fie să returneze o valoare, fie să ridice excepția în continuare; altfel Oracle generează o eroare de tip „Funcție returnată fără valoare” la momentul execuției.
  • Declarații de control al tranzacțiilor poate fi emisă în interiorul blocului de tratare a excepțiilor.
  • SQLERRM și SQLCODE sunt funcții încorporate care returnează mesajul de excepție, respectiv codul de excepție.
  • Dacă o excepție nu este gestionată, atunci, în mod implicit, toate tranzacțiile active din sesiunea respectivă sunt anulate.
  • RAISE_APPLICATION_ERROR (- , ) poate fi folosit în loc de RAISE pentru a genera o eroare cu un cod și un mesaj personalizate. Codul de eroare trebuie să fie între -20000 și -20999.

Întrebări frecvente

PRAGMA EXCEPTION_INIT asociază un nume de excepție declarat de utilizator cu un anumit Oracle numărul erorii. După legare, puteți capta acea eroare ORA după nume într-o clauză WHEN în loc să utilizați WHEN OTHERS și să verificați SQLCODE.

SQLCODE returnează codul de eroare numeric al excepției curente, în timp ce SQLERRM returnează mesajul text. Ambele sunt apelate în interiorul unui handler de tratare a excepțiilor, cel mai adesea blocul WHEN OTHERS, pentru a înregistra sau afișa ce a mers greșit.

Evitați o excepție WHEN OTHERS care preia fiecare eroare în tăcere. Fără a înregistra în jurnal SQLCODE și SQLERRM sau a o re-raisi cu RAISE, aceasta ascunde erorile. Folosiți-o doar pentru a înregistra, curăța și apoi propaga excepția.

RAISE_APPLICATION_ERROR acceptă un număr de eroare între -20000 și -20999 și un mesaj de până la 2048 de octeți. Oprește execuția și returnează o eroare personalizată aplicației apelante, făcând ca o condiție definită de utilizator să arate ca o condiție nativă. Oracle eroare.

Nu în același bloc — odată ce controlul se mută în secțiunea EXCEPTION, blocul respectiv se termină. Pentru a continua, încadrați instrucțiunea riscantă într-un bloc intern BEGIN…EXCEPTION…END; după ce gestionează eroarea, blocul extern continuă să se execute.

O eroare este orice problemă de execuție sau de compilare din cod. O excepție este mecanismul de execuție PL/SQL care reprezintă o eroare de execuție, transferând controlul către secțiunea EXCEPTION, astfel încât programul să poată răspunde în loc să se termine brusc.

Da. Asistenții inteligenți artificiali și revizorii de cod pentru învățarea automată redactează blocuri EXCEPȚII, sugerează ce excepții predefinite să fie detectate și semnalează căile de cod cărora le lipsesc handler-uri. Un dezvoltator ar trebui să confirme totuși logica și mesajele de eroare înainte de implementare.

Copilotul GitHub completează automat clauzele WHEN, apelurile RAISE_APPLICATION_ERROR și blocurile EXCEPTION complete dintr-un comentariu scurt care descrie intenția. Accelerează codarea de rutină a handlerului, deși codurile de eroare și mesajele generate necesită verificare pentru acuratețe.

Rezumați această postare cu: