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.

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:
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:
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:
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:
Následující snímek obrazovky ukazuje pokračování stejného příkladu, kde hlavní blok nakonec zachytí šířenou výjimku:
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.





