Zpracování výjimek Oracle PL/SQL (příklady)

⚡ Chytré shrnutí

Zpracování výjimek v Oracle PL/SQL zachycuje chyby za běhu, které zastaví spuštění bloku, a umožňuje tak enginu předat řízení do sekce EXCEPTION, kde předdefinované, uživatelsky definované a OTHERS obslužné rutiny bezpečně reagují, vyvolávají nebo šíří chyby.

  • ⚙️ Chyby za běhu: Výjimka nastane, když engine PL/SQL narazí na instrukci, kterou nemůže provést, například dělení čísla nulou.
  • 🧱 Struktura bloku: Výjimky se ošetřují v sekci EXCEPTION pomocí klauzulí WHEN, přičemž WHEN OTHERS je vždy umístěna jako poslední.
  • ???? Předdefinované výjimky: Oracle pojmenovává běžné chyby jako NO_DATA_FOUND a ZERO_DIVIDE v balíčku STANDARD, připravené k přímému zachycení.
  • 🛠️ Uživatelem definované výjimky: Programátoři deklarují své vlastní proměnné EXCEPTION a explicitně je vyvolávají klíčovým slovem RAISE.
  • ⬆️ Propagace: Neošetřená výjimka se předává do ohraničujícího bloku a RAISE ji znovu signalizuje nadřazenému programu.
  • 🤖 Asistence AI: Nástroje pro kódování s umělou inteligencí navrhují bloky VÝJIMEK a během kontroly označují neošetřené cesty k chybám.

Zpracování výjimek Oracle PL / SQL

Co je zpracování výjimek v PL/SQL?

K výjimce dochází, když engine PL/SQL narazí na instrukci, kterou nemůže provést kvůli chybě, která se vyskytne za běhu. Tyto chyby nejsou detekovány za běhu kompilace, a proto musí být ošetřeny pouze za běhu.

Například pokud PL/SQL engine obdrží instrukci k dělení čísla nulou, vyvolá chybu jako výjimku. Výjimka je vyvolána PL/SQL enginem pouze za běhu.

Výjimka zastaví další provádění programu, takže aby se takové situaci předešlo, je třeba chybu zachytit a ošetřit samostatně. Tento proces se nazývá ošetření výjimek, při kterém programátor ošetřuje chybu, která může nastat za běhu.

Syntaxe zpracování výjimek

Výjimky se ošetřují na úrovni bloku. Jakmile se v bloku vyskytne výjimka, řízení opouští prováděcí část daného bloku a výjimka se poté ošetřuje v části bloku určené pro ošetření výjimek. Po ošetření výjimky se řízení nemůže vrátit do prováděcí sekce stejného bloku.

Níže uvedený obrázek ukazuje, jak se sekce pro provádění a sekce pro ošetření výjimek nacházejí v jednom bloku PL/SQL:

Struktura bloku PL/SQL se sekcí pro provádění a výjimky

Níže uvedená syntaxe vysvětluje, jak zachytit a ošetřit výjimku.

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;

Vysvětlení syntaxe:

  • Ve výše uvedené syntaxi blok pro ošetření výjimek obsahuje řadu podmínek WHEN pro ošetření výjimek.
  • Za každou podmínkou WHEN následuje název výjimky, která by měla být vyvolána za běhu.
  • Když je za běhu vyvolána výjimka, engine PL/SQL prohledá část pro ošetření výjimek, počínaje první klauzulí WHEN a postupně dále.
  • Pokud najde obslužnou rutinu pro vyvolanou výjimku, provede daný kód obslužné rutiny.
  • Pokud se žádná klauzule WHEN neshoduje s vyvolanou výjimkou, engine PL/SQL provede část WHEN OTHERS, pokud je přítomna. Tento obslužný program je společný pro všechny výjimky.
  • Po spuštění obslužné rutiny řízení opustí aktuální blok.
  • Za běhu programu se může pro blok spustit pouze jeden obslužný program výjimek. Po jeho spuštění programový engine přeskočí zbývající obslužné programy a opustí aktuální blok.

Poznámka: Funkce WHEN OTHERS by měla být vždy umístěna jako poslední v sekvenci. Žádná obslužná rutina napsaná po funkci WHEN OTHERS se nikdy nespustí, protože po provedení funkce WHEN OTHERS řízení opustí blok.

Typy výjimek

Existují dva typy výjimek v PL / SQL.

  • Předdefinované výjimky
  • Uživatelsky definované výjimky

Předdefinované výjimky

Oracle má předdefinované některé běžné výjimky. Každá předdefinovaná výjimka má jedinečný název a číslo chyby a všechny jsou deklarovány v balíčku STANDARD v OracleV kódu můžete tyto předdefinované názvy výjimek použít přímo k ošetření odpovídajících chyb. Mnoho z nich se mapuje přímo na běžné SQL chyby, se kterými se setkáváte každý den.

Níže je uvedeno několik předdefinovaných výjimek:

Výjimka Chyba Code Důvod výjimky
ACCESS_INTO_NULL ORA-06530 Přiřazení hodnoty atributům neinicializovaného objektu
CASE_NOT_FOUND ORA-06592 Žádná z klauzulí WHEN v příkazu CASE není splněna a není zadána žádná klauzule ELSE.
COLLECTION_IS_NULL ORA-06531 Používání metod kolekce (kromě EXISTS) nebo přístup k atributům kolekce u neinicializované kolekce
CURSOR_ALREADY_OPEN ORA-06511 Pokus o otevření a kurzor která je již otevřená
DUP_VAL_ON_INDEX ORA-00001 Uložení duplicitní hodnoty do sloupce databáze, který je omezen jedinečným indexem
INVALID_CURSOR ORA-01001 Neplatné operace s kurzorem, například zavření neotevřeného kurzoru
NEPLATNÉ ČÍSLO ORA-01722 Převod znaku na číslo selhal kvůli neplatnému číselnému znaku.
NENALEZENA ŽÁDNÁ DATA ORA-01403 Příkaz SELECT, který obsahuje klauzuli INTO, nenačte žádné řádky.
ROW_MISMATCH ORA-06504 Datový typ proměnné kurzoru není kompatibilní se skutečným návratovým typem kurzoru.
SUBSCRIPT_BEYOND_COUNT ORA-06533 Odkazování na kolekci pomocí indexového čísla většího než je velikost kolekce
SUBSCRIPT_OUTSIDE_LIMIT ORA-06532 Odkazování na kolekci pomocí indexového čísla mimo povolený rozsah (například -1)
TOO_MANY_ROWS ORA-01422 Příkaz SELECT s klauzulí INTO vrací více než jeden řádek.
VALUE_ERROR ORA-06502 Aritmetická chyba nebo chyba omezení velikosti (například přiřazení hodnoty větší než je proměnná size)
ZERO_DIVIDE ORA-01476 Dělení čísla nulou

Uživatelsky definovaná výjimka

Kromě výše uvedených předdefinovaných výjimek může programátor vytvářet vlastní výjimky a ošetřovat je. Ty se vytvářejí na úrovni podprogramu v deklarační části a jsou viditelné pouze uvnitř daného podprogramu. Výjimka definovaná ve specifikaci balíčku je veřejná výjimka a je viditelná všude, kde je možné k balíčku přistupovat.

Syntaxe: Na úrovni podprogramu

DECLARE
<exception_name> EXCEPTION;
BEGIN
<Execution block>
EXCEPTION
WHEN <exception_name> THEN
<Handler>
END;
  • Ve výše uvedené syntaxi je proměnná 'exception_name' definována jako typ VÝJIMKA.
  • Lze jej pak použít stejným způsobem jako předdefinovanou výjimku.

Syntaxe: Na úrovni specifikace balíčku

CREATE PACKAGE <package_name>
 IS
<exception_name> EXCEPTION;
.
.
END <package_name>;
  • Ve výše uvedené syntaxi je proměnná 'exception_name' definována jako typ VÝJIMKY ve specifikaci balíčku .
  • Lze jej použít v celé databázi, kdekoli lze volat balíček 'package_name'.

Výjimka zvýšení PL/SQL

Všechny předdefinované výjimky jsou implicitně vyvolány vždy, když dojde k odpovídající chybě. Uživatelem definované výjimky však musí být vyvolány explicitně pomocí klíčového slova RAISE. RAISE lze použít níže uvedenými způsoby.

Pokud se RAISE použije samostatně uvnitř obslužné rutiny, šíří se již vyvolaná výjimka do nadřazeného bloku. Lze ji použít pouze uvnitř bloku výjimky, jak je znázorněno níže.

Níže uvedený snímek obrazovky ukazuje použití funkce RAISE samostatně k opětovnému vyvolání výjimky v ohraničujícím bloku:

Šíření výjimky do nadřazeného bloku s holým RAISE

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

Vysvětlení syntaxe:

  • Ve výše uvedené syntaxi se klíčové slovo RAISE používá uvnitř bloku pro ošetření výjimek.
  • Kdykoli program narazí na výjimku 'exception_name', je výjimka ošetřena a dokončena normálně.
  • Klíčové slovo RAISE v obslužné rutině pak šíří stejnou výjimku do nadřazeného programu.

Poznámka: Při vyvolání výjimky v nadřazeném bloku musí být vyvolávaná výjimka viditelná i v nadřazeném bloku; jinak Oracle vyvolá chybu.

Klíčové slovo RAISE následované názvem výjimky můžete také použít k vyvolání dané uživatelem definované nebo předdefinované výjimky. Tento formulář lze použít jak v části provádění, tak v části ošetřování výjimek.

Níže uvedený snímek obrazovky ukazuje příkaz RAISE následovaný názvem výjimky pro vyvolání konkrétní výjimky:

Vyvolání specifické pojmenované výjimky pomocí RAISE následované názvem výjimky

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

Vysvětlení syntaxe:

  • Ve výše uvedené syntaxi se v části provádění používá klíčové slovo RAISE, následované výjimkou 'exception_name'.
  • To vyvolá danou výjimku za běhu a poté je třeba ji dále ošetřit nebo vyvolat.

Příklad 1: V tomto příkladu uvidíme:

  • Jak deklarovat výjimku
  • Jak vyvolat deklarovanou výjimku
  • Jak to propagovat do hlavního bloku

Níže uvedený snímek obrazovky ukazuje kompletní blok, který deklaruje výjimku sample_exception, vyvolá ji uvnitř vnořeného bloku a šíří ji do hlavního bloku:

Příklad PL/SQL deklarace a vyvolání uživatelem definované výjimky ve vnořeném bloku

Následující snímek obrazovky ukazuje pokračování stejného příkladu, kde hlavní blok nakonec zachytí šířenou výjimku:

Výstup zobrazující výjimku zachycenou nejprve ve vnořeném bloku a poté v hlavním bloku

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 Vysvětlení:

  • Code řádek 2: Deklarace proměnné 'sample_exception' jako typu EXCEPTION.
  • Code řádek 3: Deklarace procedury nested_block.
  • Code řádek 6: Výpis příkazu „Uvnitř vnořeného bloku“.
  • Code řádek 7: Výpis příkazu „Vyvolání výjimky sample_exception z vnořeného bloku“.
  • Code řádek 8: Vyvolání výjimky pomocí 'RAISE sample_exception'.
  • Code řádek 10: Obslužná rutina výjimky pro výjimku sample_exception ve vnořeném bloku.
  • Code řádek 11: Výpis příkazu „Výjimka zachycena ve vnořeném bloku. Zvýšení na hlavní blok“.
  • Code řádek 12: Vyvolání výjimky do hlavního bloku (její šíření).
  • Code řádek 15: Výpis příkazu „Uvnitř hlavního bloku“.
  • Code řádek 16: Tisk příkazu „Volání vnořeného bloku“.
  • Code řádek 17: Volání procedury nested_block.
  • Code řádek 19: Ovladač výjimky pro sample_exception v hlavním bloku.
  • Code řádek 20: Výpis příkazu „Výjimka zachycena v hlavním bloku“.

Důležité body k poznámce ve výjimce

  • Ve funkci by výjimka měla vždy buď vrátit hodnotu, nebo výjimku dále vyvolat; jinak Oracle za běhu vyvolá chybu „Funkce vrátila bez hodnoty“.
  • Příkazy pro řízení transakcí lze vydat uvnitř bloku pro zpracování výjimek.
  • SQLERRM a SQLCODE jsou vestavěné funkce, které vracejí zprávu o výjimce a kód výjimky.
  • Pokud není výjimka ošetřena, pak se ve výchozím nastavení všechny aktivní transakce v dané relaci vrátí zpět.
  • CHYBA_PŘI_ZVYŠŠÍ_APLIKACI (- , ) lze použít místo RAISE k vyvolání chyby s vlastním kódem a zprávou. Kód chyby musí být v rozmezí -20000 až -20999.

Nejčastější dotazy

Příkaz PRAGMA EXCEPTION_INIT přiřazuje uživatelem deklarovaný název výjimky ke konkrétnímu Oracle číslo chyby. Po navázání můžete danou chybu ORA zachytit podle názvu v klauzuli WHEN namísto použití klauzule WHEN OTHERS a kontroly SQLCODE.

Funkce SQLCODE vrací číselný chybový kód aktuální výjimky, zatímco funkce SQLERRM vrací její textovou zprávu. Oba jsou volány uvnitř obslužné rutiny výjimek, nejčastěji v bloku WHEN OTHERS, k zaznamenání nebo zobrazení chyby.

Vyhněte se funkci WHEN OTHERS, která tiše pohltí každou chybu. Bez protokolování SQLCODE a SQLERRM nebo opětovného vyvolání pomocí RAISE skryje chyby. Používejte ji pouze k protokolování, vyčištění a následnému šíření výjimky.

Funkce RAISE_APPLICATION_ERROR přijímá číslo chyby mezi -20000 a -20999 a zprávu o délce až 2048 bajtů. Zastaví provádění a vrátí volající aplikaci vlastní chybu, čímž se uživatelem definovaná podmínka bude jevit jako nativní. Oracle chyba.

Ne ve stejném bloku – jakmile se řízení přesune do sekce EXCEPTION, tento blok končí. Chcete-li pokračovat, zabalte riskantní příkaz do vnitřního bloku BEGIN…EXCEPTION…END; po ošetření chyby se vnější blok nadále provádí.

Chyba je jakýkoli problém v kódu za běhu nebo kompilace. Výjimkou je běhový mechanismus PL/SQL, který reprezentuje chybu za běhu a přenáší řízení do sekce EXCEPTION, aby program mohl reagovat namísto náhleho ukončení.

Ano. Asistenti umělé inteligence a recenzenti kódu strojového učení navrhují bloky VÝJIMEK, navrhují, které předdefinované výjimky zachytit, a označují cesty kódu, které postrádají obslužné rutiny. Vývojář by si měl i tak před nasazením ověřit logiku a chybové zprávy.

GitHub Copilot Automaticky doplňuje klauzule WHEN, volání RAISE_APPLICATION_ERROR a celé bloky EXCEPTION z krátkého komentáře popisujícího záměr. Urychluje kódování rutinních obslužných rutin, i když generované chybové kódy a zprávy vyžadují kontrolu přesnosti.

Shrňte tento příspěvek takto: