Oracle стек ошибки

Статьи про Oracle

->

Программирование

dbms_utility.format_error_backtrace — отслеживание ошибок в pl/sql

v:1.0 03.12.2011

Петрелевич Сергей

Часто при обработке исключений в pl/sql разработчики ограничиваются использованием встроенной функции sqlerrm, однако в Oracle есть и другие интересные
средства для обработки ошибок. Одно из этих средств — функция dbms_utility.format_error_backtrace.

Функция dbms_utility.format_error_backtrace возвращает список вызовов функций и процедур от места генерации исключения до места его обработки.
Для рассмотрения работы dbms_utility.format_error_backtrace создадим тестовый пакет с процедурами, которые подобно матрешкам вызываются одна из другой.


create or replace package Err asprocedure testProc1;
 procedure testProc2;
 procedure testProc3;
 procedure testProc4;end;

Пример 1. dbms_utility.format_error_backtrace в каждом обработчике исключений

В первом примере функция dbms_utility.format_error_backtrace вставлена в обработчики исключений каждой процедуры.

  1. create or replace package body Err as
  2.  
  3. procedure testProc1 is
  4. begin
  5.  dbms_output.put_line('testProc1');
  6.  testProc2;
  7. exception
  8. when others then
  9.  dbms_output.put_line('testProc1 error:'||dbms_utility.format_error_stack);
  10.  dbms_output.put_line('stack:'||dbms_utility.format_error_backtrace);
  11. end;
  12.  
  13. procedure testProc2 is
  14. begin
  15.  dbms_output.put_line('testProc2');
  16.  testProc3;
  17. exception
  18. when others then
  19.  dbms_output.put_line('testProc2 error:'||dbms_utility.format_error_stack);
  20.  dbms_output.put_line('stack:'||dbms_utility.format_error_backtrace);
  21.  raise;
  22. end;
  23. procedure testProc3 is
  24. begin
  25.  dbms_output.put_line('testProc3');
  26.  testProc4;
  27. exception
  28. when others then
  29.  dbms_output.put_line('testProc3 error:'||dbms_utility.format_error_stack);
  30.  dbms_output.put_line('stack:'||dbms_utility.format_error_backtrace);
  31.  raise;
  32. end;
  33.  
  34. procedure testProc4 is
  35. begin
  36.  dbms_output.put_line('testProc4');
  37. raise no_data_found;
  38. exception
  39. when others then
  40.  dbms_output.put_line('testProc4 error:'||dbms_utility.format_error_stack);
  41.  dbms_output.put_line('stack:'||dbms_utility.format_error_backtrace);
  42.  raise;
  43. end;
  44.  
  45. 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.

  1. create or replace package body Err as
  2.  
  3. procedure testProc1 is
  4. begin
  5.  dbms_output.put_line('testProc1');
  6.  testProc2;
  7. exception
  8. when others then
  9.  dbms_output.put_line('testProc1 error:'||dbms_utility.format_error_stack);
  10.  dbms_output.put_line('stack:'||dbms_utility.format_error_backtrace);
  11. end;
  12.  
  13. procedure testProc2 is
  14. begin
  15.  dbms_output.put_line('testProc2');
  16.  testProc3;
  17. exception
  18. when others then
  19.  raise;
  20. end;
  21. procedure testProc3 is
  22. begin
  23.  dbms_output.put_line('testProc3');
  24.  testProc4;
  25. exception
  26. when others then
  27.  raise;
  28. end;
  29.  
  30. procedure testProc4 is
  31. begin
  32.  dbms_output.put_line('testProc4');
  33.  raise no_data_found;
  34. exception
  35. when others then
  36.  raise;
  37. end;
  38.  
  39. 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.

  1. create or replace package body Err as
  2.  
  3. procedure testProc1 is
  4. begin
  5.  dbms_output.put_line('testProc1');
  6.  testProc2;
  7. exception
  8.  when others then
  9.   dbms_output.put_line('testProc1 error:'||dbms_utility.format_error_stack);
  10.   dbms_output.put_line('stack:'||dbms_utility.format_error_backtrace);
  11. end;
  12.  
  13. procedure testProc2 is
  14. begin
  15.  dbms_output.put_line('testProc2');
  16.  testProc3;
  17. end;
  18.  
  19. procedure testProc3 is
  20. begin
  21.  dbms_output.put_line('testProc3'); 
  22.  testProc4; 
  23. end;
  24.  
  25. procedure testProc4 is
  26. begin
  27.  dbms_output.put_line('testProc4'); 
  28.  raise no_data_found;
  29. end;
  30.  
  31. 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.
Эту функцию надо вставлять в каждый обработчик исключений или обрабатывать все исключения в одной точке — стартовой процедуре(функции).

Метки:

PL/SQL  

Внимание.
Комментировать могут только зарегистрированные пользователи.
Возможно использование следующих HTML тегов: <a>, <b>, <i>, <br>.

PL/SQL 101: Three ways to get error message/stack in PL/SQL

The PL/SQL Challenge quiz for 10 September — 16 September 2016 explored the different ways you can obtain the error message / stack in PL/SQL. Note: an error stack is a sequence of multiple error messages that can occur when an exception is propagated and re-raised through several layers of nested blocks.

The three ways are:

  1. SQLERRM — The original, traditional and (oddly enough) not currently recommended function to get the current error message. Not recommended because the next two options avoid a problem which you are unlikely to run into: the error stack will be truncated at 512 bytes, and you might lose some error information.
  2. DBMS_UTILITY.FORMAT_ERROR_STACK — Returns the error message / stack, and will not truncate your string like SQLERRM will.
  3. UTL_CALL_STACK API — Added in Oracle Database 12c, the UTL_CALL_STACK package offers a comprehensive API into the execution call stack, the error stack and the error backtrace. 

Note: check out this LiveSQL script if you’d like to explore more of the nuances between SQLERRM and DBMS_UTILITY.FORMAT_ERROR_STACK.

Other helpful resources regarding error management in PL/SQL:

Nine Good to Knows for PL/SQL Error Management
PL/SQL Error Handling (doc)

Finally, here’s the code from our quiz that you can copy/paste into your editor to check out these alternatives.

CREATE OR REPLACE PROCEDURE plch_check_balance (
   balance_in IN NUMBER)
   AUTHID DEFINER
IS
BEGIN
   IF balance_in < 0
   THEN
      RAISE VALUE_ERROR;
   END IF;
EXCEPTION
   WHEN OTHERS
   THEN
      DBMS_OUTPUT.put_line (SQLERRM);
END;
/

BEGIN
   plch_check_balance (-1);
END;
/

CREATE OR REPLACE PROCEDURE plch_check_balance (
   balance_in IN NUMBER)
   AUTHID DEFINER
IS
BEGIN
   IF balance_in < 0
   THEN
      RAISE VALUE_ERROR;
   END IF;
EXCEPTION
   WHEN OTHERS
   THEN
      DBMS_OUTPUT.put_line (DBMS_UTILITY.format_error_stack);
END;
/

BEGIN
   plch_check_balance (-1);
END;
/

CREATE OR REPLACE PROCEDURE plch_check_balance (
   balance_in IN NUMBER)
   AUTHID DEFINER
IS
BEGIN
   IF balance_in < 0
   THEN
      RAISE VALUE_ERROR;
   END IF;
EXCEPTION
   WHEN OTHERS
   THEN
      DBMS_OUTPUT.put_line (   'ORA-'
         || TO_CHAR (UTL_CALL_STACK.error_number (1), 'fm00000')
         || ': '
         || UTL_CALL_STACK.error_msg (1));
END;
/

BEGIN
   plch_check_balance (-1);
END;
/

DROP PROCEDURE plch_check_balance
/

Popular posts from this blog

A Twitter follower recently asked for more information on user-defined types in the PL/SQL language, and I figured the best way to answer is to offer up this blog post. PL/SQL is a strongly-typed language . Before you can work with a variable or constant, it must be declared with a type (yes, PL/SQL also supports lots of implicit conversions from one type to another, but still, everything must be declared with a type). PL/SQL offers a wide array of pre-defined data types , both in the language natively (such as VARCHAR2, PLS_INTEGER, BOOLEAN, etc.) and in a variety of supplied packages (e.g., the NUMBER_TABLE collection type in the DBMS_SQL package). Data types in PL/SQL can be scalars, such as strings and numbers, or composite (consisting of one or more scalars), such as record types, collection types and object types. You can’t really declare your own «user-defined» scalars, though you can define subtypes  from those scalars, which can be very helpful from the p

 EVERY once in a while, a developer gets in touch with a question like this: I am confused about the exact difference between deterministic and result_cache. Do they have different application use cases? I have used deterministic feature in many functions which retrieve data from some lookup tables. Is it essential to replace these ‘deterministic’ key words with ‘result_cache’?  So I thought I’d write a post about the differences between these two features. But first, let’s make sure we all understand what it means for a function to be  deterministic. From Wikipedia : In computer science, a deterministic algorithm is an algorithm which, given a particular input, will always produce the same output, with the underlying machine always passing through the same sequence of states.  Another way of putting this is that a deterministic subprogram (procedure or function) has no side-effects. If you pass a certain set of arguments for the parameters, you will always get

We (the over-sized development team for the PL/SQL Challenge — myself and my son, Eli) have been busy creating a new website on top of the PLCH platform (tables and packages): The Oracle Dev Gym! In a few short months (and just a part time involvement by yours truly), we have leveraged Oracle Application Express 5 to create what I think is an elegant, easy-to-use site that our users will absolutely love.  We plan to initially make the Dev Gym available only for current users of PL/SQL Challenge, so we can get feedback from our loyal user base. We will make the necessary adjustments and then offer it for general availability later this year. Anyway, more on that as the date approaches (the date being June 27, the APEX Open Mic Night at Kscope16 , where I will present it to a packed room of APEX experts). What I want to talk about today are two features of APEX that are making me so happy these days: Regional Display Selector and Cards. Regional Display Sel

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

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

    В Oracle 10g возможности для работы со стеком ошибок были расширены. В пакете DBMS_UTILITY появились функции, которые позволяют получить больше информации о том, как ведёт себя программа в случае возникновения исключительной ситуации.

    Вот эти функции:

  • FORMAT_ERROR_BACKTRACE — позволяет получить строку из программы, в которой произошла исключительная  ситуация.
  • FORMAT_CALL_STACK — отображает на экране стэк программы на момент возникновения исключения.
  • FORMAT_ERROR_STACK позволяет получить “полное” сообщение об ошибке (дело в том, что привычная всем функция SQLERRM имеет ограничение на длину выводимого текста 512 символов, новая функция имеет ограничение в 2000 символов).

  Самый простой пример, который демонстрирует работу этих функций выглядит так:
   DECLARE
     local_exception EXCEPTION;
     FUNCTION nested_local_function
     RETURN BOOLEAN IS
       retval BOOLEAN := FALSE;
     BEGIN
       RAISE local_exception;
       RETURN retval;
     END;
     BEGIN
       IF nested_local_function THEN
         dbms_output.put_line(‘No raised exception’);
       END IF;
     EXCEPTION
       WHEN others THEN
         dbms_output.put_line(‘DBMS_UTILITY.FORMAT_CALL_STACK’);
         dbms_output.put_line(‘——————————‘);
         dbms_output.put_line(dbms_utility.format_call_stack);
         dbms_output.put_line(‘DBMS_UTILITY.FORMAT_ERROR_BACKTRACE’);
         dbms_output.put_line(‘————————————‘);
         dbms_output.put_line(dbms_utility.format_error_backtrace);
         dbms_output.put_line(‘DBMS_UTILITY.FORMAT_ERROR_STACK’);
         dbms_output.put_line(‘——————————-‘);
         dbms_output.put_line(dbms_utility.format_error_stack);
     END;

   Если его выполнить, то получим:
DBMS_UTILITY.FORMAT_CALL_STACK
——————————
—— PL/SQL Call Stack ——
object    line     object
handle    number   name
20909240      18   anonymous block
DBMS_UTILITY.FORMAT_ERROR_BACKTRACE
————————————
ORA-06512: at line 7
ORA-06512: at line 11
DBMS_UTILITY.FORMAT_ERROR_STACK
——————————-
ORA-06510: PL/SQL: unhandled user-defined exception

Скорее всего, самой востребованной функцией будет — DBMS_UTILITY.FORMAT_ERROR_BACKTRACE,  рекомендую ознакомиться с более интересным примеров стека ошибок на сайте документации по Oracle 10g: http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_util.htm#i1003874

Often, it’s a head ache for me to
debug the unhandled exception in my programs. Now, I have a pill for it. It’s DBMS_UTILITY.FORMAT_ERROR_STACK
and DBMS_UTILITY.FORMAT_ERROR_BACKTRACE

Let’s see how it’s useful for PLSQL
developers. 

Test Package:

CREATE OR replace PACKAGE test_oracle

IS

  PROCEDURE main;

END test_oracle;

/

CREATE OR replace PACKAGE BODY test_oracle

IS

  PROCEDURE Fun5

  IS

    ln_dummy_number NUMBER;

  BEGIN

      ln_dummy_number := 1 / 0; — Kept to raise an exception

  END;

  PROCEDURE Fun4

  IS

  BEGIN

      fun5;

  END;

  PROCEDURE Fun3

  IS

  BEGIN

      fun4;

  END;

  PROCEDURE Fun2

  IS

  BEGIN

      fun3;

  END;

  PROCEDURE Main

  IS

  BEGIN

      fun2;

  EXCEPTION

    WHEN OTHERS THEN

              
dbms_output.Put_line(
‘Format error
stack:’

                                   
||dbms_utility.Format_error_stack());

              
dbms_output.Put_line(
‘Print error
stack:’

                                   
||Chr(
10)

                                   
||dbms_utility.Format_error_backtrace());

  END;

END test_oracle;

/

show errors;

Testing:

Now, I know the exact line which
caused the error. It mentioned standard oracle utilities gaves the complete
back trace. It’s a nice utility!!

Hopefully it helps!!

Do you think this Article is useful?

Disclaimer

The ideas, thoughts and concepts expressed here are my own. They, in no way reflect those of my employer or any other organization/client that I am associated. The articles presented doesn’t imply to any particular organization or client and are meant only for knowledge Sharing purpose. The articles can’t be reproduced or copied without the Owner’s knowledge or permission.

Понравилась статья? Поделить с друзьями:
  • Oracle посмотреть ошибки
  • Oracle перехват ошибок
  • Oracle ошибка pls 00103 encountered the symbol
  • Oracle ошибка ora 06550
  • Oracle ошибка ora 06502