Sign Up

Sign Up to our social questions and Answers to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In


Have an account? Sign In Now

Sign In

Login to our social questions & Answers to ask questions, answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Sorry, you do not have permission to add post.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Oraask Logo Oraask Logo
Sign InSign Up

Oraask

  • Write
    • Add A New Post
    • Ask A Question

Oraask Navigation

Search
Ask A Question

Mobile menu

Close
  • Categories
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Dev Tools
    • Online Compiler
    • Base64 Converter
  • Wiki
    • SQL Tutorials
    • Java Tutorials
    • Python Tutorials
    • JavaScript Tutorials

Stephan Borsodi

Ask Stephan Borsodi
25 Visits
0 Followers
0 Questions
Home/ Stephan Borsodi/Answers
  • About
  • Questions
  • Answers
  • Best Answers
  • Posts
  • Polls
  • Asked Questions
  • Comments
  1. Asked: July 31, 2016In: PL/SQL

    How to Raise User-Defined Exception and display Custom SQLERRM ?

    Stephan Borsodi
    Stephan Borsodi
    Added an answer on August 29, 2016 at 7:01 am

    raise_application_error() is a good feature ... but go one step ahead:how do you identify the location of an exception in a pl/sql object withhundreds or thousands of lines of code and what was an eventual data constellationwhen the exception occurred?I collect as many informations as I can, for insRead more

    raise_application_error() is a good feature … but go one step ahead:
    how do you identify the location of an exception in a pl/sql object with
    hundreds or thousands of lines of code and what was an eventual data constellation
    when the exception occurred?
    I collect as many informations as I can, for instance the content of the
    oracle stack and extra infos – I call them secondary messages – in the code
    which I normally log for later analysis.
    I am aware that it means extra effort when coding but in my experience
    it pays out: I was much quicker in identifying problems and defects in my code.
    Here’s a simple test case to demonstrate the idea:
    —
    — [A] create a function which returns the informations
    — from the oracle error stack. Actually, this function
    — should be integrated into a utility or log packages
    —
    create or replace
    function f_cre_err_infos(i_len in pls_integer default 4000)
    return varchar2
    is
    c_err constant varchar2(11) := ‘[ERROR]: ‘;
    v_len pls_integer := i_len; — limits output length of error output msg
    /*
    ||——————————————————————-
    || dbms_utility.format_call_stack:
    || Format the current call stack. This can be used an any stored
    || procedure or trigger to access the call stack. This can be
    || useful for debugging.
    ||——————————————————————-
    */
    v_call_stk varchar2(2000); — call stack var. / <= 2000 bytes.
    /*
    ||——————————————————————-
    || dbms_utility.format_error_stack:
    || Format the current error stack. This can be used in exception
    || handlers to look at the full error stack.
    ||——————————————————————-
    */
    v_err_stk varchar2(2000); — Returns the error stack. <= 2000 bytes.
    /*
    ||——————————————————————-
    || dbms_utility.format_error_backtrace:
    || Format the backtrace from the point of the current error
    || to the exception handler where the error has been caught.
    || NULL string is returned if no error is currently being
    || handled.
    ||——————————————————————-
    */
    v_bck_trc varchar2(2000);
    begin
    v_err_stk := dbms_utility.format_error_stack;
    v_call_stk := dbms_utility.format_call_stack;
    /*
    ||————————————————————————
    || We replace/shorten following oracle error code with just the string
    || ‘backtrace’ (otherwise, it might be misleading; see also
    || http://download.oracle.com/docs/cd/B19306_01/server.102/b14219/e4100.htm#sthref2006):
    ||
    || ORA-06512: at stringline string
    || Cause: Backtrace message as the stack is unwound
    || by unhandled exceptions.
    || Action: Fix the problem causing the exception or write an exception
    || handler for this condition. Or you may need to contact your
    || application administrator or DBA.
    ||————————————————————————
    */
    v_bck_trc := regexp_replace(dbms_utility.format_error_backtrace, ‘ORA-06512: ‘, ‘backtrace: ‘);
    /*
    ||————————————————————————
    || A minimum length of 256 characters for the error message is guaranteed
    || (and a theoretical maximum of 32768 as well)
    ||————————————————————————
    */
    v_len := case when coalesce(v_len,1) < 256 then 256
    when v_len > 32768 then 32768
    else v_len
    end;
    return substr(
    c_err || v_err_stk ||
    c_err || v_bck_trc ||
    c_err || v_call_stk, 1, v_len);
    end f_cre_err_infos;
    /
    —
    — [B] I create a simple test case with 2 tables; my test procedure
    — will transfer data from T1 to T2, record 5 fires the exception
    —
    create table T1 (id number(5,0), txt varchar2(10));
    create table T2 (id number(5,0) not null,
    txt varchar2(10) not null,
    constraint T2_PK primary key(id) using index)
    ;
    truncate table T1;
    truncate table T2;
    insert into T1 values (1, ‘A text 1’);
    insert into T1 values (2, ‘2nd text’);
    insert into T1 values (3, ‘Text 2’);
    insert into T1 values (4, ‘Text 3’);
    insert into T1 values (4, ‘Text 4’);
    insert into T1 values (5, null);
    commit;
    select t.*, rowid from T1 t order by id;
    —
    — [C] create the test procedure; see comments in exception handler
    —
    create or replace procedure p_tst_xfer
    is
    c_module constant varchar2(30) := ‘p_tst_xfer’;
    v_msg varchar2(230);
    cursor sel_cur is
    select ID,
    TXT
    from T1;
    rec sel_cur%rowtype;
    begin
    v_msg := ‘[1] opening sel_cur’;
    open sel_cur;
    loop
    v_msg := ‘[2] fetching from sel_cur’;
    fetch sel_cur into rec;
    exit when sel_cur%notfound;

    v_msg := ‘[3] inserting into T2: ID=’|| rec.ID || ‘, TXT=’ || nvl(rec.TXT, ‘NULL’);
    insert into T2 (ID, TXT)
    values (rec.ID, rec.TXT);
    end loop;
    v_msg := ‘[4] closing sel_cur cursor’;
    close sel_cur;
    exception
    when OTHERS then
    if sel_cur%isopen then
    close sel_cur;
    end if;
    — ————————————————
    — For demo purposes: display oracle error stack
    — and the secondary infos. Better: log all infos
    — and use ‘raise;’ as the last statement
    — ————————————————
    dbms_output.put_line(f_cre_err_infos);
    dbms_output.put_line(‘[ERROR]: module ‘ || c_module);
    dbms_output.put_line(‘[ERROR]: while ‘ || v_msg);
    end p_tst_xfer;
    /
    show errors

    — in sqlplus
    set serverout on size unlimited format wrapped
    set trimout on trimspool on
    set linesize 500
    begin
    p_tst_xfer;
    end;
    /
    —
    — The output looks like this:
    —
    [ERROR]: ORA-00001: unique constraint (SCOTT.T2_PK) violated
    [ERROR]: backtrace: at “SCOTT.P_TST_XFER”, line 20
    [ERROR]: —– PL/SQL Call Stack —–
    object line object
    handle number name
    000007FFB5B48C38 37 function SCOTT.F_CRE_ERR_INFOS
    000007FFB5AA4328 35 procedure SCOTT.P_TST_XFER
    000007FFB5A70230 2 anonymous block
    [ERROR]: module p_tst_xfer
    [ERROR]: while [3] inserting into T2: ID=4, TXT=Text 4
    PL/SQL procedure successfully completed.
    What we can see:
    * The module/program name and the location/line where the exception was fired
    * The secondary message shows the ‘data constellation’ ([3] inserting into T2: ID=4, TXT=Text 4)
    Now, I can debug my code with following sql (I put these lines in a script, e.g. srcproc.sql):
    — SQL: begin ———–
    set pagesize 40
    set linesize 120
    set trimout on trimspool on
    set verify off
    col LINE for 99999 hea ‘Line|Nr’
    col TEXT for a80 hea ‘Text’ wrap
    prompt
    prompt *** Listing source of PL/SQL object *****
    prompt
    accept plsql_obj char prompt “*** Define name of PL/SQL object [%]: ” default “%”
    accept plsql_typ char prompt “*** Type of object ….. [PROCEDURE]: ” default “PROCEDURE”
    accept start_line number prompt “*** Starting line number ……..[1]: ” default 1
    accept end_line number prompt “*** Ending line number ……….[9]: ” default 9
    select LINE,
    TEXT
    from USER_SOURCE
    where NAME like upper(‘&&plsql_obj.%’)
    and TYPE = upper(‘&&plsql_typ.’)
    and line between &&start_line and &&end_line
    order by NAME, LINE
    /
    undefine plsql_obj
    undefine plsql_typ
    undefine start_line
    undefine end_line
    — SQL: end ———–
    I run this script in SQL*Plus using e.g. starting line 15 and ending line 25 in order to
    narrow the ‘problem area’ in the first run … you might ask ‘why SQL*Plus?’.
    Reason: normally, SQL and PL/SQL source files are deployed by means of sqlplus.
    Therefore I develop ‘production-close’ uploading my developed PL/SQL code via sqlplus
    (my first basic unit test: do the PL/SQL objects get compiled at all?).
    As for me, the sql script based debugging methodology payed out in most cases.
    sometimes, I also use debugging functionality in PL/SQL Developer or Toad …
    But this is a completely different discussion 😉
    —
    — [D] test case cleanup
    —
    drop procedure p_tst_xfer;
    drop function f_cre_err_infos;
    drop table T1 cascade constraints;
    drop table T2 cascade constraints;

    See less
      • 1
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp

Sidebar

Adv 250x250

Explore

  • Categories
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Dev Tools
    • Online Compiler
    • Base64 Converter
  • Wiki
    • SQL Tutorials
    • Java Tutorials
    • Python Tutorials
    • JavaScript Tutorials

Footer

Oraask

About

Oraask is a website for developers and software engineers who want to learn new skills, share their knowledge, and solve their coding problems. Oraask provides free content on various programming languages and topics, such as Oracle, Python, Java, etc. Oraask also allows users to ask questions and get answers from other members of the community.

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy
  • Terms & Conditions

Follow

Oraask is licensed under CC BY-NC-SA 4.0Oraask CopyrightOraask CopyrightOraask CopyrightOraask Copyright

© 2019 Oraask. All Rights Reserved
With Love by Oraask.