﻿<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Steven Feuerstein's Blog</title>
    <description>&lt;table cellspacing="1" cellpadding="1"&gt;
        &lt;tr&gt;
            &lt;td valign="top"&gt;&lt;img height="183" alt="" width="139" src="/Portals/0/Blog/blog-steven-feuerstein.png" /&gt;&lt;/td&gt;
            &lt;td valign="top"&gt;Steven Feuerstein is considered one of the world's leading experts on the Oracle PL/SQL language, having written ten books on PL/SQL (all published by O'Reilly Media, including Oracle PL/SQL Programming. Steven has been developing software since 1980, spent five years with Oracle (1987-1992) and has served as PL/SQL Evangelist for Quest Software since January 2001. He is also an Oracle ACE Director. He writes regularly for Oracle Magazine, which named him the PL/SQL Developer of the Year in both 2002 and 2006.
            &lt;p&gt;&amp;#160;Steven's blog provides advice and code that you can put to immediate use in your world of programming.&amp;#160;&lt;/p&gt;
            &lt;p&gt;&lt;font color="#003366" size="3"&gt;&lt;strong&gt;Recent postings on his  PL/SQL Obsession:&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
&lt;/table&gt;</description>
    <link>http://www.toadworld.com/BLOGS/tabid/67/BlogId/13/Default.aspx</link>
    <language>en-US</language>
    <managingEditor>Steven Feuerstein</managingEditor>
    <webMaster>webmaster@toadworld.com</webMaster>
    <pubDate>Thu, 18 Mar 2010 20:31:25 GMT</pubDate>
    <lastBuildDate>Thu, 18 Mar 2010 20:31:25 GMT</lastBuildDate>
    <docs>http://backend.userland.com/rss</docs>
    <generator>Blog RSS Generator Version 3.2.0.15477</generator>
    <item>
      <title>PL/SQL Breadcrumbs</title>
      <description>&lt;p&gt;When an exception is raised, one of the most important pieces of information a programmer would love to get hold of is the line of code that caused the exception to be raised.  Before Oracle 10g came long, the only way to get this information was to allow the exception to go unhandled and then view the error stack. The following chain of program calls shows you what I mean.&lt;/p&gt;
&lt;div style="border-style: none none none solid; border-color: -moz-use-text-color -moz-use-text-color -moz-use-text-color windowtext; border-width: medium medium medium 1pt; padding: 0in 0in 0in 2pt; margin-left: 0.25in; margin-right: -67.7pt;"&gt;
&lt;p style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;CREATE OR REPLACE PROCEDURE my_procedure_1 IS&lt;/font&gt;&lt;/p&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;BEGIN&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;   DBMS_OUTPUT.put_line ('running my_procedure_1');&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;   RAISE NO_DATA_FOUND;&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;END;&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;/&lt;/font&gt;&lt;/div&gt;
&lt;p style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;CREATE OR REPLACE PROCEDURE my_procedure_2 IS&lt;/font&gt;&lt;/p&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;   l_str VARCHAR2(30) := 'calling my_procedure_1';&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;BEGIN&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;   DBMS_OUTPUT.put_line (l_str);&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;   my_procedure_1; &lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;END;&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;/&lt;/font&gt;&lt;/div&gt;
&lt;p style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;CREATE OR REPLACE PROCEDURE my_procedure_3 IS&lt;/font&gt;&lt;/p&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;BEGIN&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;   DBMS_OUTPUT.put_line ('calling my_procedure_2');&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;   my_procedure_2;&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;END;&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;/&lt;/font&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Procedure my_procedure_3 calls my_procedure_2 calls my_procedure_1, at which point my_procedure_1 raises the NO_DATA_FOUND exception. Notice that there is no error handling in any of the procedures, most significantly lacking in the top-level my_procedure_3 procedure. If I run my_procedure_3, I will then see the following results:&lt;/p&gt;
&lt;div style="border-style: none none none solid; border-color: -moz-use-text-color -moz-use-text-color -moz-use-text-color windowtext; border-width: medium medium medium 1pt; padding: 0in 0in 0in 2pt; margin-left: 0.25in; margin-right: -67.7pt;"&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;ERROR at line 1:&lt;/font&gt;&lt;/div&gt;
&lt;p style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;ORA-01403: no data found&lt;/font&gt;&lt;/p&gt;
&lt;p style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;ORA-06512: at "SCOTT.MY_PROCEDURE_1", line 4&lt;/font&gt;&lt;/p&gt;
&lt;p style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;ORA-06512: at "SCOTT.MY_PROCEDURE_2", line 6&lt;/font&gt;&lt;/p&gt;
&lt;p style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;ORA-06512: at "SCOTT.MY_PROCEDURE_3", line 4&lt;/font&gt;&lt;/p&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;ORA-06512: at line 3&lt;/font&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;We see immediately that the error was raised on line 7 of my_procedure_1. &lt;/p&gt;
&lt;p&gt;Glad to have the info, but I would really like to avoid letting my exception go unhandled. Instead, I want to &lt;em&gt;log&lt;/em&gt; this information from within PL/SQL – and sad to say, prior to Oracle 10g, this was not possible. You can see this in the code below:&lt;/p&gt;
&lt;p&gt;I add an exception section to the my_procedure_3 procedure used above:&lt;/p&gt;
&lt;div style="border-style: none none none solid; border-color: -moz-use-text-color -moz-use-text-color -moz-use-text-color windowtext; border-width: medium medium medium 1pt; padding: 0in 0in 0in 2pt; margin-left: 0.25in; margin-right: -67.7pt;"&gt;
&lt;p style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;CREATE OR REPLACE PROCEDURE my_procedure_3&lt;/font&gt;&lt;/p&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;IS&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;BEGIN&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;   DBMS_OUTPUT.put_line ('calling my_procedure_2');&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;   my_procedure_2;&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;EXCEPTION&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;   WHEN OTHERS THEN&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;      DBMS_OUTPUT.PUT_LINE (&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;         DBMS_UTILITY.FORMAT_ERROR_STACK);&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;END;&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;/&lt;/font&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Notice that I call &lt;span&gt;DBMS_UTILITY.FORMAT_ERROR_STACK instead of &lt;/span&gt;SQLERRM. Oracle recommends that we use this built-in packaged function because it will return the &lt;em&gt;full&lt;/em&gt; error message, while SQLERRM may truncate the error message. &lt;/p&gt;
&lt;div&gt;When I run this code, I see the following output:&lt;/div&gt;
&lt;div style="border-style: none none none solid; border-color: -moz-use-text-color -moz-use-text-color -moz-use-text-color windowtext; border-width: medium medium medium 1pt; padding: 0in 0in 0in 2pt; margin-left: 0.25in; margin-right: -67.7pt;"&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;calling my_procedure_2&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;calling my_procedure_1&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;running my_procedure_1&lt;/font&gt;&lt;/div&gt;
&lt;p style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;ORA-01403: no data found&lt;/font&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;In other words, &lt;span&gt;DBMS_UTILITY.FORMAT_ERROR_STACK does not show us the full error stack with line numbers. I only see the error message; I get the same behavior with SQLERRM. &lt;/span&gt;&lt;/p&gt;
&lt;div&gt;Very frustrating!&lt;/div&gt;
&lt;p&gt;&lt;span&gt;Fortunately, in Oracle 10g, the DBMS_UTILITY.FORMAT_ERROR_BACKTRACE provides precisely this functionality: it displays the call stack at the point where an exception was raised, even if the function is called in a PL/SQL block in an outer scope from that where the exception was raised. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Let's go back to that my_procedure_3 procedure and replace the call to FORMAT_ERROR_STACK with FORMAT_ERROR_BACKTRACE. &lt;/span&gt;&lt;/p&gt;
&lt;div style="border-style: none none none solid; border-color: -moz-use-text-color -moz-use-text-color -moz-use-text-color windowtext; border-width: medium medium medium 1pt; padding: 0in 0in 0in 2pt; margin-left: 0.25in; margin-right: -67.7pt;"&gt;
&lt;p style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;CREATE OR REPLACE PROCEDURE my_procedure_3&lt;/font&gt;&lt;/p&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;IS&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;BEGIN&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;   DBMS_OUTPUT.put_line ('calling my_procedure_2');&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;   my_procedure_2;&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;EXCEPTION&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;   WHEN OTHERS&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;   THEN&lt;/font&gt;&lt;/div&gt;
&lt;p style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;      DBMS_OUTPUT.put_line ('Error stack at top level:');&lt;/font&gt;&lt;/p&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;      DBMS_OUTPUT.PUT_LINE (DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;END;&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;/&lt;/font&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;And now when I run my_procedure_3, I will see the following output:&lt;/p&gt;
&lt;div style="border-style: none none none solid; border-color: -moz-use-text-color -moz-use-text-color -moz-use-text-color windowtext; border-width: medium medium medium 1pt; padding: 0in 0in 0in 2pt; margin-left: 0.25in; margin-right: -67.7pt;"&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;calling my_procedure_2&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;calling my_procedure_1&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;running my_procedure_1&lt;/font&gt;&lt;/div&gt;
&lt;p style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;Error stack at top level:&lt;/font&gt;&lt;/p&gt;
&lt;p style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;ORA-06512: at "SCOTT.MY_PROCEDURE_1", line 4&lt;/font&gt;&lt;/p&gt;
&lt;p style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;ORA-06512: at "SCOTT.MY_PROCEDURE_2", line 6&lt;/font&gt;&lt;/p&gt;
&lt;p style="margin: 0in 0in 0.0001pt;"&gt;&lt;font color="#006600"&gt;ORA-06512: at "SCOTT.MY_PROCEDURE_3", line 4&lt;/font&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Fantastic! The line number can now be obtained within my PL/SQL block and stored along with the rest of my error log information.&lt;/p&gt;
&lt;p&gt;And, just so we all understand my choice for the title of this blog entry: the backtrace is like a trail of breadcrumbs leading back to the line that raised the error. 'Nuff said.&lt;/p&gt;
&lt;p&gt;I consider &lt;span&gt;DBMS_UTILITY.FORMAT_ERROR_BACKTRACE to be one of the most useful enhancements in Oracle 10g. Here are my recommendations for its use:&lt;/span&gt;&lt;/p&gt;
&lt;ul type="disc" style="margin-top: 0in;"&gt;
    &lt;li&gt;Call      this function whenever you have trapped an exception in a WHEN clause.      Grab that backtrace information and store in your error log (database      table, file, whatever).&lt;/li&gt;
    &lt;li&gt;It is      especially important to call the function &lt;em&gt;before &lt;/em&gt;you re-raise an exception in your exception handler (or      raise another exception). Once you raise an exception, the backtrace      string will only trace back to this last raise, and not the original      error.&lt;/li&gt;
    &lt;li&gt;Best      of all: create a standard error logging package or procedure that all      developers use to log an error, and have &lt;em&gt;that&lt;/em&gt; central module call the backtrace function.&lt;/li&gt;
&lt;/ul&gt;</description>
      <link>http://www.toadworld.com/BLOGS/tabid/67/EntryID/39/Default.aspx</link>
      <author>Steven Feuerstein</author>
      <comments>http://www.toadworld.com/BLOGS/tabid/67/EntryID/39/Default.aspx#Comments</comments>
      <guid isPermaLink="true">http://www.toadworld.com/Default.aspx?tabid=67&amp;EntryID=39</guid>
      <pubDate>Thu, 09 Nov 2006 18:55:00 GMT</pubDate>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://www.toadworld.com/DesktopModules/Blog/Trackback.aspx?id=39</trackback:ping>
    </item>
  </channel>
</rss>