После прилета исключения в раздел обработки возможны два случая:
если никакой обработчик исключению не подошел, то исключение со статусом «не обработано» бросается в дальнейший полет уже в родительском блоке (блоке, предыдущим по вложенности) с того места кода, где заканчивается вложенный блок;
если в результате «примерки» нашелся подходящий исключению обработчик, то управление передается ему.
Работа обработчика свою очередь может завершиться тремя исходами:
команды обработчика успешно выполнились, исключение получает статус «обработано» и управление передается родительскому блоку в то место кода, где заканчивается вложенный блок;
в процессе работы обработчика принято решение, что обрабатывать исключение надо не в этом обработчике, тогда исключение здесь же в обработчике инициируется повторно вызовом команды RAISE без параметров;
в ходе выполнения команд обработчика инициировано новое исключение (такое бывает, например, если в обработчике ошибки регистрируются в специальной таблице, а для нее кончилось место), прилетевшее исходное исключение тогда получает статус «обработано».
Два последних исхода работы обработчика предполагают, что из блока даже с подходящим обработчиком исключение бросится дальше – либо то же самое (после вызова команды RAISE), либо уже другое. Могло прилететь пользовательское исключение, обработаться со своей ошибкой, поэтому из обработчика бросится и в родительском блоке полетит дальше уже системное исключение, как в примере с ошибкой добавления строки в специальную таблицу журнала ошибок.
Примеры обработки исключений
Рассмотрим примеры полетов исключений в программе из трех вложенных блоков:
BEGIN – начало блока1
команда1_блока1;
команда2_блока1;
команда3_блока1;
BEGIN – начало блока2
команда1_блока2;
команда2_блока2 l_int := 1/TO_NUMBER(l_var) (l_var='1' или '0' или 'a')
команда3_блока2;
EXCEPTION
WHEN ZERO_DIVIDE THEN
команда1_zero_блока2;
команда2_zero_блока2;
END; – конец блока2
команда4_блока1;
команда5_блока1;
EXCEPTION
WHEN ZERO_DIVIDE THEN
команда1_zero_блока1;
команда2_zero_блока1;
WHEN OTHERS THEN
команда1_others_блока1;
команда2_others_блока1;
END; – конец блока 1
Пусть команда2_блока2 имеет вид l_int:=1/TO_NUMBER(l_var); где l_int – целочисленная переменная, l_var – символьная.
l_var='1' (без исключений)
l_var='0' (zero divide)
l_var='a' (conversion error)
команда1_блока1;
команда2_блока1;
команда3_блока1;
команда1_блока2;
команда2_блока2;
команда3_блока2;
команда4_блока1;
команда5_блока1;
команда1_блока1;
команда2_блока1;
команда3_блока1;
команда1_блока2;
команда2_блока2(error);
– в