Обработка на изключения в Oracle PL/SQL (Примери)
⚡ Умно обобщение
Обработка на изключения Oracle PL/SQL улавя грешки по време на изпълнение, които спират изпълнението на блок, позволявайки на двигателя да прехвърли контрола към секция EXCEPTION, където предварително дефинирани, потребителски дефинирани и OTHERS обработчици реагират, повдигат или разпространяват грешки безопасно.

Какво е обработка на изключения в PL/SQL?
Изключение възниква, когато PL/SQL системата срещне инструкция, която не може да изпълни поради грешка, възникнала по време на изпълнение. Тези грешки не се откриват по време на компилация и следователно трябва да се обработват само по време на изпълнение.
Например, ако PL/SQL енджинът получи инструкция за деление на число на нула, той генерира грешката като изключение. Изключението се генерира само по време на изпълнение от PL/SQL енджинa.
Изключение спира по-нататъшното изпълнение на програмата, така че за да се избегне подобно състояние, грешката трябва да бъде заснета и обработена отделно. Този процес се нарича обработка на изключения, при който програмистът обработва грешката, която може да възникне по време на изпълнение.
Синтаксис за обработка на изключения
Изключенията се обработват на ниво блок. След като възникне изключение в блок, управлението напуска частта за изпълнение на този блок и изключението се обработва в частта за обработка на изключения на блока. След обработката на изключението, управлението не може да се върне в секцията за изпълнение на същия блок.
Илюстрацията по-долу показва как секцията за изпълнение и секцията за обработка на изключения се намират в един PL/SQL блок:
Синтаксисът по-долу обяснява как да се улови и обработи изключение.
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;
Обяснение на синтаксиса:
- В горния синтаксис, блокът за обработка на изключения съдържа серия от условия WHEN за обработка на изключения.
- Всяко условие WHEN е последвано от име на изключение, което се очаква да бъде генерирано по време на изпълнение.
- Когато по време на изпълнение се генерира изключение, PL/SQL енджинът търси в частта за обработка на изключенията това конкретно изключение, започвайки от първата клауза WHEN и продължавайки последователно.
- Ако намери обработчик за генерираното изключение, той изпълнява този конкретен код на обработчика.
- Ако никоя WHEN клауза не съответства на генерираното изключение, PL/SQL енджинът изпълнява частта WHEN OTHERS, ако има такава. Този манипулатор е общ за всички изключения.
- След като обработчикът се изпълни, контролът напуска текущия блок.
- Само един обработчик на изключения може да се изпълни за блок по време на изпълнение. След като се изпълни, енджина пропуска останалите обработчици и напуска текущия блок.
Забележка: WHEN OTHERS винаги трябва да се поставя последен в последователността. Всеки манипулатор, написан след WHEN OTHERS, никога не се изпълнява, защото управлението излиза от блока след изпълнението на WHEN OTHERS.
Видове изключения
Има два вида изключения в PL / SQL.
- Предварително дефинирани изключения
- Потребителски дефинирани изключения
Предварително дефинирани изключения
Oracle има предварително дефинирани някои често срещани изключения. Всяко предварително дефинирано изключение има уникално име и номер на грешката и всички те са декларирани в пакета STANDARD в OracleВ кода можете да използвате тези предварително дефинирани имена на изключения директно, за да обработвате съответните грешки. Много от тях се съпоставят директно с често срещани грешки. SQL грешки, с които се сблъсквате всеки ден.
По-долу са дадени няколко предварително дефинирани изключения:
| изключение | грешка Code | Причина за изключение |
|---|---|---|
| ACCESS_INTO_NULL | ORA-06530 | Присвояване на стойност на атрибутите на неинициализиран обект |
| CASE_NOT_FOUND | ORA-06592 | Нито една от клаузите WHEN в оператор CASE не е изпълнена и не е посочена клауза ELSE. |
| COLLECTION_IS_NULL | ORA-06531 | Използване на методи за колекция (с изключение на EXISTS) или достъп до атрибути на колекция на неинициализирана колекция |
| CURSOR_ALREADY_OPEN | ORA-06511 | Опитвайки се да отворите a курсор което вече е отворено |
| DUP_VAL_ON_INDEX | ORA-00001 | Съхраняване на дублирана стойност в колона на база данни, която е ограничена от уникален индекс |
| INVALID_CURSOR | ORA-01001 | Незаконни операции с курсора, като например затваряне на неотворен курсор |
| INVALID_NUMBER | ORA-01722 | Преобразуването на символ в число е неуспешно поради невалиден числов символ |
| НЯМА_НАМЕРЕНИ_ДАННИ | ORA-01403 | Израз SELECT, който съдържа клауза INTO, не извлича редове |
| ROW_MISMATCH | ORA-06504 | Типът данни на променливата на курсора е несъвместим с действителния тип връщане на курсора |
| SUBSCRIPT_BEYOND_COUNT | ORA-06533 | Препращане към колекция чрез индексен номер, по-голям от размера на колекцията |
| SUBSCRIPT_OUTSIDE_LIMIT | ORA-06532 | Препращане към колекция чрез индексен номер извън допустимия диапазон (например -1) |
| TOO_MANY_ROWS | ORA-01422 | SELECT оператор с INTO клауза връща повече от един ред |
| VALUE_ERROR | ORA-06502 | Аритметична грешка или грешка, свързана с ограничението на размера (например, присвояване на стойност, по-голяма от променливата size) |
| НУЛА_ДЕЛЕНИЕ | ORA-01476 | Деление на число на нула |
Дефинирано от потребителя изключение
Освен предварително дефинираните изключения по-горе, програмистът може да създава персонализирани изключения и да ги обработва. Те се създават на ниво подпрограма в декларационната част и са видими само в рамките на тази подпрограма. Изключение, дефинирано в спецификация на пакет, е публично изключение и е видимо навсякъде, където може да се осъществи достъп до пакета.
Синтаксис: На ниво подпрограма
DECLARE <exception_name> EXCEPTION; BEGIN <Execution block> EXCEPTION WHEN <exception_name> THEN <Handler> END;
- В горния синтаксис, променливата „exception_name“ е дефинирана като тип EXCEPTION.
- След това може да се използва по същия начин като предварително дефинирано изключение.
Синтаксис: На ниво спецификация на пакета
CREATE PACKAGE <package_name> IS <exception_name> EXCEPTION; . . END <package_name>;
- В горния синтаксис, променливата „exception_name“ е дефинирана като тип EXCEPTION в спецификацията на пакета на .
- Може да се използва в базата данни, където и да може да се извика пакетът „package_name“.
PL/SQL Raise Exception
Всички предварително дефинирани изключения се генерират имплицитно, когато възникне съответната грешка. Потребителски дефинираните изключения обаче трябва да се генерират изрично, като се използва ключовата дума RAISE. RAISE може да се използва по начините, показани по-долу.
Ако RAISE се използва самостоятелно вътре в манипулатор, той разпространява вече генерираното изключение към родителския блок. Може да се използва само вътре в блок с изключения, както е показано по-долу.
Снимката на екрана по-долу показва RAISE, използван самостоятелно за повторно генериране на изключение към ограждащия блок:
CREATE [ PROCEDURE | FUNCTION ] AS BEGIN <Execution block> EXCEPTION WHEN <exception_name> THEN <Handler> RAISE; END;
Обяснение на синтаксиса:
- В горния синтаксис ключовата дума RAISE се използва вътре в блока за обработка на изключения.
- Всеки път, когато програмата срещне изключението „exception_name“, то се обработва и завършва нормално.
- Ключовата дума RAISE в манипулатора след това разпространява същото изключение към родителската програма.
Забележка: Когато се генерира изключение към родителския блок, генерираното изключение трябва да е видимо и в родителския блок; в противен случай Oracle хвърля грешка.
Можете също да използвате ключовата дума RAISE, последвана от име на изключение, за да генерирате това конкретно потребителски дефинирано или предварително дефинирано изключение. Тази форма може да се използва както в частта за изпълнение, така и в частта за обработка на изключения.
Снимката на екрана по-долу показва RAISE, последвано от име на изключение, за да се генерира конкретно изключение:
CREATE [ PROCEDURE | FUNCTION ] AS BEGIN <Execution block> RAISE <exception_name> EXCEPTION WHEN <exception_name> THEN <Handler> END;
Обяснение на синтаксиса:
- В горния синтаксис, ключовата дума RAISE се използва в частта за изпълнение, последвана от изключението 'exception_name'.
- Това поражда това конкретно изключение по време на изпълнение и след това то трябва да бъде обработено или повиквано допълнително.
Пример 1: В този пример ще видим:
- Как да декларирам изключение
- Как да се повдигне декларираното изключение
- Как да го разпространя в основния блок
Екранната снимка по-долу показва целия блок, който декларира sample_exception, повдига го във вложен блок и го разпространява към главния блок:
Следната екранна снимка показва същия пример, където основният блок най-накрая улавя разпространеното изключение:
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 Обяснение:
- Code ред 2: Деклариране на променливата 'sample_exception' като тип ИЗКЛЮЧЕНИЕ.
- Code ред 3: Деклариране на процедурата nested_block.
- Code ред 6: Отпечатване на оператора „Вътре във вложен блок“.
- Code ред 7: Отпечатване на оператора „Повишаване на sample_exception от вложен блок“.
- Code ред 8: Повишаване на изключението чрез „RAISE sample_exception“.
- Code ред 10: Обработчик на изключения за изключението sample_exception във вложения блок.
- Code ред 11: Отпечатване на оператора „Изключение, заловено във вложен блок. Повишаване до главен блок“.
- Code ред 12: Повишаване на изключението към основния блок (разпространението му).
- Code ред 15: Отпечатване на оператора „Вътре в главния блок“.
- Code ред 16: Отпечатване на оператора „Извикване на вложен блок“.
- Code ред 17: Извикване на процедурата nested_block.
- Code ред 19: Обработчик на изключения за sample_exception в главния блок.
- Code ред 20: Отпечатване на оператора „Изключение, заснето в главния блок“.
Важни моменти за отбелязване в Изключение
- Във функция, изключението винаги трябва или да върне стойност, или да предизвика допълнително изключение; в противен случай Oracle хвърля грешка „Функция, върната без стойност“ по време на изпълнение.
- Извлечения за контрол на транзакциите може да бъде издаден вътре в блока за обработка на изключения.
- SQLERRM и SQLCODE са вградени функции, които връщат съответно съобщението за изключение и кода на изключението.
- Ако дадено изключение не бъде обработено, по подразбиране всички активни транзакции в тази сесия се отменят.
- ГРЕШКА_В_ПРИЛОЖЕНИЕТО_ЗА_ПОВИШАВАНЕ (- , ) може да се използва вместо RAISE за генериране на грешка с персонализиран код и съобщение. Кодът на грешката трябва да бъде между -20000 и -20999.





