Kivételek kezelése Oracle PL/SQL (példák)

⚡ Okos összefoglaló

Kivételkezelés Oracle A PL/SQL rögzíti a futásidejű hibákat, amelyek megakadályozzák egy blokk végrehajtását, lehetővé téve a motor számára, hogy a vezérlést egy EXCEPTION szakaszba vigye át, ahol az előre definiált, a felhasználó által definiált és OTHERS kezelők biztonságosan válaszolnak, hibát generálnak vagy terjesztenek.

  • 🇧🇷 Futásidejű hibák: Kivétel akkor keletkezik, amikor a PL/SQL motor egy olyan utasítással találkozik, amelyet nem tud végrehajtani, például egy szám nullával való osztása.
  • 🧱 Blokk szerkezet: A kivételeket az EXCEPTION szakaszban kezeljük a WHEN záradékok segítségével, a WHEN OTHERS mindig a végére kerül.
  • ???? Előre definiált kivételek: Oracle megnevezi a STANDARD csomagban található gyakori hibákat, mint például a NO_DATA_FOUND és a ZERO_DIVIDE, amelyek közvetlenül elkaphatók.
  • 🇧🇷 Felhasználó által definiált kivételek: A programozók deklarálják a saját EXCEPTION változóikat, és explicit módon hívják meg azokat a RAISE kulcsszóval.
  • ⬆️ Szaporítás: Egy kezeletlen kivétel átkerül a körülzáró blokkhoz, és a RAISE utasítás újrajelzi azt egy szülőprogramnak.
  • 🤖 AI segítség: A mesterséges intelligencia által fejlesztett kódolóeszközök KIVÉTEL blokkokat rajzolnak, és a felülvizsgálat során megjelölik a kezeletlen hibaútvonalakat.

Kivételek kezelése Oracle PL / SQL

Mi az a kivételkezelés a PL/SQL-ben?

Kivétel történik, amikor a PL/SQL motor olyan utasítást talál, amelyet futási időben felmerülő hiba miatt nem tud végrehajtani. Ezeket a hibákat a rendszer nem észleli fordítási időben, ezért csak futási időben kell kezelni őket.

Például, ha a PL/SQL motor egy utasítást kap egy szám nullával való osztására, akkor kivételként hibát jelez. A kivételt a PL/SQL motor csak futásidőben generálja.

Egy kivétel megakadályozza a program további végrehajtását, ezért az ilyen helyzet elkerülése érdekében a hibát külön kell rögzíteni és kezelni. Ezt a folyamatot kivételkezelésnek nevezik, amelynek során a programozó kezeli a futásidőben előforduló hibát.

Kivételkezelési szintaxis

A kivételek kezelése blokkszinten történik. Amint egy kivétel történik egy blokkban, a vezérlés elhagyja a blokk végrehajtási részét, és a kivétel kezelése a blokk kivételkezelő részében történik. A kivétel kezelése után a vezérlés nem térhet vissza ugyanazon blokk végrehajtási szakaszába.

Az alábbi ábra azt mutatja, hogyan helyezkedik el a végrehajtási szakasz és a kivételkezelési szakasz egyetlen PL/SQL blokkon belül:

Egy PL/SQL blokk szerkezete végrehajtási és kivétel szakasszal

Az alábbi szintaxis elmagyarázza, hogyan lehet kivételeket elkapni és kezelni.

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;

Szintaxis magyarázata:

  • A fenti szintaxisban a kivételkezelő blokk egy sor WHEN feltételt tartalmaz a kivételek kezelésére.
  • Minden WHEN feltételt egy kivétel neve követ, amelynek futási időben kell bekövetkeznie.
  • Amikor futásidőben kivétel keletkezik, a PL/SQL motor a kivételkezelő részben keresi az adott kivételt, az első WHEN záradéktól kezdve, és szekvenciálisan haladva.
  • Ha talál egy kezelőt a felmerült kivételhez, akkor végrehajtja az adott kezelő kódot.
  • Ha egyetlen WHEN záradék sem felel meg a felmerült kivételnek, a PL/SQL motor végrehajtja a WHEN OTHERS részt, ha van ilyen. Ez a kezelő minden kivételre közös.
  • A kezelő lefutása után a vezérlés elhagyja az aktuális blokkot.
  • Futásidőben egy blokkhoz csak egy kivételkezelő hajtható végre. A futás után a motor kihagyja a fennmaradó kezelőket, és kilép az aktuális blokkból.

Jegyzet: A WHEN OTHERS függvényt mindig a szekvenciában utoljára kell helyezni. A WHEN OTHERS után írt kezelők soha nem futnak le, mivel a vezérlés a WHEN OTHERS végrehajtása után kilép a blokkból.

A kivételek típusai

Kétféle kivétel létezik a PL / SQL.

  • Előre definiált kivételek
  • Felhasználó által definiált kivételek

Előre meghatározott kivételek

Oracle előre definiált néhány gyakori kivételt. Minden előre definiált kivétel egyedi névvel és hibaszámmal rendelkezik, és mindegyik deklarálva van a STANDARD csomagban a OracleKódban ezeket az előre definiált kivételneveket közvetlenül használhatod a megfelelő hibák kezelésére. Sokuk közvetlenül a gyakori hibákra vonatkozik. SQL hibák, amikkel nap mint nap találkozol.

Az alábbiakban néhány előre definiált kivételt láthat:

kivétel hiba Code Kivétel oka
ACCESS_INTO_NULL ORA-06530 Érték hozzárendelése egy nem inicializált objektum attribútumaihoz
CASE_NOT_FOUND ORA-06592 A CASE utasításban egyik WHEN záradék sem teljesül, és nincs megadva ELSE záradék.
COLLECTION_IS_NULL ORA-06531 Gyűjtési metódusok használata (az EXISTS kivételével) vagy gyűjteményattribútumok elérése egy nem inicializált gyűjteményen
CURSOR_ALREADY_OPEN ORA-06511 Megpróbálja megnyitni a kurzor ami már nyitva van
DUP_VAL_ON_INDEX ORA-00001 Ismétlődő érték tárolása egy egyedi index által korlátozott adatbázisoszlopban
INVALID_CURSOR ORA-01001 Érvénytelen kurzorműveletek, például egy megnyitatlan kurzor bezárása
ÉRVÉNYTELEN SZÁM ORA-01722 Egy karakter számmá alakítása sikertelen volt érvénytelen numerikus karakter miatt.
NEM TALÁLHATÓ ADAT ORA-01403 Egy INTO záradékot tartalmazó SELECT utasítás nem ad vissza sorokat.
ROW_MISMATCH ORA-06504 A kurzorváltozó adattípusa nem kompatibilis a tényleges kurzor visszatérési típusával.
SUBSCRIPT_BEYOND_COUNT ORA-06533 Egy gyűjteményre való hivatkozás egy olyan indexszámmal, amely nagyobb, mint a gyűjtemény mérete
SUBSCRIPT_OUTSIDE_LIMIT ORA-06532 Gyűjteményre való hivatkozás a megengedett tartományon kívül eső indexszámmal (például -1)
TOO_MANY_ROWS ORA-01422 Egy INTO záradékkal ellátott SELECT utasítás egynél több sort ad vissza
VALUE_ERROR ORA-06502 Számtani vagy méretkorlátozási hiba (például a változó méreténél nagyobb érték hozzárendelése)
ZERO_DIVIDE ORA-01476 Szám osztása nullával

Felhasználó által meghatározott kivétel

A fenti előre definiált kivételeken kívül a programozó létrehozhat egyéni kivételeket és kezelheti azokat. Ezek az alprogram szintjén jönnek létre a deklarációs részben, és csak az adott alprogramon belül láthatók. A csomagspecifikációban definiált kivétel nyilvános kivétel, és bárhol látható, ahol a csomag elérhető.

Szintaxis: Alprogram szinten

DECLARE
<exception_name> EXCEPTION;
BEGIN
<Execution block>
EXCEPTION
WHEN <exception_name> THEN
<Handler>
END;
  • A fenti szintaxisban az „exception_name” változó EXCEPTION típusként van definiálva.
  • Ezután ugyanúgy használható, mint egy előre definiált kivétel.

Szintaxis: Csomagspecifikáció szintjén

CREATE PACKAGE <package_name>
 IS
<exception_name> EXCEPTION;
.
.
END <package_name>;
  • A fenti szintaxisban az „exception_name” változó EXCEPTION típusként van definiálva a következő csomag specifikációjában: .
  • Az adatbázisban bárhol használható, ahol a 'package_name' csomag meghívható.

PL/SQL emelés kivétel

Minden előre definiált kivétel implicit módon keletkezik, amikor a megfelelő hiba előfordul. A felhasználó által definiált kivételeket azonban explicit módon kell létrehozni a RAISE kulcsszó használatával. A RAISE kulcsszó az alább látható módon használható.

Ha a RAISE metódust önmagában használjuk egy kezelőn belül, akkor a már felmerült kivételt továbbküldi a szülő blokknak. Csak egy kivételblokkon belül használható, ahogy az alább látható.

Az alábbi képernyőképen a RAISE önmagában történő használata látható egy kivétel újbóli kiváltására a befoglaló blokkban:

Kivétel terjesztése a szülő blokkra egy egyszerű RAISE utasítással

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

Szintaxis magyarázata:

  • A fenti szintaxisban a RAISE kulcsszó a kivételkezelő blokkon belül szerepel.
  • Amikor a program a(z) „kivétel_neve” kivétellel találkozik, a kivétel kezelése és futása normál módon fejeződik be.
  • A kezelőben található RAISE kulcsszó ezután ugyanazt a kivételt továbbítja a szülőprogramnak.

Jegyzet: Amikor kivételt generálunk a szülőblokkra, a kiváltott kivételnek a szülőblokkban is láthatónak kell lennie; egyébként Oracle hibát dob.

Használhatod a RAISE kulcsszót, majd egy kivétel nevét az adott felhasználó által definiált vagy előre definiált kivétel előidézéséhez. Ez az űrlap mind a végrehajtási, mind a kivételkezelési részben használható.

Az alábbi képernyőképen a RAISE (RÁZÁS) parancsot egy kivételnév követi, amely egy adott kivételt generál.

Egy adott elnevezett kivétel felvetése a RAISE paranccsal, majd a kivétel nevével

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

Szintaxis magyarázata:

  • A fenti szintaxisban a RAISE kulcsszót a végrehajtási részben használjuk, amelyet a „kivétel_neve” kivétel követ.
  • Ez futásidőben előidézi az adott kivételt, amit aztán tovább kell kezelni vagy kiváltani.

Példa 1: Ebben a példában a következőket fogjuk látni:

  • Hogyan deklaráljunk kivételt
  • Hogyan lehet felidézni a deklarált kivételt?
  • Hogyan terjesztjük a főblokkba

Az alábbi képernyőkép a teljes blokkot mutatja, amely deklarálja a sample_exception kivételt, egy beágyazott blokkon belül aktiválja azt, és továbbadja a fő blokknak:

PL/SQL példa felhasználó által definiált kivétel deklarálására és felidézésére beágyazott blokkban

A következő képernyőképen ugyanaz a példa folytatódik, ahol a fő blokk végül rögzíti a továbbadott kivételt:

Kimenet, amely a beágyazott blokkban, majd a fő blokkban rögzített kivételt mutatja

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 Magyarázat:

  • Code 2. sor: A „sample_exception” változó deklarálása EXCEPTION típusként.
  • Code 3. sor: A nested_block eljárás deklarálása.
  • Code 6. sor: A „Beágyazott blokkon belül” utasítás kinyomtatása.
  • Code 7. sor: A „sample_exception generálása beágyazott blokkból” utasítás kinyomtatása.
  • Code 8. sor: A kivétel emelése a 'RAISE sample_exception' használatával.
  • Code 10. sor: Kivételkezelő a beágyazott blokkban található sample_exception kivételhez.
  • Code 11. sor: A „Kivételt rögzítettek a beágyazott blokkban. Feliratkozás a fő blokkra” utasítás kinyomtatása.
  • Code 12. sor: A kivétel felvetése a fő blokkra (terjesztése).
  • Code 15. sor: A „Fő blokkon belül” utasítás kinyomtatása.
  • Code 16. sor: A „Beágyazott blokk hívása” utasítás kinyomtatása.
  • Code 17. sor: A nested_block eljárás meghívása.
  • Code 19. sor: A minta_exception kivételkezelője a fő blokkban.
  • Code 20. sor: A „Kivételt rögzítettek a fő blokkban” utasítás kinyomtatása.

Fontos tudnivalók a Kivételnél

  • Egy függvényben egy kivételnek mindig vagy értéket kell visszaadnia, vagy tovább kell emelnie a kivétel hatókörét; egyébként Oracle futásidőben „A függvény érték nélkül tért vissza” hibát dob.
  • Tranzakcióvezérlő utasítások a kivételkezelő blokkon belül adható ki.
  • Az SQLERRM és az SQLCODE beépített függvények, amelyek rendre a kivételüzenetet, illetve a kivételkódot adják vissza.
  • Ha egy kivételt nem kezel a rendszer, akkor alapértelmezés szerint az adott munkamenetben lévő összes aktív tranzakció visszavonásra kerül.
  • RAISE_APPLICATION_ERROR (-) , ) használható a RAISE helyett egyéni kóddal és üzenettel ellátott hibaüzenet esetén. A hibakódnak -20000 és -20999 között kell lennie.

GYIK

A PRAGMA EXCEPTION_INIT egy felhasználó által deklarált kivételnevet egy adott kivételhez társít. Oracle hibaszám. A kötés után az ORA hibát név szerint rögzítheti egy WHEN záradékban a WHEN OTHERS használata és az SQLCODE ellenőrzése helyett.

Az SQLCODE az aktuális kivétel numerikus hibakódját adja vissza, míg az SQLERRM a szöveges üzenetét. Mindkettőt egy kivételkezelőn belül hívjuk meg, leggyakrabban a WHEN OTHERS blokkban, hogy naplózzuk vagy megjelenítsük a hiba okát.

Kerüld a WHEN OTHERS metódust, ami minden hibát csendben elnyel. Az SQLCODE és SQLERRM naplózása vagy a RAISE paranccsal történő újraindítás nélkül elrejti a hibákat. Csak a kivétel naplózására, tisztítására és terjesztésére használd.

A RAISE_APPLICATION_ERROR függvény -20000 és -20999 közötti hibaszámot és legfeljebb 2048 bájtos üzenetet fogad el. Leállítja a végrehajtást, és egyéni hibát ad vissza a hívó alkalmazásnak, így a felhasználó által definiált feltétel natívnak tűnik. Oracle hiba.

Nem ugyanabban a blokkban – amint a vezérlés az EXCEPTION szakaszba lép, az a blokk véget ér. A folytatáshoz csomagold a kockázatos utasítást egy belső BEGIN…EXCEPTION…END blokkba; miután az kezeli a hibát, a külső blokk folytatja a végrehajtást.

A hiba bármilyen futásidejű vagy fordítási probléma a kódban. Kivételt képez a PL/SQL futásidejű mechanizmus, amely futásidejű hibát jelez, és a vezérlést az EXCEPTION szakaszba helyezi át, így a program a hirtelen leállás helyett válaszolni tud.

Igen. A mesterséges intelligencia asszisztensek és a gépi tanulással foglalkozó kódellenőrök KIVÉTEL blokkokat fogalmaznak meg, javaslatot tesznek arra, hogy mely előre definiált kivételeket kell elkapni, és megjelölik a kezelőket nem tartalmazó kódútvonalakat. A fejlesztőnek továbbra is meg kell erősítenie a logikát és a hibaüzeneteket a telepítés előtt.

GitHub másodpilóta Automatikusan kiegészíti a WHEN záradékokat, a RAISE_APPLICATION_ERROR hívásokat és a teljes EXCEPTION blokkokat egy rövid, a szándékot leíró megjegyzésből. Felgyorsítja a rutin kezelőkódolást, bár a generált hibakódokat és üzeneteket ellenőrizni kell a pontosság érdekében.

Foglald össze ezt a bejegyzést a következőképpen: