понедельник, 25 октября 2010 г.

Oracle PL/SQL: Обработка ошибок

Создадим пакет и в нем тестовую процедуру, которая будет генерировать исключение (спецификацию пакета я опускаю, т.к. она очевидна):

  create or replace package body VTESTPKG is
  
    procedure Test1
    is
    begin
      raise NO_DATA_FOUND;
    end Test1;
  
  end VTESTPKG;

Теперь, вызовем VTESTPKG.Test1 и запишем текст исключения в output:

  begin
    VTESTPKG.Test1;
  exception
    when others then
      dbms_output.put_line(sqlerrm);
  end;

Результат будет выглядеть так:

ORA-01403: данные не найдены

Код и текст ошибки в SQLERRM есть, однако нам бы очень хотелось увидеть место возникновения ошибки - в идеале номер строки и стек вызовов. Ниже приведен код функции ERR_WHENCE, которая возвращает место возникновения ошибки, и стандартный обработчик ошибок RaiseError, который я использую при обработке всех ошибок в моем коде на PL/SQL.

  function ERR_WHENCE return varchar2
  is
    l_back_trace varchar2(4096) default DBMS_UTILITY.FORMAT_ERROR_BACKTRACE;
    l_pos integer;
  begin
    if substr(l_back_trace, length(l_back_trace), 1) = chr(10)
    then
      l_back_trace := substr(l_back_trace, 1, length(l_back_trace)-1);
    end if;
    l_pos := instr(l_back_trace, chr(10), -1);
    if l_pos > 0 then
      l_back_trace := substr(l_back_trace, l_pos+1);
    end if;
    return l_back_trace || chr(10);
  end ERR_WHENCE;
  
  procedure RaiseError(
    error_source varchar2,
    error_message varchar2 default ERR_WHENCE || sqlerrm,
    error_code number default -20001
  )
  is
  begin    
    if not error_source is null then
      raise_application_error(
        error_code, 'error in ' || error_source || chr(10) || error_message);
    else
      raise_application_error(
        error_code, error_message);
    end if;
  end RaiseError;

Для демонстрации использования создадим процедуры Test2 и Test3, в которых используется обработчик ошибок RaiseError:

  procedure Test2
  is
  begin
    raise NO_DATA_FOUND;
  exception
    when others then
      RaiseError('Test2');
  end Test2;

  procedure Test3
  is
  begin    
    Test2;
  exception
    when others then
      RaiseError('Test3');
  end Test3;

Результат (в SQLERRM) вызова Test2:

ORA-20001: error in Test2
ORA-06512: на  "AIS.VTESTPKG", line 44
ORA-01403: данные не найдены

Результат (в SQLERRM) вызова Test3:

ORA-20001: error in Test3
ORA-06512: на  "AIS.VTESTPKG", line 53
ORA-20001: error in Test2
ORA-06512: на  "AIS.VTESTPKG", line 44
ORA-01403: данные не найдены

===
Перепечатка материалов блога разрешается с обязательной ссылкой на blog.coolsoftware.ru

Комментариев нет:

Отправить комментарий