Обробка винятків у Oracle PL/SQL (приклади)

⚡ Розумний підсумок

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

  • Помилки під час виконання: Виняток виникає, коли механізм PL/SQL зустрічає інструкцію, яку він не може виконати, наприклад, ділення числа на нуль.
  • 🧱 Структура блоку: Винятки обробляються в розділі EXCEPTION за допомогою речень WHEN, де WHEN OTHERS завжди розміщується останнім.
  • 📚 Попередньо визначені винятки: Oracle іменує поширені помилки, такі як NO_DATA_FOUND та ZERO_DIVIDE у пакеті STANDARD, готові до безпосереднього перехоплення.
  • 🛠️ Винятки, визначені користувачем: Програмісти оголошують власні змінні EXCEPTION та явно викликають їх за допомогою ключового слова RAISE.
  • ⬆️ Розмноження: Необроблений виняток передається до блоку, що його оточує, а RAISE повторно сигналізує про нього батьківській програмі.
  • 🤖 Допомога AI: Інструменти штучного інтелекту (AI) кодування створюють блоки ВИНЯТКІВ та позначають необроблені шляхи помилок під час перевірки.

Обробка винятків у Oracle PL / SQL

Що таке обробка винятків у PL/SQL?

Виняток виникає, коли механізм 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 використовується окремо для повторного виклику винятку в оточуючому блоці:

Поширення винятку на батьківський блок за допомогою простого RAISE

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

Пояснення синтаксису:

  • У наведеному вище синтаксисі ключове слово RAISE використовується всередині блоку обробки винятків.
  • Щоразу, коли програма стикається з винятком 'exception_name', виняток обробляється та завершується нормально.
  • Ключове слово RAISE в обробнику потім поширює той самий виняток на батьківську програму.

Примітка: Під час виникнення винятку для батьківського блоку, виняток, що викликається, також має бути видимим у батьківському блоці; інакше Oracle видає помилку.

Ви також можете використовувати ключове слово RAISE, а потім ім'я винятку, щоб викликати цей конкретний визначений користувачем або попередньо визначений виняток. Цю форму можна використовувати як у частині виконання, так і в частині обробки винятків.

На скріншоті нижче показано 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, викликає його всередині вкладеного блоку та поширює його на основний блок:

Приклад PL/SQL: оголошення та виклик користувацького винятку у вкладеному блоці

На наступному скріншоті показано той самий приклад, де основний блок нарешті фіксує поширений виняток:

Вивід, що показує виняток, захоплений спочатку у вкладеному блоці, а потім у головному блоці

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.

Поширені запитання

PRAGMA EXCEPTION_INIT пов'язує ім'я винятку, оголошене користувачем, з певним Oracle номер помилки. Після зв'язування ви можете перехопити цю помилку ORA за назвою в реченні WHEN замість використання WHEN OTHERS та перевірки SQLCODE.

SQLCODE повертає числовий код помилки поточного винятку, тоді як SQLERRM повертає його текстове повідомлення. Обидва викликаються всередині обробника винятків, найчастіше в блоці WHEN OTHERS, для реєстрації або відображення того, що пішло не так.

Уникайте WHEN OTHERS, який мовчки ковтає кожну помилку. Без логування SQLCODE та SQLERRM або повторного виклику за допомогою RAISE, це приховує помилки. Використовуйте його лише для логування, очищення та подальшого поширення винятку.

RAISE_APPLICATION_ERROR приймає номер помилки від -20000 до -20999 та повідомлення довжиною до 2048 байт. Він зупиняє виконання та повертає власну помилку до викликаючої програми, роблячи визначену користувачем умову схожою на власну. Oracle помилка

Не в тому ж блоці — як тільки керування переходить до секції EXCEPTION, цей блок завершується. Щоб продовжити, оберніть ризикований оператор у внутрішній блок BEGIN…EXCEPTION…END; після обробки помилки зовнішній блок продовжує виконуватися.

Помилка — це будь-яка проблема під час виконання або компіляції коду. Виняток — це механізм виконання PL/SQL, який представляє помилку під час виконання, передаючи керування розділу EXCEPTION, щоб програма могла реагувати, а не раптово завершувати свою роботу.

Так. Помічники ШІ та фахівці з машинного навчання створюють блоки EXCEPTION, пропонують, які попередньо визначені винятки перехоплювати, та позначають шляхи коду, яким бракує обробників. Розробник все одно повинен перевірити логіку та повідомлення про помилки перед розгортанням.

Копілот GitHub автоматично завершує речення WHEN, виклики RAISE_APPLICATION_ERROR та повні блоки EXCEPTION з короткого коментаря, що описує намір. Це пришвидшує кодування обробників рутин, хоча згенеровані коди помилок та повідомлення потребують перевірки на точність.

Підсумуйте цей пост за допомогою: