
Какую работу нужно написать?
Обработка ошибок
При возникновении исключительных ситуаций важно выдавать дружественные к пользователю сообщения об ошибках. Об исключениях уже упоминалось в разделе, посвященном базовым блокам PL/SQL. Теперь настало время рассмотреть их подробнее.
Исключения
Исключение – это состояние ошибки, которое активизируется – или возбуждается – при возникновении некоторой проблемы. Существует много разных исключений, каждое из которых связано с определенным типом проблем. При возникновении исключительной ситуации выполнение кода останавливается на операторе, который возбудил исключение, и управление передается той части блока, которая обрабатывает это исключение. Если блок не содержит выполняемой секции, PL/SQL пытается найти выполняемую секцию во включающем базовом блоке (enclosing basic block), т.е. в блоке, который является внешним по отношению к коду, возбудившему исключение. Если в непосредственном включающем блоке отсутствует обработчик данного исключения, то поиск продолжается в блоках следующих уровней, пока не будет найден подходящий обработчик, а если его найти не удается, то выполнение программы прекращается с выдачей сообщения о необрабатываемой ошибке.
Часть блока, предназначенная для обработки исключений, – это идеальное место для выдачи информативных сообщений об ошибках и выполнения очистки (cleanup), позволяющей избавиться от всего, что могло бы в дальнейшем вызвать путаницу или проблемы. Если исключение было возбуждено в ходе выполнения процедуры вставляющей строки в таблицу, то типичная процедура очистки может включать в себя оператор ROLLBACK.
После того как управление было передано обработчику исключения, оно уже не возвращается оператору, ставшему причиной этого исключения. Вместо этого управление передается оператору включающего базового блока, который следует сразу за вызовом вложенного блока или процедуры/функции.
Системные исключения
Вы уже знакомы с исключением ZERO_DIVIDE, предопределенным в PL/SQL. Существует довольно много других системных исключений, которые распознаются и возбуждаются PL/SQL или Oracle. В таблице 1 приведен более полный список системных исключений.
В PL/SQL можно выдавать пользователям информацию об ошибке двумя способами. Первый способ – использовать команду SQLCODE, которая возвращает код ошибки. Этот код представляет собой отрицательное число, обычно равное номеру ошибки ORA, которая выводится при завершении приложения, если исключение осталось необработанным. Второй способ – возвращать текстовое сообщение, описывающее ошибку. Неудивительно, что соответствующая команда называется SQLERRM. В обработчике исключения можно использовать как SQLCODE, так и SQLERRM. Замечание: не у всех системных исключений есть имена.
Таблица 1. Системные исключения
Системное исключение, код ошибки |
Причина возбуждения |
CURSOR_ALREADY_OPEN ORA-06511 |
Попытка открыть уже открытый курсор |
DUP_VAL_ON_INDEX ORA-00001 |
Попытка вставить повторяющееся значение в столбец, имеющий уникальный индекс, а следовательно, ограничение уникальности |
INVALID_CURSOR ORA-01001 |
Попытка применить команду FETCH к неоткрытому курсору или попытка закрыть курсор, который не открывался |
NO_DATA_FOUND ORA-01403 |
Попытка выполнить SELECT INTO, когда SELECT возвращает нулевое количество строк (а также другие причины, описание которых выходит за рамки этой книги) |
PROGRAM_ERROR ORA-06501 |
Внутренняя ошибка. Обычно означает, что вам нужно обратиться в службу поддержки Oracle |
STORAGE_ERROR ORA-06500 |
Программе не хватает системной памяти |
TIMEOUT_ON_RESOURCE ORA-00051 |
Программа слишком долго ожидала доступности некоторого ресурса |
TOO_MANY_ROWS ORA-01422 |
SELECT INTO в PL/SQL вернул более одной строки |
VALUE_ERROR ORA-06502 |
PL/SOL встретил неправильное преобразование или усечение данных, или неправильное ограничение на данные |
ZERO_DIVIDE ORA-01476 |
Попытка деления на нуль |
OTHERS |
Все прочие исключения и внутренние ошибки, которые не охватываются исключениями, определенными в базовом блоке. Используется в тех случаях, когда вы точно не знаете, какое именованное исключение предстоит обрабатывать, и хотите обрабатывать любые возбуждаемые исключения |
Теперь вернемся к самому первому примеру этой главы и используем в нем SQLCODE и SQLERRM. Ниже приведен исходный код примера и результаты его запуска (рис.1).
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 '|| 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;
/
SQL> set serveroutput on
SQL> DECLARE
2 num_a NUMBER := 6;
3 num_b NUMBER;
4 BEGIN
5 num_b := 0;
6 num_a := num_a / num_b;
7 num_b := 7;
8 dbms_output.put_line(' Value of num_b '|| num_b);
9 EXCEPTION
10 WHEN ZERO_DIVIDE
11 THEN
12 DECLARE
13 err_num NUMBER := SQLCODE;
14 err_msg VARCHAR2(512) := SQLERRM;
15 BEGIN
16 dbms_output.put_line('ORA Error Number '|| err_num);
17 dbms_output.put_line('ORA Error message ' || err_msg);
18 dbms_output.put_line('Value of num_a ' || num_a);
19 dbms_output.put_line('Value of num_b ' || num_b);
20 END;
21 END;
22 /
ORA Error Number -1476
ORA Error Message ORA-01476: divisor is equal to zero
Value of num_а 6
Value of num_b 0
PL/SQL procedure successfully completed.
SQL>
Рис. 1. Использование SQLCODE и SQLERRM при обработке системных исключений