Обработка на изключения в 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 енджинa.

Изключение спира по-нататъшното изпълнение на програмата, така че за да се избегне подобно състояние, грешката трябва да бъде заснета и обработена отделно. Този процес се нарича обработка на изключения, при който програмистът обработва грешката, която може да възникне по време на изпълнение.

Синтаксис за обработка на изключения

Изключенията се обработват на ниво блок. След като възникне изключение в блок, управлението напуска частта за изпълнение на този блок и изключението се обработва в частта за обработка на изключения на блока. След обработката на изключението, управлението не може да се върне в секцията за изпълнение на същия блок.

Илюстрацията по-долу показва как секцията за изпълнение и секцията за обработка на изключения се намират в един 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)
НУЛА_ДЕЛЕНИЕ 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, използван самостоятелно за повторно генериране на изключение към ограждащия блок:

Разпространение на изключение към родителския блок с гола 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' като тип ИЗКЛЮЧЕНИЕ.
  • 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 от кратък коментар, описващ намерението. Ускорява кодирането на рутинните обработчици, въпреки че генерираните кодове за грешки и съобщения изискват преглед за точност.

Обобщете тази публикация с: