Обработка исключений в 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 предопределены некоторые распространенные исключения. Каждое предопределенное исключение имеет уникальное имя и номер ошибки, и все они объявлены в пакете 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 | Пытаюсь открыть курсор который уже открыт |
| DUP_VAL_ON_INDEX | ORA-00001 | Хранение повторяющегося значения в столбце базы данных, ограниченном уникальным индексом. |
| INVALID_CURSOR | ORA-01001 | Недопустимые операции с курсором, такие как закрытие неоткрытого курсора. |
| НЕПРАВИЛЬНЫЙ НОМЕР | 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 | Арифметическая ошибка или ошибка, связанная с ограничением размера (например, присвоение значения, превышающего размер переменной). |
| 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 отдельно для повторного вызова исключения в окружающем блоке:
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_APPLICATION_ERROR (- , Вместо команды RAISE можно использовать ) для генерации ошибки с пользовательским кодом и сообщением. Код ошибки должен находиться в диапазоне от -20000 до -20999.





