Петрелевич Сергей
Часто при обработке исключений в pl/sql разработчики ограничиваются использованием встроенной функцииsqlerrm, однако в Oracle есть и другие интересные средства для обработки ошибок. Одно из этих средств - функция dbms_utility.format_error_backtrace.
Функция dbms_utility.format_error_backtrace возвращает список вызовов функций и процедур от места генерации исключения до места его обработки.
Для рассмотрения работы dbms_utility.format_error_backtrace создадим тестовый пакет с процедурами, которые подобно матрешкам вызываются одна из другой.
create or replace package Err as
procedure testProc1;
procedure testProc2;
procedure testProc3;
procedure testProc4;
end;
Пример 1. dbms_utility.format_error_backtrace в каждом обработчике исключений
В первом примере функция dbms_utility.format_error_backtrace вставлена в обработчики исключений каждой процедуры.
- create or replace package body Err as
-
- procedure testProc1 is
- begin
- dbms_output.put_line('testProc1');
- testProc2;
- exception
- when others then
- dbms_output.put_line('testProc1 error:'//dbms_utility.format_error_stack);
- dbms_output.put_line('stack:'//dbms_utility.format_error_backtrace);
- end;
-
- procedure testProc2 is
- begin
- dbms_output.put_line('testProc2');
- testProc3;
- exception
- when others then
- dbms_output.put_line('testProc2 error:'//dbms_utility.format_error_stack);
- dbms_output.put_line('stack:'//dbms_utility.format_error_backtrace);
- raise;
- end;
- procedure testProc3 is
- begin
- dbms_output.put_line('testProc3');
- testProc4;
- exception
- when others then
- dbms_output.put_line('testProc3 error:'//dbms_utility.format_error_stack);
- dbms_output.put_line('stack:'//dbms_utility.format_error_backtrace);
- raise;
- end;
-
- procedure testProc4 is
- begin
- dbms_output.put_line('testProc4');
- raise no_data_found;
- exception
- when others then
- dbms_output.put_line('testProc4 error:'//dbms_utility.format_error_stack);
- dbms_output.put_line('stack:'//dbms_utility.format_error_backtrace);
- raise;
- end;
-
- end;
Выполняем первую процедуру.
Получаем результат:
testProc1
testProc2
testProc3
testProc4
testProc4 error:ORA-01403: no data found
stack:ORA-06512: at "DEV.ERR", line 38
testProc3 error:ORA-01403: no data found
stack:ORA-06512: at "DEV.ERR", line 43
ORA-06512: at "DEV.ERR", line 27
testProc2 error:ORA-01403: no data found
stack:ORA-06512: at "DEV.ERR", line 32
ORA-06512: at "DEV.ERR", line 16
testProc1 error:ORA-01403: no data found
stack:ORA-06512: at "DEV.ERR", line 21
ORA-06512: at "DEV.ERR", line 6
Видно, что функция
dbms_utility.format_error_backtrace выводит пакет, в котором сработало исключение и номер строки. Надо отметить, что в данном примере и строки вида dbms_output.put_line('testProc3 error:'//dbms_utility.format_error_stack); отлично формируют стек ошибки,
dbms_utility.format_error_backtrace лишь уточняет конкретную строку.
Пример 2. dbms_utility.format_error_backtrace в стартовой процедуре, во всех процедурах есть обработчики исключений
Рассмотрим другой пример.
На этот раз dbms_utility.format_error_backtrace будет в стартовой процедуре, из которой вызываются другие. В других процедурах будут обработчики исключений, но в них не будет вызоваdbms_utility.format_error_backtrace.
- create or replace package body Err as
-
- procedure testProc1 is
- begin
- dbms_output.put_line('testProc1');
- testProc2;
- exception
- when others then
- dbms_output.put_line('testProc1 error:'//dbms_utility.format_error_stack);
- dbms_output.put_line('stack:'//dbms_utility.format_error_backtrace);
- end;
-
- procedure testProc2 is
- begin
- dbms_output.put_line('testProc2');
- testProc3;
- exception
- when others then
- raise;
- end;
- procedure testProc3 is
- begin
- dbms_output.put_line('testProc3');
- testProc4;
- exception
- when others then
- raise;
- end;
-
- procedure testProc4 is
- begin
- dbms_output.put_line('testProc4');
- raise no_data_found;
- exception
- when others then
- raise;
- end;
-
- end;
Выполняем первую процедуру.
Получаем результат:
testProc1
testProc2
testProc3
testProc4
testProc1 error:ORA-01403: no data found
stack:ORA-06512: at "DEV.ERR", line 19
ORA-06512: at "DEV.ERR", line 6
Информации не очень-то много. Складывается впечатление, что ошибка возникла в 19 строке кода, хотя правильное место - строка 34. Причина в том, что
dbms_utility.format_error_backtrace показывает стек не с места фактического появления ошибки, а с мест ее последнего перехвата. В нашем случае это процедура proc2, строка 21.
Получается, в этом случае
dbms_utility.format_error_backtrace ни только не помогает, а еще и мешает, запутывает следы.
Пример 3. dbms_utility.format_error_backtrace в стартовой процедуре, в других процедурах нет обработчиков исключений
На этот раз все исключения обрабатываются только в одном месте - вызывающей функции, и только в ней используется dbms_utility.format_error_backtrace.
- create or replace package body Err as
-
- procedure testProc1 is
- begin
- dbms_output.put_line('testProc1');
- testProc2;
- exception
- when others then
- dbms_output.put_line('testProc1 error:'//dbms_utility.format_error_stack);
- dbms_output.put_line('stack:'//dbms_utility.format_error_backtrace);
- end;
-
- procedure testProc2 is
- begin
- dbms_output.put_line('testProc2');
- testProc3;
- end;
-
- procedure testProc3 is
- begin
- dbms_output.put_line('testProc3');
- testProc4;
- end;
-
- procedure testProc4 is
- begin
- dbms_output.put_line('testProc4');
- raise no_data_found;
- end;
-
- end;
Выполняем первую процедуру.
Получаем результат:
testProc1
testProc2
testProc3
testProc4
testProc1 error:ORA-01403: no data found
stack:ORA-06512: at "DEV.ERR", line 32
ORA-06512: at "DEV.ERR", line 25
ORA-06512: at "DEV.ERR", line 18
ORA-06512: at "DEV.ERR", line 7
На этот раз информации куда больше. По выводу функции
dbms_utility.format_error_backtrace можно точно отследить, что ошибка появилась в функции testProc4, строка 32, и какие процедуры выполнялись.
Из этих примеров можно вывести две основные тактики применения dbms_utility.format_error_backtrace.
Эту функцию надо вставлять в каждый обработчик исключений или обрабатывать все исключения в одной точке - стартовой процедуре(функции).
Ссылки по теме