Undtagelseshåndtering ind Oracle PL/SQL (eksempler)

⚡ Smart opsummering

Undtagelseshåndtering i Oracle PL/SQL indfanger runtime-fejl, der forhindrer en blok i at udføres, hvilket lader motoren overføre kontrollen til en EXCEPTION-sektion, hvor foruddefinerede, brugerdefinerede og ANDRE handlere reagerer, genererer eller udbreder fejl sikkert.

  • 🇧🇷 Køretidsfejl: En undtagelse opstår, når PL/SQL-motoren møder en instruktion, den ikke kan udføre, såsom at dividere et tal med nul.
  • 🧱 Blokstruktur: Undtagelser håndteres i EXCEPTION-sektionen ved hjælp af WHEN-klausuler, hvor WHEN OTHERS altid placeres sidst.
  • 📚 Foruddefinerede undtagelser: Oracle navngiver almindelige fejl som NO_DATA_FOUND og ZERO_DIVIDE i STANDARD-pakken, klar til at blive fanget direkte.
  • 🛠️ Brugerdefinerede undtagelser: Programmører erklærer deres egne EXCEPTION-variabler og hæver dem eksplicit med RAISE-nøgleordet.
  • ⬆️ Formering: En ubehandlet undtagelse sendes til den omsluttende blok, og RAISE signalerer den igen til et overordnet program.
  • 🤖 AI assistance: AI-kodningsværktøjer udarbejder UNDTAGELSESblokke og markerer ubehandlede fejlstier under gennemgang.

Undtagelseshåndtering ind Oracle PL / SQL

Hvad er undtagelseshåndtering i PL/SQL?

En undtagelse opstår, når PL/SQL-motoren støder på en instruktion, som den ikke kan udføre på grund af en fejl, der opstår under kørsel. Disse fejl registreres ikke under kompilering og skal derfor kun håndteres under kørsel.

Hvis PL/SQL-motoren for eksempel modtager en instruktion om at dividere et tal med nul, genererer den fejlen som en undtagelse. Undtagelsen genereres kun under kørsel af PL/SQL-motoren.

En undtagelse forhindrer programmet i at køre videre, så for at undgå en sådan tilstand skal fejlen registreres og håndteres separat. Denne proces kaldes undtagelseshåndtering, hvor programmøren håndterer den fejl, der kan opstå under kørsel.

Undtagelseshåndteringssyntaks

Undtagelser håndteres på blokniveau. Når en undtagelse opstår i en blok, forlader kontrollen udførelsesdelen af ​​den blok, og undtagelsen håndteres derefter i undtagelseshåndteringsdelen af ​​blokken. Når undtagelsen er håndteret, kan kontrollen ikke vende tilbage til udførelsessektionen af ​​den samme blok.

Illustrationen nedenfor viser, hvordan udførelsessektionen og undtagelseshåndteringssektionen sidder i en enkelt PL/SQL-blok:

Struktur af en PL/SQL-blok med en udførelses- og en undtagelsessektion

Syntaksen nedenfor forklarer, hvordan man fanger og håndterer en undtagelse.

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;

Syntaks forklaring:

  • I syntaksen ovenfor indeholder undtagelseshåndteringsblokken en række WHEN-betingelser til at håndtere undtagelser.
  • Hver WHEN-betingelse efterfølges af et undtagelsesnavn, der forventes at blive genereret under kørsel.
  • Når en undtagelse opstår under kørsel, søger PL/SQL-motoren i undtagelseshåndteringsdelen efter den pågældende undtagelse, startende fra den første WHEN-klausul og sekventielt.
  • Hvis den finder en handler for den undtagelse, der blev rejst, udfører den den pågældende handlerkode.
  • Hvis ingen WHEN-klausul matcher den hævede undtagelse, udfører PL/SQL-motoren WHEN OTHERS-delen, hvis den er til stede. Denne handler er fælles for alle undtagelser.
  • Efter at handleren kører, forlader kontrollen den aktuelle blok.
  • Kun én undtagelseshandler kan udføres for en blok under kørsel. Når den kører, springer motoren de resterende handlere over og forlader den aktuelle blok.

Bemærk: WHEN OTHERS skal altid placeres sidst i sekvensen. Enhver handler skrevet efter WHEN OTHERS kører aldrig, fordi kontrollen afslutter blokken, når WHEN OTHERS er udført.

Typer af undtagelser

Der er to typer undtagelser i PL / SQL.

  • Foruddefinerede undtagelser
  • Brugerdefinerede undtagelser

Foruddefinerede undtagelser

Oracle har foruddefinerede nogle almindelige undtagelser. Hver foruddefineret undtagelse har et unikt navn og fejlnummer, og alle er deklareret i STANDARD-pakken i OracleI kode kan du bruge disse foruddefinerede undtagelsesnavne direkte til at håndtere de tilsvarende fejl. Mange af dem knyttes direkte til almindelige SQL fejl, du støder på hver dag.

Nedenfor er et par foruddefinerede undtagelser:

undtagelse Fejl Code Undtagelsesårsag
ACCESS_INTO_NULL ORA-06530 Tildeling af en værdi til attributterne for et ikke-initialiseret objekt
CASE_NOT_FOUND ORA-06592 Ingen af ​​WHEN-klausulerne i en CASE-sætning er opfyldt, og ingen ELSE-klausul er angivet
COLLECTION_IS_NULL ORA-06531 Brug af indsamlingsmetoder (undtagen EXISTS) eller adgang til samlingsattributter på en ikke-initialiseret samling
CURSOR_ALREADY_OPEN ORA-06511 Forsøger at åbne en markøren der allerede er åben
DUP_VAL_ON_INDEX ORA-00001 Lagring af en duplikatværdi i en databasekolonne, der er begrænset af et unikt indeks
INVALID_CURSOR ORA-01001 Ulovlige markørhandlinger, såsom at lukke en uåbnet markør
INVALID_NUMBER ORA-01722 Konvertering af et tegn til et tal mislykkedes på grund af et ugyldigt numerisk tegn
INGEN DATA FUNDET ORA-01403 En SELECT-sætning, der indeholder en INTO-klausul, henter ingen rækker
ROW_MISMATCH ORA-06504 Cursorvariabelens datatype er inkompatibel med den faktiske cursorreturtype
SUBSCRIPT_BEYOND_COUNT ORA-06533 Henvisning til en samling med et indeksnummer, der er større end samlingens størrelse
SUBSCRIPT_OUTSIDE_LIMIT ORA-06532 Henvisning til en samling med et indeksnummer uden for det lovlige interval (for eksempel -1)
TOO_MANY_ROWS ORA-01422 En SELECT-sætning med en INTO-klausul returnerer mere end én række
VALUE_ERROR ORA-06502 En aritmetisk fejl eller en størrelsesbegrænsningsfejl (for eksempel tildeling af en værdi, der er større end variablen størrelse)
ZERO_DIVIDE ORA-01476 At dividere et tal med nul

Brugerdefineret undtagelse

Udover de foruddefinerede undtagelser ovenfor kan en programmør oprette brugerdefinerede undtagelser og håndtere dem. De oprettes på underprogramniveau i deklarationsdelen og er kun synlige i det pågældende underprogram. En undtagelse defineret i en pakkespecifikation er en offentlig undtagelse og er synlig, uanset hvor pakken kan tilgås.

Syntaks: På underprogramniveau

DECLARE
<exception_name> EXCEPTION;
BEGIN
<Execution block>
EXCEPTION
WHEN <exception_name> THEN
<Handler>
END;
  • I syntaksen ovenfor er variablen 'exception_name' defineret som EXCEPTION-typen.
  • Den kan derefter bruges på samme måde som en foruddefineret undtagelse.

Syntaks: På pakkespecifikationsniveau

CREATE PACKAGE <package_name>
 IS
<exception_name> EXCEPTION;
.
.
END <package_name>;
  • I ovenstående syntaks er variablen 'exception_name' defineret som EXCEPTION-typen i pakkespecifikationen for .
  • Den kan bruges på tværs af databasen, hvor som helst pakken 'pakkenavn' kan kaldes.

PL/SQL Raise-undtagelse

Alle foruddefinerede undtagelser genereres implicit, når den tilsvarende fejl opstår. Brugerdefinerede undtagelser skal dog genereres eksplicit ved hjælp af nøgleordet RAISE. RAISE kan bruges på de måder, der er vist nedenfor.

Hvis RAISE bruges alene i en handler, spreder den den allerede hævede undtagelse til den overordnede blok. Den kan kun bruges i en undtagelsesblok, som vist nedenfor.

Skærmbilledet nedenfor viser RAISE brugt alene til at genoprette en undtagelse fra den omsluttende blok:

Udbredelse af en undtagelse til den overordnede blok med en bar RAISE

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

Syntaks forklaring:

  • I syntaksen ovenfor bruges nøgleordet RAISE inde i undtagelseshåndteringsblokken.
  • Når programmet støder på undtagelsen 'exception_name', håndteres undtagelsen og fuldføres normalt.
  • Nøgleordet RAISE i handleren udbreder derefter den samme undtagelse til det overordnede program.

Bemærk: Når der oprettes en undtagelse til den overordnede blok, skal den oprettede undtagelse også være synlig i den overordnede blok; ellers Oracle kaster en fejl.

Du kan også bruge nøgleordet RAISE efterfulgt af et undtagelsesnavn til at aktivere den specifikke brugerdefinerede eller foruddefinerede undtagelse. Denne formular kan bruges i både udførelsesdelen og undtagelseshåndteringsdelen.

Skærmbilledet nedenfor viser RAISE efterfulgt af et undtagelsesnavn for at oprette en specifik undtagelse:

Oprettelse af en specifik navngivet undtagelse med RAISE efterfulgt af undtagelsesnavnet

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

Syntaks forklaring:

  • I syntaksen ovenfor bruges nøgleordet RAISE i udførelsesdelen, efterfulgt af undtagelsen 'exception_name'.
  • Dette forårsager den pågældende undtagelse under kørsel, og den skal derefter håndteres eller forårsages yderligere.

Eksempel 1: I dette eksempel vil vi se:

  • Sådan deklarerer du en undtagelse
  • Sådan hæver du den deklarerede undtagelse
  • Sådan udbredes det til hovedblokken

Skærmbilledet nedenfor viser den komplette blok, der erklærer sample_exception, hæver den inde i en indlejret blok og overfører den til hovedblokken:

PL/SQL-eksempel på deklarering og opkald af en brugerdefineret undtagelse i en indlejret blok

Følgende skærmbillede viser det samme eksempel fortsat, hvor hovedblokken endelig indfanger den udbredte undtagelse:

Outputtet viser den undtagelse, der først blev registreret i den indbyggede blok og derefter i hovedblokken

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 Forklaring:

  • Code linje 2: Deklarering af variablen 'sample_exception' som en EXCEPTION-type.
  • Code linje 3: Deklarering af proceduren nested_block.
  • Code linje 6: Udskriver sætningen "Inden for indlejret blok".
  • Code linje 7: Udskriver sætningen “Opretter sample_exception fra indlejret blok”.
  • Code linje 8: Hæve undtagelsen ved hjælp af 'RAISE sample_exception'.
  • Code linje 10: Undtagelseshåndterer for undtagelsen sample_exception i den indbyggede blok.
  • Code linje 11: Udskriver sætningen "Undtagelse fanget i indlejret blok. Ophævelse til hovedblok".
  • Code linje 12: Hæver undtagelsen til hovedblokken (udbreder den).
  • Code linje 15: Udskriver udsagnet "Inden for hovedblokken".
  • Code linje 16: Udskrivning af sætningen "Calling nested block".
  • Code linje 17: Kald af nested_block-proceduren.
  • Code linje 19: Undtagelsesbehandler for sample_exception i hovedblokken.
  • Code linje 20: Udskriver sætningen "Undtagelse registreret i hovedblok".

Vigtige punkter at bemærke i Undtagelse

  • I en funktion skal en undtagelse altid enten returnere en værdi eller hæve undtagelsen yderligere; ellers Oracle kaster fejlen 'Funktion returneret uden værdi' under kørsel.
  • Transaktionskontrolerklæringer kan udstedes inden for undtagelseshåndteringsblokken.
  • SQLERRM og SQLCODE er indbyggede funktioner, der returnerer henholdsvis undtagelsesmeddelelsen og undtagelseskoden.
  • Hvis en undtagelse ikke håndteres, rulles alle aktive transaktioner i den pågældende session som standard tilbage.
  • RAISE_APPLICATION_FEJL (- , ) kan bruges i stedet for RAISE til at give en fejlmelding med en brugerdefineret kode og meddelelse. Fejlkoden skal være mellem -20000 og -20999.

Ofte Stillede Spørgsmål

PRAGMA EXCEPTION_INIT knytter et brugerdeklareret undtagelsesnavn til et specifikt Oracle fejlnummer. Efter binding kan du fange ORA-fejlen efter navn i en WHEN-klausul i stedet for at bruge WHEN OTHERS og kontrollere SQLCODE.

SQLCODE returnerer den numeriske fejlkode for den aktuelle undtagelse, mens SQLERRM returnerer sin tekstmeddelelse. Begge kaldes i en undtagelseshandler, oftest WHEN OTHERS-blokken, for at logge eller vise, hvad der gik galt.

Undgå en WHEN OTHERS, der sluger enhver fejl lydløst. Uden at logge SQLCODE og SQLERRM eller reraise med RAISE skjuler den fejl. Brug den kun til at logge, rydde op i og derefter udbrede undtagelsen.

RAISE_APPLICATION_ERROR accepterer et fejlnummer mellem -20000 og -20999 og en besked på op til 2048 bytes. Den stopper udførelsen og returnerer en brugerdefineret fejl til den kaldende applikation, hvilket får en brugerdefineret betingelse til at ligne en native. Oracle fejl.

Ikke i den samme blok — når kontrollen flyttes til EXCEPTION-sektionen, slutter den blok. For at fortsætte skal du pakke den risikable sætning ind i en indre BEGIN…EXCEPTION…END-blok; efter at den har håndteret fejlen, fortsætter den ydre blok med at udføre.

En fejl er ethvert kørsels- eller kompileringsproblem i koden. En undtagelse er PL/SQL-kørselsmekanismen, der repræsenterer en kørselsfejl og overfører kontrollen til EXCEPTION-sektionen, så programmet kan reagere i stedet for at afslutte brat.

Ja. AI-assistenter og maskinlæringskodegranskere udarbejder UNDTAGELSESblokke, foreslår hvilke foruddefinerede undtagelser der skal fanges, og markerer kodestier, der mangler handlere. En udvikler bør stadig bekræfte logikken og fejlmeddelelserne før implementering.

GitHub Copilot autofuldfører WHEN-klausuler, RAISE_APPLICATION_ERROR-kald og komplette EXCEPTION-blokke fra en kort kommentar, der beskriver intentionen. Det fremskynder rutinemæssig handlerkodning, selvom genererede fejlkoder og meddelelser skal gennemgås for nøjagtighed.

Opsummer dette indlæg med: