Протокол ошибок

Протокол ошибок

Если для вас важно сохранять протокол ошибок, помните, что исключения, возникающие у клиента, приводят к отмене всей работы, выполненной в модуле. Если вы ведете протокол в таблице базы данных, то записи протокола исчезнут вместе с другой отмененной работой. В случаях, когда обработчики исправят или "проглотят" каждую ошибку, внутренняя таблица будет работать просто прекрасно.

Если вам нужен протокол, который будет сохраняться и после необработанного исключения, используйте внешнюю таблицу. Подробности см. в разд. "Использование внешних файлов в качестве таблиц" главы 16.

! ! !

СОВЕТ. В конце этой главы описано применение подобной техники в процедуре, которая добавляет строки во внешнюю таблицу, хотя последняя не является таблицей протоколирования ошибок.

. ! .

SQLCODE и GDSCODE

В версии 1.5 и выше вы можете перехватить числовой код ошибки, который передается внутренне определенному исключению в контекстной переменной SQLCODE или GDSCODE. Это предоставляет весьма компактный способ протоколирования текущего исключения в виде фрагмента вашей подпрограммы обработки исключений.

Внутренне определенные исключения имеют и SQLCODE, и GDSCODE. Ваш код может обратиться только к одному коду, другой будет недоступен.

! ! !

ПРИМЕЧАНИЕ. Каждый раз, когда вы попытаетесь обратиться к этим кодам вне блока обработчика, вы получите ноль.

. ! .

Следующая структура блока кода завершается группой обработчиков исключений. Первые два обрабатывают ошибки SQLCODE в виде пользовательских исключений. Эти пользовательские исключения могут быть обработаны во внешнем блоке или их назначением может быть аварийное завершение процедуры и возврат клиенту полезного сообщения.

Если не появилось ни одного из предусмотренных исключений, а было некоторое другое, то его перехватит оператор WHEN ANY. Его обработчик вызывает хранимую процедуру для вывода записи протокола, передавая код SQLCODE вместе с другими входными аргументами, полученными из контекста блока:

BEGIN

. . .

WHEN SQLCODE -802 DO

EXCEPTION E_EXCEPTION_1;

WHEN SQLCODE -803 DO

EXCEPTION E_EXCEPTION_2;

WHEN ANY DO

EXECUTE PROCEDURE P_ANY_EXCEPTION (SQLCODE, другие входные данные ...);

END

Повторный вызов исключения

Предположим, вам нужно перехватить и внести во внешнюю таблицу протокола непредвиденную ошибку, перед тем как позволить исключению выполнить свою работу и завершить процедуру или триггер. Начиная с версии 1.5, можно повторно вызвать исключение - вы можете выполнить некоторую обработку исключения и завершить обработчик оператором EXCEPTION для возбуждения исключения и передачи управления на конечный END. Выполнение останавливается, и управление передается клиенту с кодом или именем исключения и подходящим сообщением в массиве состояния ошибки.

В вашем обработчике вы выбираете SQLCODE или GDSCODE и некоторые другие контекстные переменные, записываете запись в протокол, а затем заново вызываете исключение:

BEGIN

. . .

WHEN ANY DO

BEGIN

EXECUTE PROCEDURE P_ANY_EXCEPTION (SQLCODE, другие входные данные ...);

EXCEPTION; END

END ^