Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Oracle Новый топик    Ответить
 Возможно ли получить текст сообщения об ошибке?  [new]
rvk
Member

Откуда:
Сообщений: 60
Всем доброго времени суток.
Имеется ввиду, если вылетела процедура, то получить программным путем сообщение (в какую-нибудь переменную при обработке, допустим, EXCEPTION WHEN OTHERS). Если использовать SQLCODE c SQLERRM - выдается стандартное описание, а не конкретное для данного случая.
Спасибо
18 июн 06, 00:24    [2783752]     Ответить | Цитировать Сообщить модератору
 Re: Возможно ли получить текст сообщения об ошибке?  [new]
dmidek
Member

Откуда: Киев - Дортмунд
Сообщений: 116274
Подозрительная терминология, но посмотрите в сторону

DBMS_UTILITY.FORMAT_ERROR_STACK
18 июн 06, 00:33    [2783756]     Ответить | Цитировать Сообщить модератору
 Re: Возможно ли получить текст сообщения об ошибке?  [new]
andrey_anonymous
Member

Откуда: Москва
Сообщений: 18371
dmidek
Подозрительная терминология, но посмотрите в сторону
DBMS_UTILITY.FORMAT_ERROR_STACK

Думаю, скорее одно из
declare
  MyErrorCase1 exception;
  /*pragma exception_init(MyErrorCase1, -20100);*/
  MyErrorCase2 exception;
  /*pragma exception_init(MyErrorCase2, -20101);*/
begin
 ...
  RAISE MyErrorCase1;
 ...
    select ... into...; 
 ...
  if ... then
    RAISE_APPLICATION_ERROR(-20200, 'MyErrorText');
  end if;
exception
  when MyErrorCase1 then...
  when no_data_found then
    if ... then RAISE MyErrorCase2; end if;
  when others then
    RAISE;
end;
18 июн 06, 00:59    [2783776]     Ответить | Цитировать Сообщить модератору
 Re: Возможно ли получить текст сообщения об ошибке?  [new]
dmidek
Member

Откуда: Киев - Дортмунд
Сообщений: 116274
andrey_anonymous
dmidek
Подозрительная терминология, но посмотрите в сторону
DBMS_UTILITY.FORMAT_ERROR_STACK

Думаю, скорее одно из
declare
  MyErrorCase1 exception;
  /*pragma exception_init(MyErrorCase1, -20100);*/
  MyErrorCase2 exception;
  /*pragma exception_init(MyErrorCase2, -20101);*/
begin
 ...
  RAISE MyErrorCase1;
 ...
    select ... into...; 
 ...
  if ... then
    RAISE_APPLICATION_ERROR(-20200, 'MyErrorText');
  end if;
exception
  when MyErrorCase1 then...
  when no_data_found then
    if ... then RAISE MyErrorCase2; end if;
  when others then
    RAISE;
end;

Угу, теперь мне тоже так кажется
18 июн 06, 01:09    [2783783]     Ответить | Цитировать Сообщить модератору
 Re: Возможно ли получить текст сообщения об ошибке?  [new]
rvk
Member

Откуда:
Сообщений: 60
andrey_anonymous

Думаю, скорее одно из

Не совсем то. Не надо определять свои исключения. Скорее так
declare
p1 date;
text_er varchar2(500);
kod_er number;
...
BEGIN
....
begin
 ...  
    select ... into...; 
 p1:=...;

exception
  when others then
kod_er:=SQLCODE;
    Здесь выяснить какое было исключение и его содержание получить в text_er
If kod_er=...  and instr(text_err,'...')>0 then
...
End if;
end;

...
END;
18 июн 06, 20:32    [2784445]     Ответить | Цитировать Сообщить модератору
 Re: Возможно ли получить текст сообщения об ошибке?  [new]
andrey_anonymous
Member

Откуда: Москва
Сообщений: 18371
rvk
Не совсем то. Не надо определять свои исключения. Скорее так
exception
  when others then
kod_er:=SQLCODE;
    Здесь выяснить какое было исключение и его содержание получить в text_er
If kod_er=...  and instr(text_err,'...')>0 then

Ничего не понял. Что означает "Здесь выяснить какое было исключение и его содержание получить в text_er", чем не устраивает sqlcode и sqlerrm?
18 июн 06, 22:36    [2784584]     Ответить | Цитировать Сообщить модератору
 Re: Возможно ли получить текст сообщения об ошибке?  [new]
dmidek
Member

Откуда: Киев - Дортмунд
Сообщений: 116274
Не скажу , что я в восторге от этой идеи, но Вы можете специфицировать ошибку, обернув проблемные операторы в блоки.
Пример

create or replace procedure prc_test
(pi_empno IN NUMBER,
 pi_deptno IN NUMBER,
 po_ename OUT VARCHAR2,
 po_dname OUT VARCHAR2,
 po_err OUT NOCOPY VARCHAR2 
 )
IS
BEGIN
  BEGIN
    SELECT ename INTO po_ename
    FROM emp
    WHERE empno = pi_empno;
  EXCEPTION
    WHEN OTHERS
    THEN 
      po_err := sqlerrm||' in EMP for EMPNO = '||pi_empno;
      RAISE;
  END; 
  BEGIN
    SELECT dname INTO po_dname
    FROM dept
    WHERE deptno = pi_deptno;
  EXCEPTION
    WHEN OTHERS
    THEN 
      po_err := sqlerrm||' in DEPT for DEPTNO = '||pi_deptno;
      RAISE;
  END; 
END;

declare
 po_ename VARCHAR2(30);
 po_dname VARCHAR2(30);
 po_err VARCHAR2(2000); 
begin
prc_test(234, 22, po_ename, po_dname, po_err);
exception
WHEN OTHERS
THEN
dbms_output.put_line(po_err);
end;
/
ORA-01403: no data found in EMP for EMPNO = 234

Конечно, кропотливая работа, но если надо, то можно :)
Замечу кстати, что не все sqlerrm так "неконкретны" как no_data_found.
DUP_VAL_ON_INDEX например указывает , какой именно констрейнт "вылетел"...
18 июн 06, 22:38    [2784587]     Ответить | Цитировать Сообщить модератору
 Re: Возможно ли получить текст сообщения об ошибке?  [new]
andrey_anonymous
Member

Откуда: Москва
Сообщений: 18371
dmidek
 po_err := sqlerrm||' in EMP for EMPNO = '||pi_empno;

А теперь поставьте NLS_LANG=RUSSIAN_RUSSIA и посмотрите на то же сообщение ;)
Не следует размещать тексты сообщений в исходниках - это сильно вредит локализации.
18 июн 06, 22:47    [2784596]     Ответить | Цитировать Сообщить модератору
 Re: Возможно ли получить текст сообщения об ошибке?  [new]
dmidek
Member

Откуда: Киев - Дортмунд
Сообщений: 116274
andrey_anonymous
dmidek
 po_err := sqlerrm||' in EMP for EMPNO = '||pi_empno;

А теперь поставьте NLS_LANG=RUSSIAN_RUSSIA и посмотрите на то же сообщение ;)

Все нормально.
Good bye Америка

Понятно, что это только каркас.
Ничто не мешает написать EMP : EMPNO = '||pi_empno или
sqlcode||' in EMP for EMPNO = '||pi_empno
Это пусть автор решает, КАК и ГДЕ это делать.
Я представляю себе , что вопрос родился из сложностей с локализацией конкретных ошибок в тексте процедуры. Тогда этот метод ИМХО имеет право на существование, такой своеобразный трейс, можно даже номер строки писать (хотя с актуализацией кода запаришься :) ).
Повторюсь, что я не в восторге от самой идеи.
18 июн 06, 23:21    [2784653]     Ответить | Цитировать Сообщить модератору
 Re: Возможно ли получить текст сообщения об ошибке?  [new]
andrey_anonymous
Member

Откуда: Москва
Сообщений: 18371
dmidek
Повторюсь, что я не в восторге от самой идеи.

Если хочется строчку - то я поступаю гораздо проще.
Объявляю целочисленную переменную-"l_locator" и после каждого statement присваиваю ей значения.
В секции exception when others логирую вместе с номером исключения и sqlerrm.
В прочих обработчиках на основании данного значения классифицирую бизнес-кейс и трансформирую в соответствующий user error.
18 июн 06, 23:26    [2784659]     Ответить | Цитировать Сообщить модератору
 Re: Возможно ли получить текст сообщения об ошибке?  [new]
dmidek
Member

Откуда: Киев - Дортмунд
Сообщений: 116274
andrey_anonymous
dmidek
Повторюсь, что я не в восторге от самой идеи.

Если хочется строчку - то я поступаю гораздо проще.
Объявляю целочисленную переменную-"l_locator" и после каждого statement присваиваю ей значения.
В секции exception when others логирую вместе с номером исключения и sqlerrm.
В прочих обработчиках на основании данного значения классифицирую бизнес-кейс и трансформирую в соответствующий user error.

ИМХО
Кстати "иделогически" похоже.
Но тоже кропотливое дело.
В "моем" варианте я ловлю только место, а в Вашем Вы ловите место + sqlcode.
То есть для процедуры prc_test Вы должны подготовить сообщения для
1. NO_DATA_FOUND для EMP
2. NO_DATA_FOUND для DEPT
3. TOO_MANY_ROWS для EMP
4. TOO_MANY_ROWS для DEPT
5......
6......

create or replace procedure prc_test_2
(pi_empno IN NUMBER,
 pi_deptno IN NUMBER,
 po_ename OUT VARCHAR2,
 po_dname OUT VARCHAR2,
 po_locator OUT NOCOPY NUMBER 
 po_sqlcode OUT NOCOPY NUMBER 
 )
IS
BEGIN
  po_locator := 1;
  BEGIN
    po_locator := po_locator + 1;
    SELECT ename INTO po_ename
    FROM emp
    WHERE empno = pi_empno;
  EXCEPTION
    WHEN OTHERS
    THEN 
     po_err := sqlcode;
     RAISE;
  END; 
  BEGIN
    po_locator := po_locator + 1;
    SELECT dname INTO po_dname
    FROM dept
    WHERE deptno = pi_deptno;
  EXCEPTION
    WHEN OTHERS
    THEN 
      po_err := sqlcode;
      RAISE;
  END; 
END;

declare
 po_ename VARCHAR2(30);
 po_dname VARCHAR2(30);
 po_locator NUMBER; 
 po_sqlcode NUMBER; 
begin
prc_test(234, 22, po_ename, po_dname, po_sqlcode, po_locator);
exception
WHEN OTHERS
THEN
 -- огромный CASE по po_sqlcode + po_locator
 -- или не такой большрй по po_locator ?
end;
Нет, пока писал, еще больше убедился, что это не работает.
Как такой CASE подготовить ?
Или Вы имеете в виду CASE только по po_locator ?
Тогда наши методы ИМХО очень близкие родственники.
18 июн 06, 23:58    [2784691]     Ответить | Цитировать Сообщить модератору
 Re: Возможно ли получить текст сообщения об ошибке?  [new]
rvk
Member

Откуда:
Сообщений: 60
Спасибо за обсуждение. Но речь не о том - про уловитель ошибок на конкретной строке - сама делаю как andrey_anonymous . Но это не всегда нужно использовать.
Если процедура выполняется в SQL*Plus -все легоко, ошибки выводятся spool-файл. А если процедура выполняется в Forms, то тогда тоже хотелось бы вывести текст ошибки в протокол, полный текст с номером строки и т.д.
SQLERRM - выдает характеристику кода.
19 июн 06, 00:36    [2784714]     Ответить | Цитировать Сообщить модератору
 Re: Возможно ли получить текст сообщения об ошибке?  [new]
dmidek
Member

Откуда: Киев - Дортмунд
Сообщений: 116274
rvk
Спасибо за обсуждение. Но речь не о том - про уловитель ошибок на конкретной строке - сама делаю как andrey_anonymous . Но это не всегда нужно использовать.
Если процедура выполняется в SQL*Plus -все легоко, ошибки выводятся spool-файл. А если процедура выполняется в Forms, то тогда тоже хотелось бы вывести текст ошибки в протокол, полный текст с номером строки и т.д.
SQLERRM - выдает характеристику кода.

А Вы все таки DBMS_UTILITY.FORMAT_ERROR_STACK по ссылке смотрели ?
19 июн 06, 00:57    [2784732]     Ответить | Цитировать Сообщить модератору
 Re: Возможно ли получить текст сообщения об ошибке?  [new]
mcureenab
Member

Откуда: Murmansk
Сообщений: 5928
rvk
Спасибо за обсуждение. Но речь не о том - про уловитель ошибок на конкретной строке - сама делаю как andrey_anonymous . Но это не всегда нужно использовать.
Если процедура выполняется в SQL*Plus -все легоко, ошибки выводятся spool-файл. А если процедура выполняется в Forms, то тогда тоже хотелось бы вывести текст ошибки в протокол, полный текст с номером строки и т.д.
SQLERRM - выдает характеристику кода.


Не уверен, что дело в этом, однако. Forms работает с ораклом через интерфейс SQLLIB, а SQL*Plus через OCI. SQLLIB передаёт исключение в PL/SQL, который обрабатывает его как умеет. Т.е. в стеке ошибок и функцией SQLERRM видно только то место, где ошибка поймана, а не там где она поднялась. Функция DBMS_UTILITY.FORMAT_ERROR_STACK тут ничего не добавляет. В Оракл 10g появилась функция DBMS_UTILITY.FORMAT_ERROR_BACKTRACE. Судя по примеру в документации, это то что нужно. Во всяком случае ORA-06512: там есть в изобилии.
19 июн 06, 11:10    [2785650]     Ответить | Цитировать Сообщить модератору
 Re: Возможно ли получить текст сообщения об ошибке?  [new]
rvk
Member

Откуда:
Сообщений: 60
Спасибо всем. DBMS_UTILITY.FORMAT_ERROR_STACK+ DBMS_UTILITY.FORMAT_ERROR_BACKTRACE - то что нужно.
21 июн 06, 00:57    [2794712]     Ответить | Цитировать Сообщить модератору
Все форумы / Oracle Ответить