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

Що таке обробка винятків у PL/SQL?
Виняток виникає, коли механізм PL/SQL зустрічає інструкцію, яку не може виконати через помилку, що виникає під час виконання. Ці помилки не виявляються під час компіляції, і тому їх потрібно обробляти лише під час виконання.
Наприклад, якщо механізм PL/SQL отримує інструкцію ділення числа на нуль, він викликає помилку як виняток. Виняток викликається механізмом PL/SQL лише під час виконання.
Виняток зупиняє подальше виконання програми, тому, щоб уникнути такої ситуації, помилку потрібно перехоплювати та обробляти окремо. Цей процес називається обробкою винятків, під час якої програміст обробляє помилку, яка може виникнути під час виконання.
Синтаксис обробки винятків
Винятки обробляються на рівні блоку. Після виникнення винятку в блоці керування залишає частину виконання цього блоку, і виняток потім обробляється в частині обробки винятків блоку. Після обробки винятку керування не може повернутися до частини виконання того ж блоку.
На ілюстрації нижче показано, як розділ виконання та розділ обробки винятків розташовані в одному блоці 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) |
| ZERO_DIVIDE | 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
Усі попередньо визначені винятки викликаються неявно щоразу, коли виникає відповідна помилка. Однак, винятки, визначені користувачем, повинні бути викликані явно за допомогою ключового слова 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' як типу 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.





