Is there a way to get the line number where an exception was thrown?
Asked Answered
R

6

34

Im working on a pl-sql script, in which I have about 10 TO_CHAR conversions.

One of them is throwing an

ORA-06502: PL/SQL: numeric or value error: character string buffer too small

exception.

Currently, im logging the message with this piece of code

EXCEPTION
  WHEN OTHERS THEN
    DBMS_OUTPUT.put_line('Exception message is '||SQLERRM(sqlcode));
    ROLLBACK;

I'd like to add (mostly for debugging purposes) the line where the exception is thrown, in order to receive a message in the form of

ORA-06502: PL/SQL: numeric or value error: character string buffer too small (at line x)

Is there an easy way to do this?

Require answered 19/10, 2009 at 15:10 Comment(0)
C
27

You need 10g to use

DBMS_OUTPUT.put_line('Error in '|| $$plsql_unit || ' at ' || $$plsql_line);

also look into using

DBMS_UTILITY.format_error_backtrace

there is an article in Oracle Magazine from april '05 by Steven Feuerstein:

http://www.oracle.com/technetwork/issue-archive/2005/05-mar/o25plsql-093886.html

Cheers, niels

Clawson answered 19/10, 2009 at 15:25 Comment(0)
C
35

The answers have mentioned both, $$PLSQL_LINE & DBMS_UTILITY.FORMAT_ERROR_BACKTRACE. But I would like to add a bit about the difference between them:

  1. Predefined Inquiry Directives $$PLSQL_LINE & $$PLSQL_UNIT
    PLSQL_LINE predefined inquiry directive is a PLS_INTEGER literal value indicating the line number reference to $$PLSQL_LINE in the current program unit.
    From its definition, PLSQL_LINE is not suitable for exceptions logging because it will provide the line number of the exception, rather than the line number of the error occurred itself. This makes it difficult to detect the error location especially with big program units, unless you wrap every statement with exception handler as Jeffrey answer's stated.
    However, the good thing about PLSQL_LINE, it provides the number without the need of any extraction, or string parsing. Hence, it could be more suitable for other logging purposes.
  2. DBMS_UTILITY.FORMAT_ERROR_BACKTRACE
    This procedure displays the call stack at the point where an exception was raised, even if the procedure is called from an exception handler in an outer scope.
    The advantage of using this procedure, is that it provides the exact line number in the program using where the error occurs, and not where the procedure call appears However, the procedure returns a string like ORA-XXXXX: at "<program_unit_name>", line xx. So if you are interested in extracting the line number itself, for whatever logging purpose you want, you will need parse the string.

Finally, to make the difference clear, below are two procedures, with the same content. You can run them and notice the output difference

CREATE OR REPLACE PROCEDURE proc_plsql_line
    IS
    BEGIN
       RAISE VALUE_ERROR;
    EXCEPTION
       WHEN VALUE_ERROR
       THEN
          DBMS_OUTPUT.put_line ( 'Error raised in: '|| $$plsql_unit ||' at line ' || $$plsql_line || ' - '||sqlerrm);
   END;
/

And

CREATE OR REPLACE PROCEDURE proc_backtrace
    IS
    BEGIN
       RAISE VALUE_ERROR;
    EXCEPTION
       WHEN VALUE_ERROR
       THEN
          DBMS_OUTPUT.put_line ( 'Error raised: '|| DBMS_UTILITY.FORMAT_ERROR_BACKTRACE || ' - '||sqlerrm);
   END;
/

Execution:

exec proc_plsql_line;

Error raised in: PROC_PLSQL_LINE at line 8 - ORA-06502: PL/SQL: numeric or value error


exec proc_backtrace;

Error raised: ORA-06512: at "PROC_BACKTRACE", line 4 - ORA-06502: PL/SQL: numeric or value error
Corinacorine answered 16/6, 2016 at 2:57 Comment(2)
this should be the "ACCEPTED" answer !Millepede
My only gripe is to count with error, which was described in article, which is shared many times here: "Notice that I call DBMS_UTILITY.FORMAT_ERROR_STACK , because it will return the full error message. Of course, DBMS_OUTPUT.PUT_LINE will raise an exception if you pass it a string that is longer than 255 characters"Sedimentary
C
27

You need 10g to use

DBMS_OUTPUT.put_line('Error in '|| $$plsql_unit || ' at ' || $$plsql_line);

also look into using

DBMS_UTILITY.format_error_backtrace

there is an article in Oracle Magazine from april '05 by Steven Feuerstein:

http://www.oracle.com/technetwork/issue-archive/2005/05-mar/o25plsql-093886.html

Cheers, niels

Clawson answered 19/10, 2009 at 15:25 Comment(0)
M
8

The DBMS_UTILITY.format_error_backtrace statement will give you the line number

begin
select 1/0 from dual;
exception 
  when others then 
  dbms_output.put_line('ERROR_STACK: ' || DBMS_UTILITY.FORMAT_ERROR_STACK);
  dbms_output.put_line('ERROR_BACKTRACE: ' || DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);
end;
Manageable answered 6/9, 2017 at 8:19 Comment(0)
T
2

you need 10g or above. Check DBMS_UTILITY.FORMAT_ERROR_BACKTRACE.

http://www.oracle.com/technetwork/issue-archive/2005/05-mar/o25plsql-093886.html

Temptress answered 19/10, 2009 at 15:11 Comment(0)
T
0

You could put your exception handler around every statement.

Transgress answered 20/10, 2009 at 8:30 Comment(0)
Q
0

EXCEPTION
  WHEN OTHERS
  THEN
   p_err_msg := SUBSTR((SQLCODE || ' ' || SQLERRM || ' ' || dbms_utility.format_error_backtrace()),    1, 2000);

Quinquepartite answered 13/6, 2022 at 19:48 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Danaides

© 2022 - 2024 — McMap. All rights reserved.