Как вывести весь стек перехватываемого исключения в EXCEPTION?

Предположим такой код:

declare
  PROCEDURE p1 
  AS
  BEGIN
    RAISE no_data_found;
  END; 
  
  PROCEDURE p2
  AS
  BEGIN
    RAISE no_data_found;
  END;
  
  PROCEDURE p
  AS
  BEGIN
    p1;
    p2;
  EXCEPTION 
    WHEN OTHERS /*no_data_found*/ THEN
      RAISE;
  END;
  
BEGIN
  p;
end;

При выполнении его получаю ошибку :

ORA-01403: no data found
ORA-06512: at line 21
ORA-06512: at line 25

По такому стеку не понятно, в какой именно процедуре возникло исключение, так как оно перехватывается в процедуре p.

Вопрос, как элегантно реализовать EXCEPTION, чтобы при получении ошибки, выводился полный стек?

Для того, чтобы быстро понять в какой именно из вложенных процедур, в данном случае p1 или p2, вызвался RAISE. Вложенность процедур может быть любой.


Ответы (1 шт):

Автор решения: 0xdb

Возможно стоит устаревший клиент. У меня получается полный стек исключения:

SQL> run
  1  declare
  2    PROCEDURE p1
  3    AS
  4    BEGIN
  5      RAISE no_data_found;
  6    END;
  7
  8    PROCEDURE p2
  9    AS
 10    BEGIN
 11      RAISE no_data_found;
 12    END;
 13
 14    PROCEDURE p
 15    AS
 16    BEGIN
 17      p1;
 18      p2;
 19    EXCEPTION
 20      WHEN OTHERS /*no_data_found*/ THEN
 21        RAISE;
 22    END;
 23
 24  BEGIN
 25    p;
 26* end;
declare
*
ERROR at line 1:
ORA-01403: no data found
ORA-06512: at line 21
ORA-06512: at line 5
ORA-06512: at line 17
ORA-06512: at line 25

Видно, что при вызове процедуры P1 в 17 строке произошло исключение в 5 строке.

Если интереснна обработка исключения внутри блока EXCEPTION, то следует воспользоваться функциями пакета DBMS_UTILITY, или более нового UTL_CALL_STACK.

Вот простой пример:

create or replace package pack as
    procedure p1;
    procedure p2;
    procedure p;
end;
/
create or replace package body pack as
    procedure p1 as
    begin raise no_data_found; -- 3 строка
    end; 
    procedure p2 as
    begin raise no_data_found;
    end;
    procedure p as 
    begin
        p1; -- 10 строка
        p2;
    exception when others then
        dbms_output.put_line (sqlerrm||chr(10)||dbms_utility.format_error_backtrace ());
    end; 
end pack;
/

Даст обратный стек исключения, ошибка в 3 строке при вызове процедуры p1 в 10 строке:

begin 
    pack.p;
end;
/
ORA-01403: no data found
ORA-06512: at "ME.PACK", line 3
ORA-06512: at "ME.PACK", line 10
→ Ссылка