- •6. Управляющие структуры и обработка ошибок в pl/sql
- •6.1. Оператор if
- •6.2. Циклы
- •Цикл loop
- •Цикл while
- •Цикл for
- •6.3. Курсоры
- •Объявление курсора и атрибуты курсора
- •Записи pl/sql
- •Использование команд open, fetch и close
- •Курсорный цикл for
- •Предложение where с условием поиска current of
- •6.4. Использование вложенных циклов и курсоров
- •6.5. Обработка ошибок
- •Исключения
- •Системные исключения
- •Исключения, определяемые программистом
6.5. Обработка ошибок
При возникновении исключительных ситуаций важно выдавать поясняющие суть ошибок сообщения. Об исключениях уже упоминалось в разделе 5.3 темы 5, посвященном базовым блокам PL/SQL. Теперь они будут рассмотрены подробнее.
Исключения
Исключение — это состояние ошибки, которое активизируется — или возбуждается — при возникновении некоторой проблемы. Существует много разных исключений, каждое из которых связано с определенным типом проблем. При возникновении исключительной ситуации выполнение кода останавливается на операторе, который возбудил исключение, и управление передается той части блока, которая обрабатывает это исключение. Если блок не содержит выполняемой секции, PL/SQL пытается найти выполняемую секцию во включающем базовом блоке (enclosing basic block), т.е. в блоке, который является внешним по отношению к коду, возбудившему исключение. Если в непосредственном включающем блоке отсутствует обработчик данного исключения, то поиск продолжается в блоках следующих уровней, пока не будет найден подходящий обработчик, а если его найти не удается, то выполнение программы прекращается с выдачей сообщения о необрабатываемой ошибке.
Часть блока, предназначенная для обработки исключений, — это идеальное место для выдачи информативных сообщений об ошибках и выполнения очистки, позволяющей избавиться от всего, что могло бы в дальнейшем вызвать путаницу или проблемы. Если исключение было возбуждено в ходе выполнения процедуры, вставляющей строки в таблицу, то типичная процедура очистки может включать в себя оператор ROLLBACK.
После того как управление было передано обработчику исключения, оно уже не возвращается оператору, ставшему причиной этого исключения. Вместо этого управление передается оператору включающего базового блока, который следует сразу за вызовом вложенного блока или процедуры/функции.
Системные исключения
Помимо исключения ZERO_DIVIDE, приведенного в качестве примера в разделе 5.3, существует довольно много других системных исключений, которые распознаются и активизируются в PL/SQL или Oracle. В таблице 6.2 приведен более полный список системных исключений.
Таблица 6.2
Список некоторых системных исключений
Системное исключение |
Причина активизации |
CURSOR_ALREADY_OPEN |
Попытка открыть уже открытый курсор |
DUP_VAL_ON_INDEX |
Попытка вставить повторяющееся значение в столбец, имеющий уникальный индекс, а следовательно, ограничение уникальности |
INVALID_CURSOR |
Попытка применить команду FETCH к неоткрытому курсору или попытка закрыть курсор, который не открывался |
NO_DATA_FOUND
|
Попытка выполнить SELECT INTO, когда SELECT возвращает нулевое количество строк (а также некоторые другие причины) |
PROGRAM_ERROR |
Внутренняя ошибка. Обычно означает, что нужно обратиться в службу поддержки Oracle |
STORAGE_ERROR |
Программе не хватает системной памяти |
TIME_OUT_ON_RESOURCE |
Программа слишком долго ожидала доступности некоторого ресурса |
TOO_MANY_ROWS |
SELECT INTO в PL/SQL вернул более одной строки |
VALUE_ERROR |
PL/SQL встретил неправильное преобразование или усечение данных, или неправильное ограничение на данные |
ZERO_DIVIDE |
Попытка деления на нуль |
OTHERS |
Все прочие исключения и внутренние ошибки, которые не охватываются исключениями, определенными в базовом блоке. Используется в тех случаях, когда точно не известно, какое именованное исключение предстоит обрабатывать, и необходимо обрабатывать любые активизируемые исключения |
В PL/SQL можно выдавать пользователям информацию об ошибке двумя способами. Первый способ — использовать команду SQLCODE, которая возвращает код ошибки. Этот код представляет собой отрицательное число, обычно равное номеру ошибки ORA, которая выводится при завершении приложения, если исключение осталось необработанным. Второй способ — возвращать текстовое сообщение, описывающее ошибку, с помощью соответствующей команды SQLERRM. В обработчике исключения можно использовать как SQLCODE, так и SQLERRM. Однако не у всех системных исключений есть имена.
Пример, приведенный в разделе 5.3, можно модифицировать, чтобы использовать в нем команды SQLCODE и SQLERRM:
DECLARE
Num_a NUMBER := 6;
Num_b NUMBER;
BEGIN
Num_b := 0;
Num_a := Num_a / Num_b;
Num_b := 7;
dbms_output.put_line(' Value of Num_b ' I I Num_b);
EXCEPTION
WHEN ZERO_DIVIDE THEN
DECLARE
err_num NUMBER := SQLCODE;
err_msg VARCHAR2(512) := SQLERRM;
BEGIN
dbms_output.put_line('ORA Error number ' || err_num ) ;
dbms_.output.put_line('ORA Error message ' || err_msg) ;
dbms_output.put_line(' Value of Num_a ' || Num_a);
dbms_output.put_line(' Value of Num_b ' || Num_b);
END;
END;
/