<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
  <channel xmlns:blog="http://www.dotnetnuke.com/blog/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
    <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>
    <webMaster>Steven Feuerstein</webMaster>
    <pubDate>Tue, 15 May 2012 23:36:10 GMT</pubDate>
    <lastBuildDate>Tue, 15 May 2012 23:36:10 GMT</lastBuildDate>
    <docs>http://backend.userland.com/rss</docs>
    <generator>Blog RSS Generator Version 4.0.0.0</generator>
    <item>
      <title>Real Developers Follow Standards</title>
      <link>http://toadworld.com/Blogs/tabid/67/EntryId/896/Real-Developers-Follow-Standards.aspx</link>
      <description>&lt;p&gt;&lt;font size="2"&gt;We software developers are a very privileged bunch. We don’t have to work in dangerous environments, and our jobs aren’t physically taxing (though carpal tunnel syndrome is always a threat). We are paid to think about things, and then to write down our thoughts in the form of code. This code is then used and maintained by others, sometimes for decades. &lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font size="2"&gt;Given this situation, I believe we all have a responsibility to write code that can be easily understood and maintained (and, c’mon, let’s admit our secret desires, admired) by the developers who follow in our footsteps. Look at this way: if you have a child, she might grow up to be a programmer. She might even put in time at one of your previous employers. She might actually end up having to maintain code that you wrote.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font size="2"&gt;The choice is yours: avoid mortifying embarrassment either by never putting your name in your code, or by writing code that you would be proud to show to, share with, and inflict on your own flesh and blood.&lt;/font&gt;&lt;/p&gt;&lt;div class="tags"&gt;Tags: plsql,formatter,best practice,standards,maintainability,readability,format,code templates&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <guid isPermaLink="true">http://toadworld.com/Blogs/tabid/67/EntryId/896/Real-Developers-Follow-Standards.aspx</guid>
      <pubDate>Mon, 14 May 2012 13:06:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=896</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/80/Default.aspx">formatter</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/413/Default.aspx">best practice</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/172/Default.aspx">standards</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/414/Default.aspx">maintainability</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/415/Default.aspx">readability</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/416/Default.aspx">format</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/59/Default.aspx">code templates</blog:tag>
    </item>
    <item>
      <title>Error Management: Criticism from Abroad</title>
      <link>http://toadworld.com/Blogs/tabid/67/EntryId/880/Error-Management-Criticism-from-Abroad.aspx</link>
      <description>&lt;div&gt;
&lt;p&gt;I write a PL/SQL 101 column for Oracle Magazine and the March/April 2012 issue focused on &lt;a href="http://www.oracle.com/technetwork/issue-archive/2012/12-mar/o22plsql-1518275.html?ssSourceSiteId=ocomen"&gt;Error Management&lt;/a&gt;. I received the following letter from a reader; we couldn't fit the whole thing in Oracle Magazine's Q&amp;A section, so I decided to publish it here.&lt;/p&gt;
&lt;/div&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;p&gt;&lt;font color="#0000ff"&gt;Hello Steven,&lt;br /&gt;
&lt;br /&gt;
I've very much enjoyed your PL/SQL articles in Oracle Magazine for many years, and it's excellent that you are evangelising about good programming style and techniques in PL/SQL including exceptions.&lt;br /&gt;
&lt;br /&gt;
However (and I bet you knew a however was coming), I have a concern with the recent article about exceptions; not so much from a programming point of view but from an architectural standards point of view, especially when trying to implement parts of a service oriented architecture in PL/SQL.&lt;br /&gt;
&lt;br /&gt;
My concern is that the examples you give for application defined exceptions don't fit well with architectural best practice. The examples suggest that you could use exceptions as part of the implementation of business rules with PL/SQL, and I think that's not an appropriate use of exceptions. It also tends to lead the developer to embed business rules within larger business functions (resulting in brittle coding that needs frequent change), and it would be better to abstract and centralise business rules into a more flexible business rules PL/SQL package, and handle the results of a business rule using normal conditional logic statements. &lt;br /&gt;
&lt;br /&gt;
The examples given also lead the programmer to embed "magic numbers" in the code, when these should be declared as appropriate package level constants at the very least, if not queried from a configuration table or other method that would avoid code change. &lt;br /&gt;
&lt;br /&gt;
My view is that exceptions should be used to handle issues that are outside the specification of the function or that the programmer "hasn't thought of" (potentially non-functional requirements) and for robustness checks. Even handling standard exceptions such as divide by zero, no data found, duplicate value can veer quite close to business rules logic and therefore the hander blocks for these exceptions should wrap the statements which could raise these exceptions quite closely to convert the exception into normal conditional logic.&lt;br /&gt;
&lt;br /&gt;
Based on this, my view is that the closest that an exception should come to implementing a business rule is to raise an exception inside a business rules package where the correct business rule cannot be determined from the inputs (e. g. there isn't a "catch all" rule that returns a definitive business result).&lt;br /&gt;
&lt;br /&gt;
More formally, I think application defined exceptions should be restricted to validating detailed coding "assertions", i. e. validating the domain of the input arguments to a package or function and return values (supplementing proper data typing and object definition of the parameters) and coding predicates (preconditions, postconditions, and loop invariants), especially to validate detailed functional specifications of a procedure or function and confirm internal workings are as expected. This would fit well with safe coding/formal proof techniques such as those documented by Dijkstra, Floyd and Hoare since the 1970's, and typically used with safety-critical systems developed using languages such as SPARK Ada (and any PL/SQL developer should be right at home with SPARK Ada and vice versa, given the similarity of the languages).&lt;br /&gt;
&lt;br /&gt;
The standard exceptions defined and used in Oracle follow these principles.&lt;br /&gt;
&lt;br /&gt;
Based on these points of view, I think PL/SQL coders generally should define no more than 10 application exceptions within any sized group of PL/SQL code (ideally less than 5) to cover general classes of exception such as "Loop invariant failed" (with details handled by some error logging logic), and the outermost exception handlers should report a more specific error based on the error stack. And very often it will be possible to handle the predicate failure by raising an appropriate standard Oracle exception.&lt;br /&gt;
&lt;br /&gt;
Finally, it would be great to explore error handling and reporting in more detail in another article. I'd would very much like to know your views of the pro's and con's of various error reporting techniques alongside those touched on in the current article, e. g. UTL_FILE/TEXT_IO, DBMS_OUTPUT, DBMS_APPLICATION_INFO, AQ, or PL/SQL calls to Java Error logging packages.&lt;/font&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p dir="ltr"&gt;And my initial response:&lt;/p&gt;
&lt;div&gt;
&lt;p&gt;First, many thanks to Miles for taking the time to think about the implications of the code shown in the article and to send your thoughts to me.&lt;/p&gt;
&lt;p&gt;Second, you raise a concern that 'examples given also lead the programmer to embed "magic numbers" in the code'. Here is an example of what I assume you are talking about:&lt;/p&gt;
&lt;/div&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;CREATE OR REPLACE PROCEDURE &lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;validate_employee (&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;font face="Courier New"&gt;   birthdate_in IN DATE)&lt;/font&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;IS&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;BEGIN&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;font face="Courier New"&gt;   IF birthdate_in &gt; &lt;/font&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;font face="Courier New"&gt;      ADD_MONTHS (SYSDATE, -12 * 18)&lt;/font&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;font face="Courier New"&gt;   THEN&lt;/font&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;font face="Courier New"&gt;      RAISE_APPLICATION_ERROR (-20500&lt;/font&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;font face="Courier New"&gt;        , 'Employee must be at least &lt;/font&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;font face="Courier New"&gt;           18 years old.'); &lt;/font&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;font face="Courier New"&gt;   END IF;&lt;/font&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;END;&lt;/font&gt;&lt;/div&gt;
&lt;/blockquote&gt;
&lt;div&gt;
&lt;p&gt;Miles is absolutely correct; this example and others do contain hard-codings. And, as many of my readers probably know, I have advocated in presentations and (other) articles to do everything you can to avoid such hard-codings in your code.&lt;/p&gt;
&lt;p&gt;So what is my excuse here? Only (and inadequately) that in the short space allotted for these articles, it is not always possible to adhere to every best practice. Having said that, I could have (and will seek to do this in future articles) included a comment or sidebar that points out the hard-coded values and warns against writing code like this in your production applications.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;As to Miles' concerns about application exceptions and how they should be defined and used, I would like to invite Miles to follow up from this original letter with a bit more explanation and examples that would demonstrate clearly to my readers how his approach would change things.&lt;/div&gt;&lt;br /&gt;&lt;a href=http://toadworld.com/Blogs/tabid/67/EntryId/880/Error-Management-Criticism-from-Abroad.aspx&gt;More ...&lt;/a&gt;&lt;div class="tags"&gt;Tags: plsql,error management,exception handling,plsql package,magic numbers&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <guid isPermaLink="true">http://toadworld.com/Blogs/tabid/67/EntryId/880/Error-Management-Criticism-from-Abroad.aspx</guid>
      <pubDate>Tue, 24 Apr 2012 15:08:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=880</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/395/Default.aspx">error management</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/396/Default.aspx">exception handling</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/397/Default.aspx">plsql package</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/398/Default.aspx">magic numbers</blog:tag>
    </item>
    <item>
      <title>Oracle Open World 2012 - Time to submit papers!</title>
      <link>http://toadworld.com/Blogs/tabid/67/EntryId/863/Oracle-Open-World-2012-Time-to-submit-papers.aspx</link>
      <description>&lt;p&gt;OOW is the big (enormous, really) blast of a conference/party that Oracle hosts each year in San Francisco. I've been attending these conferences since the late 1980s, and each year it seems to get bigger. Fortunately, Oracle offers a "conference within a conference": Oracle Develop, for those of us developing applications with Oracle technology.&lt;br /&gt;
&lt;br /&gt;
I usually spend almost all my time at the Oracle Develop hotel, so even though I am one of 45,000 or so attendees, I still manage to meet up with lots of old friends in the Oracle world.&lt;br /&gt;
&lt;br /&gt;
Oracle has put out its &lt;a href="http://www.oracle.com/openworld/call-for-papers/information/index.html"&gt;call for papers&lt;/a&gt; for OOW12; it's very competitive to have one's abstract accepted for this conference. But that's no reason to skip the submission process! If you haven't been to one of these before, it is an amazing experience.The exhibition hall alone is somewhat breathtaking (and sometimes shocking - many vendors &lt;em&gt;still&lt;/em&gt; hire very attractive people to attract the attention of attendees. Very highbrow operations!). &lt;br /&gt;
&lt;br /&gt;
You are much more likely to get your manager to approve your participation in OOW12 if your paper is accepted. And even if your paper is not accepted, you will benefit from the experience of asking yourself these questions:&lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;What have I learned lately?&lt;/li&gt;
    &lt;li&gt;What problems have I solved that others are likely to encounter as well?&lt;/li&gt;
    &lt;li&gt;What interesting applications of Oracle technology have I come up with?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Hope to see you there (if any of my papers are accepted!),&lt;br /&gt;
&lt;br /&gt;
Steven&lt;/p&gt;&lt;br /&gt;&lt;a href=http://toadworld.com/Blogs/tabid/67/EntryId/863/Oracle-Open-World-2012-Time-to-submit-papers.aspx&gt;More ...&lt;/a&gt;&lt;div class="tags"&gt;Tags: oracle,oracle open world,oow,plsql,oracle develop&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <guid isPermaLink="true">http://toadworld.com/Blogs/tabid/67/EntryId/863/Oracle-Open-World-2012-Time-to-submit-papers.aspx</guid>
      <pubDate>Fri, 23 Mar 2012 19:41:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=863</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/2/Default.aspx">oracle</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/382/Default.aspx">oracle open world</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/383/Default.aspx">oow</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/384/Default.aspx">oracle develop</blog:tag>
    </item>
    <item>
      <title>The Date Literal</title>
      <link>http://toadworld.com/Blogs/tabid/67/EntryId/840/The-Date-Literal.aspx</link>
      <description>&lt;div&gt;Consider the following block:&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;strong&gt;&lt;font face="Courier New"&gt;DECLARE&lt;/font&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;   &lt;strong&gt;l_date&lt;/strong&gt;   DATE&lt;strong&gt;;&lt;/strong&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;&lt;font face="Courier New"&gt;BEGIN&lt;/font&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;   &lt;strong&gt;l_date&lt;/strong&gt; &lt;strong&gt;:=&lt;/strong&gt; &lt;strong&gt;'15-FEB-2011'&lt;/strong&gt;&lt;strong&gt;;&lt;/strong&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;&lt;font face="Courier New"&gt;END;&lt;/font&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;strong&gt; &lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;I declare a date variable and then assign a string to it. Will this block raise an error? Hard to say. It depends on the NLS settings for the default date format – for the database as a whole or for my session. If this string doesn’t match the default, then Oracle will raise an error, such as:&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;ORA-01858: a non-numeric character was found where a numeric was expected&lt;/font&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;This block also performs an implicit conversion, which is generally frowned upon. We are encouraged, instead, to explicitly convert from string to date as in:&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;strong&gt;&lt;font face="Courier New"&gt;DECLARE&lt;/font&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;   &lt;strong&gt;l_date&lt;/strong&gt;   DATE&lt;strong&gt;;&lt;/strong&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;&lt;font face="Courier New"&gt;BEGIN&lt;/font&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;   &lt;strong&gt;l_date&lt;/strong&gt; &lt;strong&gt;:=&lt;/strong&gt; &lt;strong&gt;TO_DATE&lt;/strong&gt; &lt;strong&gt;(&lt;/strong&gt;&lt;strong&gt;'15-FEB-2011'&lt;/strong&gt;&lt;strong&gt;);&lt;/strong&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;&lt;font face="Courier New"&gt;END;&lt;/font&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;strong&gt; &lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;Yes, that is better – but still will raise the same error. To avoid making an assumption about the default date format, many of us have provided that format in the call to TO_DATE, as in:&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;strong&gt;&lt;font face="Courier New"&gt;DECLARE&lt;/font&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;   &lt;strong&gt;l_date&lt;/strong&gt;   DATE&lt;strong&gt;;&lt;/strong&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;&lt;font face="Courier New"&gt;BEGIN&lt;/font&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;   &lt;strong&gt;l_date&lt;/strong&gt; &lt;strong&gt;:=&lt;/strong&gt; &lt;strong&gt;TO_DATE&lt;/strong&gt; &lt;strong&gt;(&lt;/strong&gt;&lt;strong&gt;'FEB-15-2011'&lt;/strong&gt;&lt;strong&gt;,&lt;/strong&gt; &lt;strong&gt;'MON-DD-YYYY'&lt;/strong&gt;&lt;strong&gt;);&lt;/strong&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;&lt;font face="Courier New"&gt;END;&lt;/font&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;
Then, as long as the string matches the format, Oracle will not raise an error, regardless of the default date format.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;But oh that is a pain in the you know what to write, over and over again. So Oracle now (actually, since Oracle9!) &lt;a target="_blank" href="http://docs.oracle.com/cd/B19306_01/server.102/b14200/sql_elements003.htm#BABGIGCJ"&gt;supports the ANSI date literal&lt;/a&gt;, which means that you can assign a value to a date as follows:&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;strong&gt;&lt;font face="Courier New"&gt;DECLARE&lt;/font&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;   &lt;strong&gt;l_date&lt;/strong&gt;   DATE&lt;strong&gt;;&lt;/strong&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;&lt;font face="Courier New"&gt;BEGIN&lt;/font&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;   &lt;strong&gt;l_date&lt;/strong&gt; &lt;strong&gt;:=&lt;/strong&gt; DATE &lt;strong&gt;'2011-02-15'&lt;/strong&gt;&lt;strong&gt;;&lt;/strong&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;&lt;font face="Courier New"&gt;END;&lt;/font&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;strong&gt; &lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;In other words: the keyword DATE follows by a literal string in the form ‘YYYY-MM-DD’. You have no choice in this format; it cannot be changed by changing NLS settings. In addition, the ANSI date literal contains no time portion. So if you need to specify a time other than midnight for your date variable, you will still need to fall back on code like this:&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;strong&gt;&lt;font face="Courier New"&gt;DECLARE&lt;/font&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;   &lt;strong&gt;l_date&lt;/strong&gt;   DATE&lt;strong&gt;;&lt;/strong&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;&lt;font face="Courier New"&gt;BEGIN&lt;/font&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;   &lt;strong&gt;l_date&lt;/strong&gt; &lt;strong&gt;:=&lt;/strong&gt; &lt;strong&gt;TO_DATE&lt;/strong&gt; &lt;strong&gt;(&lt;/strong&gt;&lt;strong&gt;'FEB-15-2011 13:14:15'&lt;/strong&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;strong&gt;                    &lt;/strong&gt;&lt;strong&gt;,&lt;/strong&gt; &lt;strong&gt;'MON-DD-YYYY HH24:MI:SS'&lt;/strong&gt;&lt;strong&gt;);&lt;/strong&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;&lt;font face="Courier New"&gt;END;&lt;/font&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;strong&gt; &lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;But it is certainly cleaner and simpler code when you only need to assign a hard-coded literal value to a date variable or column in the database.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;As I noted above, support for the ANSI date literal has been in place for quite a while, but very few Oracle technologists are aware of this feature.&lt;/div&gt;&lt;br /&gt;&lt;a href=http://toadworld.com/Blogs/tabid/67/EntryId/840/The-Date-Literal.aspx&gt;More ...&lt;/a&gt;&lt;div class="tags"&gt;Tags: plsql,dates,to_date,date&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <guid isPermaLink="true">http://toadworld.com/Blogs/tabid/67/EntryId/840/The-Date-Literal.aspx</guid>
      <pubDate>Tue, 21 Feb 2012 17:50:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=840</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/187/Default.aspx">dates</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/357/Default.aspx">to_date</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/358/Default.aspx">date</blog:tag>
    </item>
    <item>
      <title>"Our" Error Codes : -20999 to -20000</title>
      <link>http://toadworld.com/Blogs/tabid/67/EntryId/832/-Our-Error-Codes-20999-to-20000.aspx</link>
      <description>&lt;div&gt;
&lt;p&gt;Oracle PL/SQL provides the RAISE_APPLICATION_ERROR built-in procedure (actually defined in the DBMS_STANDARD package) so that we can communicate application-specific error messages back to our users. When you call this procedure, you provide a negative number between -20999 and -20000, as well as your error message.&lt;/p&gt;
&lt;p&gt;Here's an example of calling RAISE_APPLICATION_ERROR from inside a trigger, ensuring that employees must be at least 18 years old.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;BEGIN&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;   &lt;/span&gt;IF :new.birth_date &gt; ADD_MONTHS (SYSDATE, -18 * 12)&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;   &lt;/span&gt;THEN&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;      RAISE_APPLICATION_ERROR &lt;/span&gt;(-20701&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;                             &lt;/span&gt;, 'Employee must be at least 18 years old.');&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;   &lt;/span&gt;END IF;&lt;br /&gt;
END;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;For many programmers, having 1,000 error codes to choose from is more than enough, but I have met developers over the years who have "run out" of error codes. Surely, Oracle could have let us use a few more of the infinite number of negative integers "out there." And if they are not going to do that, then at least you would think that Oracle would not itself use any of these "precious" user error codes.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;That is, however, not the case. Oracle itself uses RAISE_APPLICATION_ERROR in a number of its own supplied packages. But which error codes does Oracle use?&lt;/p&gt;
&lt;p&gt;The 29 December 2011 quiz at the &lt;a href="http://www.plsqlchallenge.com/"&gt;PL/SQL Challenge&lt;/a&gt;, tested players' knowledge of the different ways that errors can be raised in a PL/SQL block. As has been the case with many quizzes, it served as a launch point for an interesting discussion, which you can read &lt;a href="http://plsql-challenge.blogspot.com/2011/12/what-is-generic-oracle-error-message.html"&gt;here&lt;/a&gt;. It also led Niels Hecker, one of the top players at the PL/SQL Challenge, to figure out exactly which of those -20NNN error codes are used by Oracle. Well, to be honest, he wasn't quite able to do that. Instead he finds all the PRAGMA EXCEPTION_INIT statements that reference an error code in that range.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;I offer Niels' query below, but please note that you will need access to the DBA_SOURCE data dictionary view. You can change it to USER_SOURCE, but then you will "only" identify  such usages in your &lt;em&gt;own&lt;/em&gt; code – which is useful in and of itself. I have also restricted the search to objects owned by SYS and SYSMAN, so you will want to remove that WHERE clause predicate for a wider search.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;WITH data&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;     &lt;/span&gt;AS (SELECT (&lt;span&gt;   &lt;/span&gt;'^.*PRAGMA\s+EXCEPTION_INIT\s*\(\s*' &lt;em&gt;-- PRAGMA EXCPETION_INIT(&lt;/em&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;                 &lt;/span&gt;|| '([A-Z0-9_$#]{1,30}|"[^"]{1,30}")'&lt;span&gt;         &lt;/span&gt;&lt;em&gt;-- Exception-Name&lt;/em&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;                 &lt;/span&gt;&lt;em&gt;-- comment the following line out, if the exception_name&lt;/em&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;                 &lt;/span&gt;&lt;em&gt;-- and the exception code are on different lines&lt;/em&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;                 &lt;/span&gt;|| '\s*,\s*''?(-?\d{1,5})''?'&lt;span&gt;                 &lt;/span&gt;&lt;em&gt;-- Exception-Code&lt;/em&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;                 &lt;/span&gt;&lt;em&gt;-------&lt;/em&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;                 &lt;/span&gt;|| '.*$'&lt;span&gt;                                         &lt;/span&gt;&lt;em&gt;-- End-of-Line&lt;/em&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;                         &lt;/span&gt;)&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;                   &lt;/span&gt;AS &lt;span&gt;rx&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;              &lt;/span&gt;, (' ' || CHR (10) || CHR (13) || CHR (9)) AS &lt;span&gt;trimset&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;           &lt;/span&gt;FROM DUAL)&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;   &lt;/span&gt;, &lt;span&gt;data_source&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;     &lt;/span&gt;AS (SELECT &lt;span&gt;s&lt;/span&gt;.owner&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;              &lt;/span&gt;, &lt;span&gt;s&lt;/span&gt;.TYPE&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;              &lt;/span&gt;, &lt;span&gt;s&lt;/span&gt;.name&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;              &lt;/span&gt;, &lt;span&gt;s&lt;/span&gt;.line&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;              &lt;/span&gt;, UPPER (RTRIM (s.text, (' ' || CHR (10) || CHR (13)))) AS &lt;span&gt;text&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;           &lt;/span&gt;FROM data &lt;span&gt;d&lt;/span&gt;, &lt;span&gt;dba_source s&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;          &lt;/span&gt;WHERE REGEXP_LIKE (s.text, &lt;span&gt;d&lt;/span&gt;.rx, 'i'))&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;   &lt;/span&gt;, &lt;span&gt;data_prepared&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;     &lt;/span&gt;AS (SELECT &lt;span&gt;ds&lt;/span&gt;.owner&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;              &lt;/span&gt;, &lt;span&gt;ds&lt;/span&gt;.TYPE&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;              &lt;/span&gt;, &lt;span&gt;ds&lt;/span&gt;.name&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;              &lt;/span&gt;, &lt;span&gt;ds&lt;/span&gt;.line&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;              &lt;/span&gt;, &lt;span&gt;ds&lt;/span&gt;.text&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;              &lt;/span&gt;, REGEXP_REPLACE (ds.text, &lt;span&gt;d&lt;/span&gt;.rx, '\1') AS &lt;span&gt;exname&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;              &lt;/span&gt;, REGEXP_REPLACE (ds.text, &lt;span&gt;d&lt;/span&gt;.rx, '\2') AS &lt;span&gt;excode&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;           &lt;/span&gt;FROM data &lt;span&gt;d&lt;/span&gt;, &lt;span&gt;data_source ds&lt;/span&gt;)&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt; SELECT &lt;span&gt;dp&lt;/span&gt;.excode&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;       &lt;/span&gt;, &lt;span&gt;dp&lt;/span&gt;.owner&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;       &lt;/span&gt;, &lt;span&gt;dp&lt;/span&gt;.TYPE&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;       &lt;/span&gt;, &lt;span&gt;dp&lt;/span&gt;.name&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;       &lt;/span&gt;, &lt;span&gt;dp&lt;/span&gt;.exname&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;       &lt;/span&gt;, &lt;span&gt;dp&lt;/span&gt;.line&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;       &lt;/span&gt;, &lt;span&gt;dp&lt;/span&gt;.text&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;    &lt;/span&gt;FROM &lt;span&gt;data_prepared dp&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;   &lt;/span&gt;WHERE (TO_NUMBER (dp.excode) BETWEEN -20999 AND -20000) &lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt; &lt;span&gt;       &lt;/span&gt;AND &lt;span&gt;dp&lt;/span&gt;.owner IN ('SYS', 'SYSMAN')&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;ORDER BY TO_NUMBER (dp.excode) DESC&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;       &lt;/span&gt;, &lt;span&gt;dp&lt;/span&gt;.owner&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;       &lt;/span&gt;, &lt;span&gt;dp&lt;/span&gt;.TYPE&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;       &lt;/span&gt;, &lt;span&gt;dp&lt;/span&gt;.name;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;Oracle could still use RAISE_APPLICATION_ERROR in one of its package bodies to simply raise an error in that range, without associating it with a named exception. There isn't really any way to find those, since almost all built-in package bodies are wrapped (obfuscated).&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;&lt;br /&gt;&lt;a href=http://toadworld.com/Blogs/tabid/67/EntryId/832/-Our-Error-Codes-20999-to-20000.aspx&gt;More ...&lt;/a&gt;&lt;div class="tags"&gt;Tags: plsql,raise_application_error,dbms_standard,error message&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <guid isPermaLink="true">http://toadworld.com/Blogs/tabid/67/EntryId/832/-Our-Error-Codes-20999-to-20000.aspx</guid>
      <pubDate>Fri, 03 Feb 2012 17:54:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=832</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/351/Default.aspx">raise_application_error</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/352/Default.aspx">dbms_standard</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/353/Default.aspx">error message</blog:tag>
    </item>
    <item>
      <title>Debugging "Exotic" PL/SQL Data Types</title>
      <link>http://toadworld.com/Blogs/tabid/67/EntryId/820/Debugging-Exotic-PL-SQL-Data-Types.aspx</link>
      <description>&lt;p&gt;The "new" debugging architecture (Java Debug Wire Protocol-based) that was introduced in Oracle Database 9&lt;em&gt;i&lt;/em&gt; Release 2 was a major improvement on the previous one (DBMS_DEBUG), especially because it made it possible to inspect the values of a wider range of data types. However, it's still not possible to inspect the values of all data types, as the JDWP-based debugging architecture has the following limitations on inspection of the following "exotic" data types:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;CLOB: Only the first 511 characters are shown.&lt;/li&gt;
    &lt;li&gt;BLOB: Only the first 510 bytes are shown.&lt;/li&gt;
    &lt;li&gt;XMLTYPE, ANYDATA, ANYDATASET, ANYTYPE: No value is shown.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Obviously this is counterproductive when using these data types (and they are becoming more and more common), since it's more difficult to debug the values and often one needs to write custom logging/tracing code in order to "inspect" the values.&lt;br /&gt;
 &lt;br /&gt;
In August 2009, my friend and Oracle Test Coach Finn Ellebaek Nielsen raised the following Enhancement Request (ER) to Oracle, in order to lift these limitations in the debugging architecture:&lt;br /&gt;
 &lt;br /&gt;
&lt;font face="Courier New"&gt;ER 8837708: IMPLEMENT INVOKEMETHOD COMMAND IN JDWP-BASED DEBUG PROTOCOL&lt;br /&gt;
&lt;br /&gt;
&lt;/font&gt;I believe that it is theoretically still possible to implement this ER for 12c, but I doubt it will happen unless developers around the world make clear that this would be important to them. &lt;br /&gt;
&lt;br /&gt;
So if you often use the "exotic" data types mentioned above and are frustrated with the limitations on debugging, I suggest that you add your business case(s) to the ER as soon as possible.&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;Note:&lt;/strong&gt; your PL/SQL tool provider would still then need to update their software to use this enhancement before the debugging capabilities in that tool are extended, but vendors' hands are tied until Oracle implements this enhancement request.&lt;/p&gt;&lt;br /&gt;&lt;a href=http://toadworld.com/Blogs/tabid/67/EntryId/820/Debugging-Exotic-PL-SQL-Data-Types.aspx&gt;More ...&lt;/a&gt;&lt;div class="tags"&gt;Tags: plsql,data type,debug,JDWP,clob,blob,xml,xmltype,anydata,anydataset,anytype&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <guid isPermaLink="true">http://toadworld.com/Blogs/tabid/67/EntryId/820/Debugging-Exotic-PL-SQL-Data-Types.aspx</guid>
      <pubDate>Tue, 10 Jan 2012 17:14:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=820</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/331/Default.aspx">data type</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/332/Default.aspx">debug</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/333/Default.aspx">JDWP</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/197/Default.aspx">clob</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/334/Default.aspx">blob</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/152/Default.aspx">xml</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/335/Default.aspx">xmltype</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/336/Default.aspx">anydata</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/337/Default.aspx">anydataset</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/338/Default.aspx">anytype</blog:tag>
    </item>
    <item>
      <title>Using CONTINUE in a PL/SQL Block</title>
      <link>http://toadworld.com/Blogs/tabid/67/EntryId/811/Using-CONTINUE-in-a-PL-SQL-Block.aspx</link>
      <description>&lt;div&gt;Oracle added the CONTINUE statement in Oracle Database 11g to simplify the logic you would have to write when you need to terminate execution of code within the body of a loop.&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;CONTINUE is especially helpful when you are executing nested loops and need to skip the remainder of the inner loop's body and &lt;em&gt;continue &lt;/em&gt;on to the next iteration of the outer loop. Sure, you can achieve the same effect with IF statements, but you will need to declare variables (Boolean flags to indicate "execute" or "skip") and the resulting code will be convoluted, hard to read and maintain.&lt;/p&gt;
&lt;p&gt;CONTINUE offers a much simpler, understandable solution.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;The CONTINUE statement can be used &lt;em&gt;only&lt;/em&gt; inside a loop; you cannot use CONTINUE to force termination of a block (and continue in the enclosing block). An attempt to use CONTINUE outside of a loop will raise one of this errors:&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;PLS-00376: illegal EXIT/CONTINUE statement; it must appear inside a loop&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;PLS-00373: EXIT/CONTINUE label '&lt;em&gt;label_name&lt;/em&gt;' must label a LOOP statement&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;If you specify a named loop to which you want to continue, that loop must have been named with a valid label, as in:&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;BEGIN&lt;br /&gt;
  &lt;&lt;for_loop&gt;&gt;&lt;br /&gt;
   FOR indx IN 1 .. 5&lt;br /&gt;
   LOOP&lt;br /&gt;
      DBMS_OUTPUT.put_line ('Outer: ' || indx);&lt;br /&gt;
      CONTINUE for_loop;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;      FOR indx2 IN 1 .. 5&lt;br /&gt;
      LOOP&lt;br /&gt;
         DBMS_OUTPUT.put_line ('Inner: ' || indx2);&lt;br /&gt;
      END LOOP;&lt;br /&gt;
   END LOOP;&lt;br /&gt;
END;&lt;br /&gt;
/&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;You can also use CONTINUE without a label, and include a WHEN clause (just like with EXIT):&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;BEGIN&lt;br /&gt;
   FOR indx IN 1 .. 5&lt;br /&gt;
   LOOP&lt;br /&gt;
      DBMS_OUTPUT.put_line ('Outer: ' || indx);&lt;br /&gt;
      CONTINUE WHEN indx &gt; 3;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;      FOR indx2 IN 1 .. 5&lt;br /&gt;
      LOOP&lt;br /&gt;
         DBMS_OUTPUT.put_line ('Inner: ' || indx2);&lt;br /&gt;
      END LOOP;&lt;br /&gt;
   END LOOP;&lt;br /&gt;
END;&lt;br /&gt;
/&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;If you include a label after CONTINUE, then the remaining code in the current and all enclosing loops up to the loop named by that label will be skipped over. The next iteration of the named loop will be executed.&lt;br /&gt;
&lt;br /&gt;
If you use a CONTINUE statement to exit a cursor FOR loop prematurely (for example, to exit an inner loop and transfer control to the next iteration of an outer loop), the cursor is closed automatically (in this way, CONTINUE works like GOTO).&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;&lt;br /&gt;&lt;a href=http://toadworld.com/Blogs/tabid/67/EntryId/811/Using-CONTINUE-in-a-PL-SQL-Block.aspx&gt;More ...&lt;/a&gt;&lt;div class="tags"&gt;Tags: plsql,continue,loop,for loop&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <guid isPermaLink="true">http://toadworld.com/Blogs/tabid/67/EntryId/811/Using-CONTINUE-in-a-PL-SQL-Block.aspx</guid>
      <pubDate>Mon, 19 Dec 2011 15:33:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=811</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/317/Default.aspx">continue</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/318/Default.aspx">loop</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/83/Default.aspx">for loop</blog:tag>
    </item>
    <item>
      <title>Every VARCHAR2(N) Declaration a Bug!</title>
      <link>http://toadworld.com/Blogs/tabid/67/EntryId/810/Every-VARCHAR2-N-Declaration-a-Bug.aspx</link>
      <description>&lt;div&gt;
&lt;p&gt;This is something I say in my best practice trainings:  Consider every VARCHAR2(N) declaration to be a &lt;em&gt;bug&lt;/em&gt; – unless it's a SPOD.&lt;/p&gt;
&lt;p&gt;What, you might ask, is a SPOD? It's the &lt;em&gt;single point of definition&lt;/em&gt; - the one place in your code where the thing you are working with (datatype, formula, magic value, etc.) is defined or, to put it another way, hard-coded.&lt;/p&gt;
&lt;/div&gt;&lt;div class="tags"&gt;Tags: plsql,varchar2,SPOD,VALUE_ERROR&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <guid isPermaLink="true">http://toadworld.com/Blogs/tabid/67/EntryId/810/Every-VARCHAR2-N-Declaration-a-Bug.aspx</guid>
      <pubDate>Tue, 13 Dec 2011 15:55:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=810</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/314/Default.aspx">varchar2</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/315/Default.aspx">SPOD</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/316/Default.aspx">VALUE_ERROR</blog:tag>
    </item>
    <item>
      <title>The Power of Determinism in Oracle Database 11g</title>
      <link>http://toadworld.com/Blogs/tabid/67/EntryId/782/The-Power-of-Determinism-in-Oracle-Database-11g.aspx</link>
      <description>&lt;div&gt;&lt;font size="2"&gt;A function is considered to be &lt;em&gt;&lt;font color="#ff0000"&gt;deterministic&lt;/font&gt;&lt;/em&gt;   if it returns the same result value whenever it is called with the same values for its IN and IN OUT arguments. Another way to think about deterministic programs is that they have no &lt;em&gt;&lt;font color="#ff0000"&gt;side-effects&lt;/font&gt;&lt;/em&gt;. Everything the program depends on and/or affects is reflected in the parameter list.&lt;/font&gt;&lt;/div&gt;&lt;div class="tags"&gt;Tags: plsql,function,deterministic&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <guid isPermaLink="true">http://toadworld.com/Blogs/tabid/67/EntryId/782/The-Power-of-Determinism-in-Oracle-Database-11g.aspx</guid>
      <pubDate>Mon, 28 Nov 2011 21:12:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=782</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/253/Default.aspx">function</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/298/Default.aspx">deterministic</blog:tag>
    </item>
    <item>
      <title>QuickTips: The Simple, Yet Powerful SUBTYPE</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/767/QuickTips-The-Simple-Yet-Powerful-SUBTYPE.aspx</link>
      <description>&lt;p&gt;The SUBTYPE statement is one of my favorite features of the PL/SQL language; it allows you to create “aliases” for existing types of information, in effect creating your own specially-named datatypes. Use SUBTYPE when you want to standardize on a set of named datatypes that aren’t anchorable back to the database. You can then anchor to &lt;em&gt;those&lt;/em&gt; new datatypes, instead, and achieve the same, desired goal: if a change must be made, or takes place, to a datatype, you will have to make that change in only one place.&lt;/p&gt;&lt;div class="tags"&gt;Tags: plsql,sub-type&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/767/QuickTips-The-Simple-Yet-Powerful-SUBTYPE.aspx</guid>
      <pubDate>Thu, 03 Nov 2011 19:49:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=767</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/39/Default.aspx">sub-type</blog:tag>
    </item>
    <item>
      <title>PL/SQL Grows in Popularity in Past Year</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/758/PL-SQL-Grows-in-Popularity-in-Past-Year.aspx</link>
      <description>&lt;p&gt;&lt;span style="line-height: 115%; font-family: "Calibri","sans-serif"; font-size: 11pt; mso-fareast-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-font-family: 'Times New Roman'; mso-bidi-theme-font: minor-bidi; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;TIOBE Software (www.tiobe.com) publishes a &lt;a href="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html"&gt;Programming Community Index&lt;/a&gt; that rates the popularity of various programming languages and shows trends in usage&lt;/span&gt;&lt;/p&gt;&lt;div class="tags"&gt;Tags: plsql&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/758/PL-SQL-Grows-in-Popularity-in-Past-Year.aspx</guid>
      <pubDate>Tue, 11 Oct 2011 16:04:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=758</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
    </item>
    <item>
      <title>Avoiding Hard-coded Values in Views</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/744/Avoiding-Hard-coded-Values-in-Views.aspx</link>
      <description>&lt;p&gt;Nancy recently wrote to me with the following question:&lt;/p&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;p&gt;&lt;font color="#333399"&gt;Steven, how does one avoid hard codes in views?  I have a very complex view that wants specific data from a multiple of tables - so there are multiple in ('xx','xyz','abc'....) and more.  I know it is a maintenance headache when hard codes are introduced, but not sure how to avoid them - short of creating specific tables that hold the values I want - which then becomes another maintenance headache.&lt;/font&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That is a &lt;em&gt;good&lt;/em&gt; question! And, I am afraid, there is no single really good answer.&lt;/p&gt;
&lt;p&gt;We all know that it is best to avoid hard-codings of literals &lt;em&gt;anywhere &lt;/em&gt;in our programs. Since it is quite likely that the value of the literal could change, hard-codings create serious maintenance problems and likely bugs when the values get out of synch.&lt;/p&gt;
&lt;div&gt;
&lt;p&gt;It is bad enough when a literal value appears in multiple places in our PL/SQL code. It is even worse, however, when that same value may need to appear in PL/SQL code, SQL database objects like views, and even front-end code (Java, .Net, APEX applications, etc.).&lt;/p&gt;
&lt;p&gt;There are a number of ways to avoid hard-codings, and each technique comes with its own pluses and minuses. Here's a quick review of the choices, with examples based on the most basic of hard-codings: values for True and False, Yes and No, etc.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;As you are likely aware, even though PL/SQL and most every programming language offers a Boolean datatype with actual True/False values, SQL does not support a Boolean type. So if I want to store a True or False value in the column of a table, I need to decide what "proxy" values to use (Y and N, T and F, 1 and 0, etc.) and then &lt;em&gt;use them consistently&lt;/em&gt; throughout my entire application.&lt;/p&gt;
&lt;p&gt;I have a view that currently looks like this:&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;CREATE OR REPLACE VIEW lots_of_yes_no_v&lt;br /&gt;
AS&lt;br /&gt;
   SELECT employee_id&lt;br /&gt;
     FROM employees&lt;br /&gt;
    WHERE is_active = 'Y' &lt;br /&gt;
      AND ineligible_for_bonus = 'N' &lt;br /&gt;
      AND missed_work = 'N'&lt;br /&gt;
/&lt;/font&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;and I'd really like to avoid hard-coding the values. How can I do this?&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;&lt;strong&gt;&lt;font size="5"&gt;&lt;font color="#4f81bd" size="4"&gt;Packaged Constant&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;Here's a very simple technique: hide the value behind a constant defined in a package: &lt;/p&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;CREATE OR REPLACE PACKAGE app_config&lt;br /&gt;
IS&lt;br /&gt;
   /* YES value */&lt;br /&gt;
   c_yes   CONSTANT CHAR (1) := 'Y';&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;   /* NO value */&lt;br /&gt;
   c_no    CONSTANT CHAR (1) := 'N';&lt;br /&gt;
END app_config;&lt;br /&gt;
/&lt;/font&gt; &lt;/div&gt;
&lt;/blockquote&gt;
&lt;p&gt;With these constants defined, I can use them when writing PL/SQL code in a schema that has execute authority on that package. Example:&lt;/p&gt;
&lt;/div&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;CREATE OR REPLACE PROCEDURE check_employee (&lt;br /&gt;
   emp_in IN employees%ROWTYPE)&lt;br /&gt;
IS&lt;br /&gt;
BEGIN&lt;br /&gt;
   IF     emp_in.is_active = app_config.c_yes&lt;br /&gt;
      AND emp_in.ineligible_for_bonus = app_config.c_no&lt;br /&gt;
      AND emp_in.missed_work = app_config.c_no&lt;br /&gt;
   THEN&lt;br /&gt;
      DBMS_OUTPUT.put_line ('Check!');&lt;br /&gt;
   END IF;&lt;br /&gt;
END;&lt;br /&gt;
/&lt;/font&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The major drawback of using a packaged constant is that you cannot reference a constant directly inside a SQL statement unless that SQL statement is compiled inside a PL/SQL block. You cannot, therefore, reference a packaged constant as part of a view definition, as you can see below:&lt;/p&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;SQL&gt; CREATE OR REPLACE VIEW lots_of_yes_no_v&lt;br /&gt;
  2  AS&lt;br /&gt;
  3     SELECT employee_id&lt;br /&gt;
  4       FROM my_employees&lt;br /&gt;
  5      WHERE     is_active = app_config.c_yes&lt;br /&gt;
  6            AND ineligible_for_bonus = app_config.c_no&lt;br /&gt;
  7            AND missed_work = app_config.c_no&lt;br /&gt;
  8  /&lt;br /&gt;
          AND missed_work = app_config.c_no&lt;br /&gt;
                            *&lt;br /&gt;
ERROR at line 7:&lt;br /&gt;
ORA-00904: "APP_CONFIG"."C_NO": invalid identifier&lt;/font&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div&gt;
&lt;p&gt;&lt;strong&gt;&lt;font size="5"&gt;&lt;font color="#4f81bd" size="4"&gt;Packaged Function&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;A packaged function can be called from within a SQL statement, and therefore as part of a view's definition. It can be called, of course, from within a PL/SQL block and also from other languages. So it is more or less universally accessible.&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;So why not hide the literal values inside the package body, as in:&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;CREATE OR REPLACE PACKAGE app_config&lt;br /&gt;
IS&lt;br /&gt;
   /* YES value */&lt;br /&gt;
   FUNCTION yes&lt;br /&gt;
      RETURN VARCHAR2;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;   /* NO value */&lt;br /&gt;
   FUNCTION no&lt;br /&gt;
      RETURN VARCHAR2;&lt;br /&gt;
END app_config;&lt;br /&gt;
/&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;CREATE OR REPLACE PACKAGE BODY app_config&lt;br /&gt;
IS&lt;br /&gt;
   /* YES value */&lt;br /&gt;
   FUNCTION yes&lt;br /&gt;
      RETURN VARCHAR2&lt;br /&gt;
   IS&lt;br /&gt;
   BEGIN&lt;br /&gt;
      RETURN 'Y';&lt;br /&gt;
   END;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;   /* NO value */&lt;br /&gt;
   FUNCTION no&lt;br /&gt;
      RETURN VARCHAR2&lt;br /&gt;
   IS&lt;br /&gt;
   BEGIN&lt;br /&gt;
      RETURN 'N';&lt;br /&gt;
   END;&lt;br /&gt;
END app_config;&lt;br /&gt;
/&lt;/font&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;With this package, I can create a view that hides the values:&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;CREATE OR REPLACE VIEW lots_of_yes_no_v&lt;br /&gt;
AS&lt;br /&gt;
   SELECT employee_id&lt;br /&gt;
     FROM my_employees&lt;br /&gt;
    WHERE     is_active = app_config.yes&lt;br /&gt;
          AND ineligible_for_bonus = app_config.no&lt;br /&gt;
          AND missed_work = app_config.no&lt;br /&gt;
/&lt;/font&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The main problem with calling a packaged function inside a view or, more generally, a SQL statement has to do with performance. Every time the function is called, you pay the price of a context switch (from the SQL engine to PL/SQL engine, and back). This price might not be too high if the function is called in the SELECT list. If, however, you need to call it in the WHERE clause, the additional cost of the function calls could be prohibitive. Use of functions inside SQL can also cause problems with the cost based optimizer.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;So packaged functions are &lt;em&gt;not&lt;/em&gt; the generalized solution we are looking for, though it can be suitable for many of our scenarios.&lt;/div&gt;
&lt;div&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;font size="5"&gt;&lt;font color="#4f81bd" size="4"&gt;Stored in Table&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;You can create a table to store all of your "magic values" and then join to this table to obtain the soft-coded value.&lt;/p&gt;
&lt;p&gt;The key drawbacks to this technique is the increased complexity of your applications. In a view, for example, for every value you need to reference, you will need to join to the magic values table. You will then have to identify the row by a hard-coding of the "name" of the value. Hard-coding a name is better than hard-coding a value (the name is less likely to change), but it still leads to cumbersome and verbose SQL.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;You could, alternatively, &lt;em&gt;generate&lt;/em&gt; a package that contains all the magic values from the table, encapsulated behind constants and/or functions. Whenever a change is made to the table, you re-generate the package. But then you face the same drawbacks of using constants and functions listed above.&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;I offer an example of a magic values table and package generator at the end of this posting.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;font size="5"&gt;&lt;font color="#4f81bd" size="4"&gt;Application Context&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;Now  let's look at a more complex, but almost possibly the best solution: application contexts. An application context is a name-value pair defined within a "namespace."  The value of the context can be assigned using DBMS_SESSION.SET_CONTEXT. The value can then be retrieved anywhere in your session code with a call to SYS_CONTEXT ('namespace', 'context_name', 'value_name').&lt;/p&gt;
&lt;p&gt;Generally, the context values would be set whenever a user connects to the Oracle database (this can be done with an AFTER LOGON database trigger). They would then be available inside PL/SQL program units, view definitions, and more.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;The downside of using system context values is added complexity of setup and maintenance of all the "moving parts" needed to use this feature, most of which must be done by a DBA. These "moving parts" include:&lt;/p&gt;
&lt;/div&gt;
&lt;ul&gt;
    &lt;li&gt;Definition of a "trusted package" - the package that contains the programs to set context values. This can only be done &lt;em&gt;from &lt;/em&gt;this package.&lt;/li&gt;
    &lt;li&gt;CREATE CONTEXT statement to define the context.&lt;/li&gt;
    &lt;li&gt;AFTER LOGON trigger to ensure that the context values are set for every session.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With all of this in place, a reference to my magic value in a view would look like:&lt;/p&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;div&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;WHERE mytab.boolean_column = SYS_CONTEXT ('app_config', 'true_value')&lt;/font&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;p&gt;To follow the example, here are the steps I would take to use application contexts in my view:&lt;/p&gt;
&lt;div&gt;&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;CREATE OR REPLACE PACKAGE app_context_pkg&lt;br /&gt;
IS&lt;br /&gt;
   PROCEDURE set_config_values;&lt;br /&gt;
END;&lt;br /&gt;
/&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;CREATE OR REPLACE PACKAGE BODY app_context_pkg&lt;br /&gt;
IS&lt;br /&gt;
   PROCEDURE set_config_values&lt;br /&gt;
   IS&lt;br /&gt;
   BEGIN&lt;br /&gt;
      DBMS_SESSION.set_context ('app_config_ctx', 'yes', 'Y');&lt;br /&gt;
      DBMS_SESSION.set_context ('app_config_ctx', 'no', 'N');&lt;br /&gt;
   END;&lt;br /&gt;
END;&lt;br /&gt;
/&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;CREATE CONTEXT app_config_ctx USING app_context_pkg;&lt;br /&gt;
/&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;CREATE OR REPLACE VIEW lots_of_yes_no_v&lt;br /&gt;
AS&lt;br /&gt;
   SELECT employee_id&lt;br /&gt;
     FROM my_employees&lt;br /&gt;
    WHERE     is_active = SYS_CONTEXT ('app_config_ctx', 'yes')&lt;br /&gt;
          AND ineligible_for_bonus = SYS_CONTEXT ('app_config_ctx', 'no')&lt;br /&gt;
          AND missed_work = SYS_CONTEXT ('app_config_ctx', 'no')&lt;br /&gt;
/&lt;/font&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It's verbose, but it does hide the actual value used.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;For more information on application contexts, check out:  &lt;a href="http://download.oracle.com/docs/cd/B28359_01/network.111/b28531/app_context.htm"&gt;http://download.oracle.com/docs/cd/B28359_01/network.111/b28531/app_context.htm&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;font size="5"&gt;&lt;font color="#4f81bd" size="4"&gt;Manual Synchronization Through Comments&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;If none of these choices are acceptable, then you can fall back on hard-coding of the literal values in those places where, say, a PL/SQL constant is not accepted, combined with a comment to make it easier to identify all occurrences of the value.&lt;/p&gt;
&lt;/div&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;WHERE mytab.boolean_column = 'Y' /*YES*/&lt;/font&gt;&lt;/div&gt;
&lt;/blockquote&gt;
&lt;p&gt;I would also put the same comment with explanation in my package, as in:&lt;/p&gt;
&lt;div&gt;&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;CREATE OR REPLACE PACKAGE app_config&lt;br /&gt;
IS&lt;br /&gt;
   -- YES value. If this value is ever changed, search for&lt;br /&gt;
   -- /*YES*/ and change the value there as well.&lt;br /&gt;
   c_yes   CONSTANT CHAR (1) := 'Y';&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;   -- NO value. If this value is ever changed, search for&lt;br /&gt;
   -- /*NO*/ and change the value there as well.&lt;br /&gt;
   c_no    CONSTANT CHAR (1) := 'N';&lt;br /&gt;
END app_config;&lt;br /&gt;
/&lt;/font&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I know, I know - it's ugly, it relies on the behavior and diligence of individual programmers, and it could lead to problems with out-of-synch views, but at least you now, theoretically, have a way to track down all the occurrences.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;Well, those are my ideas. I bet my readers have other ideas and critiques of what I wrote. So post a comment!&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;&lt;font size="5"&gt;&lt;font color="#4f81bd" size="4"&gt;Magic Values Table and Package Generation&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;p&gt;If you would like to try this approach, the following code should give you some ideas and, perhaps, a head start.&lt;/p&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;CREATE TABLE magic_values&lt;br /&gt;
(&lt;br /&gt;
   name          VARCHAR2 (1000)&lt;br /&gt;
 , identifier    VARCHAR2 (30)&lt;br /&gt;
 , magic_value    VARCHAR2 (1000)&lt;br /&gt;
 , datatype      VARCHAR2 (100)&lt;br /&gt;
)&lt;br /&gt;
/&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;BEGIN&lt;br /&gt;
   INSERT INTO magic_values&lt;br /&gt;
        VALUES ('Maximum Salary'&lt;br /&gt;
              , 'max_salary'&lt;br /&gt;
              , 10000000&lt;br /&gt;
              , 'NUMBER');&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;   INSERT INTO magic_values&lt;br /&gt;
        VALUES ('Company Name'&lt;br /&gt;
              , 'company_name'&lt;br /&gt;
              , 'Oracle Corporation'&lt;br /&gt;
              , 'VARCHAR2');&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;   INSERT INTO magic_values&lt;br /&gt;
        VALUES ('Earliest Date'&lt;br /&gt;
              , 'earliest_date'&lt;br /&gt;
              , '2000-10-11 12:10:00'&lt;br /&gt;
              , 'DATE');&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;   COMMIT;&lt;br /&gt;
END;&lt;br /&gt;
/&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;CREATE OR REPLACE FUNCTION magic_value_for (NAME_IN IN VARCHAR2)&lt;br /&gt;
   RETURN VARCHAR2&lt;br /&gt;
   RESULT_CACHE&lt;br /&gt;
IS&lt;br /&gt;
   l_return   magic_values.magic_value%TYPE;&lt;br /&gt;
BEGIN&lt;br /&gt;
   SELECT magic_value&lt;br /&gt;
     INTO l_return&lt;br /&gt;
     FROM magic_values mv&lt;br /&gt;
    WHERE mv.name = NAME_IN;&lt;br /&gt;
   RETURN l_return;&lt;br /&gt;
EXCEPTION&lt;br /&gt;
   WHEN NO_DATA_FOUND&lt;br /&gt;
   THEN&lt;br /&gt;
      RETURN NULL;&lt;br /&gt;
END magic_value_for;&lt;br /&gt;
/&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;CREATE OR REPLACE PROCEDURE gen_magic_values_pkg (&lt;br /&gt;
   NAME_IN        IN VARCHAR2 DEFAULT 'magic_values_mgr'&lt;br /&gt;
 , to_file_in     IN BOOLEAN DEFAULT FALSE&lt;br /&gt;
 , dir_in         IN VARCHAR2 DEFAULT 'DEMO'&lt;br /&gt;
 , ext_in         IN VARCHAR2 DEFAULT 'pkg'&lt;br /&gt;
 , date_mask_in   IN VARCHAR2 DEFAULT 'YYYY-MM-DD HH24:MI:SS')&lt;br /&gt;
IS&lt;br /&gt;
   c_to_screen   CONSTANT BOOLEAN := NVL (NOT to_file_in, TRUE);&lt;br /&gt;
   c_file        CONSTANT VARCHAR2 (1000) := NAME_IN || '.' || ext_in;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;   /*&lt;br /&gt;
   Array of output for package. First I fill up the array,&lt;br /&gt;
   then I dump it out to the requested location (screen or file).&lt;br /&gt;
   */&lt;br /&gt;
   TYPE lines_t IS TABLE OF VARCHAR2 (1000)&lt;br /&gt;
                      INDEX BY PLS_INTEGER;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;   output                 lines_t;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;   PROCEDURE add_to_output (str IN VARCHAR2)&lt;br /&gt;
   IS&lt;br /&gt;
   BEGIN&lt;br /&gt;
      output (output.COUNT + 1) := str;&lt;br /&gt;
   END;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;   PROCEDURE dump_output&lt;br /&gt;
   IS&lt;br /&gt;
   BEGIN&lt;br /&gt;
      IF c_to_screen&lt;br /&gt;
      THEN&lt;br /&gt;
         FOR indx IN output.FIRST .. output.LAST&lt;br /&gt;
         LOOP&lt;br /&gt;
            DBMS_OUTPUT.put_line (output (indx));&lt;br /&gt;
         END LOOP;&lt;br /&gt;
      ELSE&lt;br /&gt;
         -- Send output to the specified file.&lt;br /&gt;
         DECLARE&lt;br /&gt;
            fid   UTL_FILE.file_type;&lt;br /&gt;
         BEGIN&lt;br /&gt;
            fid := UTL_FILE.fopen (dir_in, c_file, 'W');&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;            FOR indx IN output.FIRST .. output.LAST&lt;br /&gt;
            LOOP&lt;br /&gt;
               UTL_FILE.put_line (fid, output (indx));&lt;br /&gt;
            END LOOP;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;            UTL_FILE.fclose (fid);&lt;br /&gt;
         EXCEPTION&lt;br /&gt;
            WHEN OTHERS&lt;br /&gt;
            THEN&lt;br /&gt;
               DBMS_OUTPUT.put_line (&lt;br /&gt;
                  'Failure to write output to ' || dir_in || '/' || c_file);&lt;br /&gt;
               UTL_FILE.fclose (fid);&lt;br /&gt;
         END;&lt;br /&gt;
      END IF;&lt;br /&gt;
   END dump_output;&lt;br /&gt;
BEGIN&lt;br /&gt;
   add_to_output ('CREATE OR REPLACE PACKAGE ' || NAME_IN);&lt;br /&gt;
   add_to_output ('IS ');&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;   FOR mv_rec IN (  SELECT *&lt;br /&gt;
                      FROM magic_values&lt;br /&gt;
                  ORDER BY name)&lt;br /&gt;
   LOOP&lt;br /&gt;
      add_to_output (&lt;br /&gt;
            '   FUNCTION '&lt;br /&gt;
         || mv_rec.identifier&lt;br /&gt;
         || ' RETURN '&lt;br /&gt;
         || mv_rec.datatype&lt;br /&gt;
         || ';');&lt;br /&gt;
   END LOOP;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;   add_to_output ('END ' || NAME_IN || ';');&lt;br /&gt;
   add_to_output ('/');&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;
&lt;font face="Courier New"&gt;   add_to_output ('CREATE OR REPLACE PACKAGE BODY ' || NAME_IN);&lt;br /&gt;
   add_to_output ('IS ');&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;   FOR mv_rec IN (  SELECT *&lt;br /&gt;
                      FROM magic_values&lt;br /&gt;
                  ORDER BY name)&lt;br /&gt;
   LOOP&lt;br /&gt;
      add_to_output (&lt;br /&gt;
         '   FUNCTION ' || mv_rec.identifier || ' RETURN ' || mv_rec.datatype);&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;      add_to_output (&lt;br /&gt;
         '   IS BEGIN RETURN '&lt;br /&gt;
         || CASE mv_rec.datatype&lt;br /&gt;
               WHEN 'VARCHAR2'&lt;br /&gt;
               THEN&lt;br /&gt;
                  '''' || mv_rec.magic_value || ''''&lt;br /&gt;
               WHEN 'NUMBER'&lt;br /&gt;
               THEN&lt;br /&gt;
                  mv_rec.magic_value&lt;br /&gt;
               WHEN 'DATE'&lt;br /&gt;
               THEN&lt;br /&gt;
                     'TO_DATE ('&lt;br /&gt;
                  || ''''&lt;br /&gt;
                  || mv_rec.magic_value&lt;br /&gt;
                  || ''', '''&lt;br /&gt;
                  || date_mask_in&lt;br /&gt;
                  || ''')'&lt;br /&gt;
            END&lt;br /&gt;
         || '; END;');&lt;br /&gt;
      add_to_output ('   ');&lt;br /&gt;
   END LOOP;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;   add_to_output ('END ' || NAME_IN || ';');&lt;br /&gt;
   add_to_output ('/');&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;   dump_output;&lt;br /&gt;
END gen_magic_values_pkg;&lt;br /&gt;
/&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;BEGIN&lt;br /&gt;
   gen_magic_values_pkg ();&lt;br /&gt;
END;&lt;br /&gt;
/&lt;/font&gt;&lt;/p&gt;
&lt;/blockquote&gt;&lt;br /&gt;&lt;a href=http://www.toadworld.com/Blogs/tabid/67/EntryId/744/Avoiding-Hard-coded-Values-in-Views.aspx&gt;More ...&lt;/a&gt;&lt;div class="tags"&gt;Tags: plsql,literals,hard-code,package,constant,function,application context&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/744/Avoiding-Hard-coded-Values-in-Views.aspx</guid>
      <pubDate>Thu, 15 Sep 2011 12:59:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=744</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/260/Default.aspx">literals</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/261/Default.aspx">hard-code</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/164/Default.aspx">package</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/262/Default.aspx">constant</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/253/Default.aspx">function</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/263/Default.aspx">application context</blog:tag>
    </item>
    <item>
      <title>APEX Support in Toad</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/735/APEX-Support-in-Toad.aspx</link>
      <description>&lt;div&gt;Quest is exploring whether to and how best to add support for Oracle Application Express in Toad for Oracle.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;More and more Oracle technologists are building websites in APEX technology. It is moving rapidly from the sidelines of departmental applications to the mainstream of robust, public and private websites implementing mission critical applications involving many users. For example, my PL/SQL Challenge website, offering daily, weekly and monthly quizzes on Oracle technology, is built on APEX.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Hundreds of thousands of these same technologists also spend lots of their time in Toad for Oracle, building out the backend elements (tables, packages, etc.). We at Quest Software believe that Toad for Oracle should be able to help APEX developers understand, analyze, maintain and even enhance their applications from.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;We also, realize, however, that there is an enormous range and depth of experience with APEX "out there." So rather than just come up with a list of features we &lt;em&gt;think&lt;/em&gt; would be helpful to APEX developers, we'd like to hear from &lt;em&gt;you, &lt;/em&gt;the APEX developer and also development DBAs supporting APEX developers, about how you think Toad for Oracle can best support your work with APEX.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;You can do so by responding to this blog post. You can also email me directly at &lt;a href="http://www.toadworld.commailto:steven.feuerstein@quest.com"&gt;steven.feuerstein@quest.com&lt;/a&gt;. I will be compiling requests and requirements for consideration by the Toad for Oracle Product Manager and development team.&lt;/div&gt;&lt;br /&gt;&lt;a href=http://www.toadworld.com/Blogs/tabid/67/EntryId/735/APEX-Support-in-Toad.aspx&gt;More ...&lt;/a&gt;&lt;div class="tags"&gt;Tags: toad,toad for oracle,apex;&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/1/Default.aspx&gt;Toad for Oracle&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/1/Default.aspx">Toad for Oracle</category>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/735/APEX-Support-in-Toad.aspx</guid>
      <pubDate>Tue, 23 Aug 2011 19:42:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=735</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/6/Default.aspx">toad</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/10/Default.aspx">toad for oracle</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/257/Default.aspx">apex;</blog:tag>
    </item>
    <item>
      <title>One Way Out of Functions</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/724/One-Way-Out-of-Functions.aspx</link>
      <description>&lt;div style="margin: 0in 0in 10pt"&gt;I received this request from a reader in July:&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;"Could you please explain why Oracle recommends that we &lt;em&gt;not&lt;/em&gt; use OUT/IN-OUT parameters in functions?"&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Actually, it's not just Oracle. Most "gurus" in the software world make the same suggestion. There are two key reasons for the recommendation that you should only return data through the RETURN clause of a function, not the parameter list. I sum up these answers here, and then I offer a section from &lt;a href="http://oreilly.com/catalog/9780596514105"&gt;Oracle PL/SQL Best Practices, 2&lt;sup&gt;nd&lt;/sup&gt; edition&lt;/a&gt;, that explores the same topic using the "story" style of that book.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Two key reasons to use only IN parameters with functions:&lt;/div&gt;
&lt;ol&gt;
    &lt;li&gt;
    &lt;div style="margin: 0in 0in 10pt"&gt;The whole point of a function is to &lt;em&gt;return&lt;/em&gt; a value (whether it’s a single, scalar value or a composite, such as a record or a collection). If you also return data back through the parameter list with OUT or IN OUT arguments, the purpose and usage of the function will be obscured.&lt;/div&gt;
    &lt;/li&gt;
    &lt;li&gt;
    &lt;div style="margin: 0in 0in 10pt"&gt;
    &lt;p&gt;A function that contains an OUT or IN OUT parameter cannot be called from within a SQL statement. Here's an example:&lt;/p&gt;
    &lt;p&gt;&lt;img alt="" width="422" height="256" src="/Portals/0/blogimages/Steven Feuerstein/SF-Blog-080911-1.png" /&gt;&lt;/p&gt;
    &lt;/div&gt;
    &lt;/li&gt;
&lt;/ol&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Perhaps you don't often run across the need to call your own application-specific functions inside SQL. I take advantage of this feature frequently in the backend and APEX code of the &lt;a href="http://www.plsqlchallenge.com/"&gt;PL/SQL Challenge&lt;/a&gt;, a site that offers quizzes on PL/SQL, SQL and APEX.&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;So remember: just because Oracle let's you do something (like define an OUT parameter in a function's parameter list), doesn't mean that you &lt;em&gt;should&lt;/em&gt; do it!&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;And now an excerpt from &lt;a href="http://oreilly.com/catalog/9780596514105"&gt;Oracle PL/SQL Best Practices, 2&lt;sup&gt;nd&lt;/sup&gt; edition&lt;/a&gt; (Chapter 8, "Playing with Blocks"):&lt;/div&gt;
&lt;div style="margin: 12pt 0in 8pt"&gt;&lt;strong&gt;&lt;font color="#ff0000" size="4"&gt;Where'd that data come from?&lt;br /&gt;
AKA: Functions should return data only through the RETURN clause.&lt;/font&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;div style="margin: 8pt 0in 4pt"&gt;&lt;strong&gt;&lt;font size="4"&gt;&lt;font color="#ff0000" size="2"&gt;Problem: Jasper returns data in a very confusing manner.&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;div style="margin: 6pt 0in"&gt;&lt;font size="2"&gt;Jasper needs a program to retrieve several pieces of information about an excuse: the title, the author and the word count. In just a few moments he builds the following function:&lt;/font&gt;&lt;/div&gt;
&lt;div style="border-bottom: medium none; border-left: windowtext 1pt solid; padding-bottom: 0in; padding-left: 2pt; padding-right: 0in; margin-left: 0.25in; border-top: medium none; margin-right: -67.7pt; border-right: medium none; padding-top: 0in"&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;&lt;font color="#008000" size="2" face="Courier New"&gt;FUNCTION excuse_title (&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;&lt;font color="#008000"&gt;&lt;font size="2" face="Courier New"&gt;   excuse_id_in IN mfe_excuse.isbn%TYPE&lt;/font&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;&lt;font color="#008000"&gt;&lt;font size="2" face="Courier New"&gt; , author_out OUT mfe_excuse.author%TYPE&lt;/font&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;&lt;font color="#008000"&gt;&lt;font size="2" face="Courier New"&gt; , word_count_out OUT mfe_excuse.word_count%TYPE)&lt;/font&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;&lt;font color="#008000" size="2" face="Courier New"&gt;RETURN mfe_excuse.title%TYPE&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;&lt;font color="#008000" size="2" face="Courier New"&gt;IS BEGIN &lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;&lt;font color="#008000"&gt;&lt;font size="2" face="Courier New"&gt;   ... implementation unimportant! ... &lt;/font&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;&lt;font color="#008000" size="2" face="Courier New"&gt;END excuse_title;&lt;/font&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div style="margin: 6pt 0in"&gt;&lt;font size="2"&gt;And then he puts this function to use as follows:&lt;/font&gt;&lt;/div&gt;
&lt;div style="border-bottom: medium none; border-left: windowtext 1pt solid; padding-bottom: 0in; padding-left: 2pt; padding-right: 0in; margin-left: 0.25in; border-top: medium none; margin-right: -67.7pt; border-right: medium none; padding-top: 0in"&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;&lt;font color="#008000" size="2" face="Courier New"&gt;PROCEDURE process_excuse (excuse_id_in IN mfe_excuse.isbn%TYPE)&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;&lt;font color="#008000" size="2" face="Courier New"&gt;IS&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;&lt;font color="#008000"&gt;&lt;font size="2" face="Courier New"&gt; l_title mfe_excuse.title%TYPE;&lt;/font&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;&lt;font color="#008000"&gt;&lt;font size="2" face="Courier New"&gt; l_author mfe_excuse.author%TYPE;&lt;/font&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;&lt;font color="#008000"&gt;&lt;font size="2" face="Courier New"&gt; l_word_count mfe_excuse.word_count%TYPE;&lt;/font&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;&lt;font color="#008000" size="2" face="Courier New"&gt;BEGIN&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;&lt;font color="#008000"&gt;&lt;font size="2" face="Courier New"&gt;   l_title := excuse_title (l_id, l_author, l_word_count);&lt;/font&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;&lt;font color="#008000"&gt;&lt;font size="2" face="Courier New"&gt;   ...&lt;/font&gt;&lt;/font&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div style="margin: 6pt 0in"&gt;&lt;font size="2"&gt;Jasper is proud that he took the time to put this retrieval logic into its own program. Now it can be used in many places in the application. He shows everyone excuse_title at the weekly code review session. Imagine his dismay when Delaware snorts:&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 4pt 0.25in"&gt;&lt;font color="#008080" size="2"&gt;Humph. Well, Jasper, it's absolutely peachy keen that you wrote a reusable function. But that is not a program I would ever want to use. The name says you are giving me a title, and you are, but then you are also passing back all that other stuff. It's self-contradictory &lt;em&gt;and&lt;/em&gt; I have to declare a bunch of individual variables to use the darned thing!&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 6pt 0in"&gt;&lt;font size="2"&gt;Jasper pouts; he was so looking forward to a pat or two on the back. Sunita gives Delaware a dirty look and shakes her head. "Jasper," she says, drawing his attention away from Delaware's gloomy outlook, "hiding the lookup was an excellent move. You just need to take a step or two further, and make sure there are no mixed messages. Let's redesign excuse_title together."&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 8pt 0in 4pt"&gt;&lt;strong&gt;&lt;font size="4"&gt;&lt;font color="#ff0000" size="2"&gt;Solution: Return multiple values through a single, composite structure or with a procedure.&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;div style="margin: 6pt 0in"&gt;&lt;font size="2"&gt;Here are the steps that Sunita takes to revamp the lookup function and make it more useful:&lt;/font&gt;&lt;/div&gt;
&lt;ul&gt;
    &lt;li&gt;
    &lt;div style="margin: 4pt 0in 4pt 0.25in"&gt;&lt;font size="2"&gt;&lt;em&gt;&lt;font color="#ff0000"&gt;Make sure the name of the program reflects what it does:&lt;/font&gt;&lt;/em&gt;&lt;font color="#000080"&gt; In this case, the program doesn't return just the title; it returns several pieces of information about an excuse. Let's call it the "excuse_info" function.&lt;/font&gt;&lt;/font&gt;&lt;/div&gt;
    &lt;/li&gt;
    &lt;li&gt;
    &lt;div style="margin: 4pt 0in 4pt 0.25in"&gt;&lt;font size="2"&gt;&lt;em&gt;&lt;font color="#ff0000"&gt;Pass everything in the RETURN clause:&lt;/font&gt;&lt;/em&gt;&lt;font color="#000080"&gt; Rather than returning one value through the RETURN clause and another through the parameter list, let's pass everything back in the RETURN clause, using a composite structure—in this case, a record.&lt;/font&gt;&lt;/font&gt;&lt;/div&gt;
    &lt;/li&gt;
&lt;/ul&gt;
&lt;div style="margin: 6pt 0in"&gt;&lt;font size="2"&gt;Here, then, is the new header of the program:&lt;/font&gt;&lt;/div&gt;
&lt;div style="border-bottom: medium none; border-left: windowtext 1pt solid; padding-bottom: 0in; padding-left: 2pt; padding-right: 0in; margin-left: 0.25in; border-top: medium none; margin-right: -67.7pt; border-right: medium none; padding-top: 0in"&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;&lt;font color="#008000" size="2" face="Courier New"&gt;FUNCTION excuse_info (id_in IN mfe_excuse.id%TYPE)&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;&lt;font color="#008000"&gt;&lt;font size="2" face="Courier New"&gt;   RETURN mfe_excuse%ROWTYPE&lt;/font&gt;&lt;/font&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div style="margin: 6pt 0in"&gt;&lt;font size="2"&gt;And here is the revised &lt;em&gt;usage&lt;/em&gt; of this function:&lt;/font&gt;&lt;/div&gt;
&lt;div style="border-bottom: medium none; border-left: windowtext 1pt solid; padding-bottom: 0in; padding-left: 2pt; padding-right: 0in; margin-left: 0.25in; border-top: medium none; margin-right: -67.7pt; border-right: medium none; padding-top: 0in"&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;&lt;font color="#008000" size="2" face="Courier New"&gt;PROCEDURE process_excuse (excuse_id_in IN mfe_excuse.isbn%TYPE)&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;&lt;font color="#008000" size="2" face="Courier New"&gt;IS&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;&lt;font color="#008000"&gt;&lt;font size="2" face="Courier New"&gt;   l_excuse mfe_excuse%ROWTYPE;&lt;/font&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;&lt;font color="#008000" size="2" face="Courier New"&gt;BEGIN&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;&lt;font color="#008000"&gt;&lt;font size="2" face="Courier New"&gt;   l_excuse := excuse_info (l_id);&lt;/font&gt;&lt;/font&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div style="margin: 6pt 0in"&gt;&lt;font size="2"&gt;Now the code is leaner and cleaner. Everything that is returned by the function is deposited into a single record. And if you are concerned about returning all the data in a table's row, when you need only a small subset of its columns, you can always create your own user-defined record, as shown here:&lt;/font&gt;&lt;/div&gt;
&lt;div style="border-bottom: medium none; border-left: windowtext 1pt solid; padding-bottom: 0in; padding-left: 2pt; padding-right: 0in; margin-left: 0.25in; border-top: medium none; margin-right: -67.7pt; border-right: medium none; padding-top: 0in"&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;&lt;font color="#008000" size="2" face="Courier New"&gt;PACKAGE excuse_pkg&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;&lt;font color="#008000" size="2" face="Courier New"&gt;IS&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;&lt;font color="#008000"&gt;&lt;font size="2" face="Courier New"&gt;   TYPE key_info IS RECORD (&lt;/font&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;&lt;font color="#008000"&gt;&lt;font size="2" face="Courier New"&gt;      title mfe_excuse.title%TYPE&lt;/font&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;&lt;font color="#008000"&gt;&lt;font size="2" face="Courier New"&gt;    , author mfe_excuse.author%TYPE&lt;/font&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;&lt;font color="#008000"&gt;&lt;font size="2" face="Courier New"&gt;    , word_count mfe_excuse.word_count%TYPE&lt;/font&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;&lt;font color="#008000"&gt;&lt;font size="2" face="Courier New"&gt;   );&lt;/font&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;&lt;font face="Courier New"&gt; &lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;&lt;font color="#008000"&gt;&lt;font size="2" face="Courier New"&gt;   FUNCTION excuse_info (id_in IN mfe_excuse.id%TYPE)&lt;/font&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;&lt;font color="#008000"&gt;&lt;font size="2" face="Courier New"&gt;      RETURN key_info;&lt;/font&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;&lt;font color="#008000" size="2" face="Courier New"&gt;END excuse_pkg;&lt;/font&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div style="margin: 6pt 0in"&gt;&lt;font size="2"&gt;To sum up: the whole point of a function is to return a value (whether it’s a single, scalar value or a composite, such as a record or a collection). If you also return data back through the parameter list with OUT or IN OUT arguments, the purpose and usage of the function will be obscured. &lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 6pt 0in"&gt;&lt;font size="2"&gt;If you need to return multiple pieces of information, take one of the following approaches: &lt;/font&gt;&lt;/div&gt;
&lt;ul&gt;
    &lt;li&gt;
    &lt;div style="margin: 6pt 0in 0pt"&gt;&lt;font color="#008000" size="2"&gt;Return a record or collection of values &lt;br /&gt;
    &lt;/font&gt;&lt;font color="#008000" size="2"&gt;&lt;br /&gt;
    Make sure to publish the structure of your record or collection (the TYPE statement) in a package specification so that developers can understand and use the function more easily. &lt;br /&gt;
    &lt;/font&gt;&lt;/div&gt;
    &lt;/li&gt;
    &lt;li&gt;
    &lt;div style="margin: 6pt 0in 0pt"&gt;&lt;font color="#008000" size="2"&gt;Break up a single function into multiple functions, all returning scalar values&lt;br /&gt;
    &lt;/font&gt;&lt;font color="#008000" size="2"&gt;&lt;br /&gt;
    With this approach, you can call the functions from within SQL statements. &lt;br /&gt;
     &lt;/font&gt;&lt;/div&gt;
    &lt;/li&gt;
    &lt;li&gt;
    &lt;div style="margin: 6pt 0in 0pt"&gt;&lt;font color="#008000" size="2"&gt;Change a function into a procedure&lt;br /&gt;
    &lt;/font&gt;&lt;font color="#008000" size="2"&gt;&lt;br /&gt;
    Unless you need to call a function to return this information, just change it to a procedure returning multiple pieces of information through the OUT arguments in the parameter list&lt;/font&gt;&lt;/div&gt;
    &lt;/li&gt;
&lt;/ul&gt;
&lt;div style="margin: 6pt 0in"&gt;&lt;font size="2"&gt;If you follow these guidelines, your subprograms will be more likely to be used and reused, because they will be defined in ways that make them easy to understand and apply in your own code. &lt;/font&gt;&lt;/div&gt;
&lt;div style="margin: 0in 0in 10pt"&gt; &lt;/div&gt;&lt;br /&gt;&lt;a href=http://www.toadworld.com/Blogs/tabid/67/EntryId/724/One-Way-Out-of-Functions.aspx&gt;More ...&lt;/a&gt;&lt;div class="tags"&gt;Tags: plsql,function,parameters&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/724/One-Way-Out-of-Functions.aspx</guid>
      <pubDate>Tue, 09 Aug 2011 13:56:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=724</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/253/Default.aspx">function</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/254/Default.aspx">parameters</blog:tag>
    </item>
    <item>
      <title>QuickTips: Using BULK COLLECT with Queries</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/712/QuickTips-Using-BULK-COLLECT-with-Queries.aspx</link>
      <description>&lt;p&gt;Oracle introduced a significant enhancement to PL/SQL’s SQL-related capabilities with the FORALL statement and BULK COLLECT clause for queries. Together, these are referred to as &lt;em&gt;bulk processing&lt;/em&gt; statements for PL/SQL. Why, you might wonder, would this be necessary? We all know that PL/SQL is tightly integrated with the underlying SQL engine in the Oracle database. PL/SQL is &lt;em&gt;the&lt;/em&gt; database programming language of choice for Oracle—even though you can now use Java inside the database as well.&lt;/p&gt;
&lt;p&gt;But this tight integration does not mean that there is no overhead associated with running SQL from a PL/SQL program. When the PL/SQL runtime engine processes a block of code, it executes the procedural statements within its own engine, but passes the SQL statements on to the SQL engine. The SQL layer executes the SQL statements and then returns information to the PL/SQL engine, if necessary.&lt;/p&gt;
&lt;p&gt;This transfer of control between the PL/SQL and SQL engines is called a &lt;em&gt;context switch&lt;/em&gt;. Each time a switch occurs, there is additional overhead. There are a number of scenarios in which many switches occur and performance degrades. As you can see, PL/SQL and SQL might be tightly integrated on the syntactic level, but "under the covers" the integration is not as tight as it could be.&lt;/p&gt;
&lt;p&gt;With FORALL and BULK COLLECT, however, you can fine-tune the way these two engines communicate, effectively telling the PL/SQL engine to compress multiple context switches into a single switch, thereby improving the performance of your applications. &lt;/p&gt;&lt;div class="tags"&gt;Tags: oracle,plsql,bulk collect,forall&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/712/QuickTips-Using-BULK-COLLECT-with-Queries.aspx#Comments</comments>
      <slash:comments>0</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/712/QuickTips-Using-BULK-COLLECT-with-Queries.aspx</guid>
      <pubDate>Wed, 13 Jul 2011 12:36:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=712</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/2/Default.aspx">oracle</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/54/Default.aspx">bulk collect</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/130/Default.aspx">forall</blog:tag>
    </item>
    <item>
      <title>Use Forward References in Package Bodies?</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/696/Use-Forward-References-in-Package-Bodies.aspx</link>
      <description>&lt;div&gt;
&lt;p&gt;A PL/SQL developer (let's call him Dan) sent me this request last week:&lt;/p&gt;
&lt;/div&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;div&gt;=============================================================&lt;/div&gt;
&lt;div&gt;Would you please settle a minor argument for me? We're trying to institute coding standards at my company.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;I've been pushing for developers to put explicit declarations of private functions and procedures in their packages. My co-workers argue back that they are unnecessary. Other than giving us the ability to reorganize the source as we see fit, I can't find anything that states additional benefits of using them. However, as I've always used them, I feel uncomfortable not asking for them.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Here's an example of how I use them:&lt;/div&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;CREATE OR REPLACE PACKAGE BODY my_sample_package&lt;br /&gt;
IS&lt;br /&gt;
&lt;font color="#339966"&gt;   --===========================================&lt;br /&gt;
   -- PRIVATE DECLARATIONS&lt;br /&gt;
   --===========================================&lt;br /&gt;
&lt;/font&gt;   FUNCTION my_private_function_f (p_parm1_in IN NUMBER)&lt;br /&gt;
      RETURN BOOLEAN;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;   PROCEDURE my_private_proc_p (&lt;br /&gt;
       p_parm1_in IN NUMBER, p_parm2_in IN NUMBER);&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;font color="#339966"&gt;   --===========================================&lt;br /&gt;
   -- PRIVATE SOURCE&lt;br /&gt;
   --===========================================&lt;br /&gt;
&lt;/font&gt;   FUNCTION my_private_function_f (p_parm1_in IN NUMBER)&lt;br /&gt;
      RETURN BOOLEAN&lt;br /&gt;
   IS&lt;br /&gt;
   BEGIN&lt;br /&gt;
      IF p_parm1_in &gt; 0&lt;br /&gt;
      THEN&lt;br /&gt;
         RETURN TRUE;&lt;br /&gt;
      ELSE&lt;br /&gt;
         RETURN FALSE;&lt;br /&gt;
      END IF;&lt;br /&gt;
   END my_private_function_f;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;   PROCEDURE my_private_proc_p (&lt;br /&gt;
       p_parm1_in IN NUMBER, p_parm2_in IN NUMBER)&lt;br /&gt;
   IS&lt;br /&gt;
      l_my_var   NUMBER;&lt;br /&gt;
   BEGIN&lt;br /&gt;
      IF p_parm1_in &gt; 0&lt;br /&gt;
      THEN&lt;br /&gt;
         l_my_var := p_parm2_in / p_parm1_in;&lt;br /&gt;
      END IF;&lt;br /&gt;
   END;&lt;br /&gt;
   &lt;br /&gt;
&lt;font color="#339966"&gt;   --===========================================&lt;br /&gt;
   -- PUBLIC SOURCE&lt;br /&gt;
   --===========================================&lt;br /&gt;
   -- Blah&lt;br /&gt;
   -- Blah&lt;br /&gt;
&lt;/font&gt;END my_sample_package;&lt;/font&gt;&lt;/div&gt;
&lt;/blockquote&gt;
&lt;div&gt;Can you give me any reasons why or why not private declarations should be used?&lt;/div&gt;
&lt;div&gt;=============================================================&lt;/div&gt;
&lt;/blockquote&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;What Dan calls a "private declaration" is commonly referred to as a &lt;em&gt;forward reference&lt;/em&gt;, also known as a &lt;em&gt;forward declaration&lt;/em&gt;, which is defined by &lt;a href="http://en.wikipedia.org/wiki/Forward_declaration"&gt;Wikipedia&lt;/a&gt; as:&lt;/div&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;div&gt;In &lt;a title="Computer programming" href="http://en.wikipedia.org/wiki/Computer_programming"&gt;computer programming&lt;/a&gt;, a &lt;strong&gt;forward declaration&lt;/strong&gt; is a &lt;a title="Declaration (computer science)" href="http://en.wikipedia.org/wiki/Declaration_%28computer_science%29"&gt;declaration&lt;/a&gt; of an &lt;a title="Identifier" href="http://en.wikipedia.org/wiki/Identifier"&gt;identifier&lt;/a&gt; (denoting an entity such as a type, a variable, or a function) for which the programmer has not yet given a complete &lt;a title="Definition" href="http://en.wikipedia.org/wiki/Definition"&gt;definition&lt;/a&gt;.&lt;/div&gt;
&lt;/blockquote&gt;
&lt;div&gt;
&lt;p&gt;As you can see in the code example, the section under "PRIVATE DECLARATIONS" contain the forward declarations: just the headers of the subprograms without their implementation, same as you would find in the package specification.&lt;/p&gt;
&lt;p&gt;I do not use forward declarations in my code in any sort of routine way. I only use them when they are &lt;em&gt;required&lt;/em&gt; - and that happens when two programs are inter-dependent (A calls B and B calls A). In this scenario, my code will not compile &lt;em&gt;without&lt;/em&gt; forward declarations. But that is quite the rare occurrence.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;The problem with using forward declarations routinely is that it introduces another kind of redundancy into my code. When and if the parameter list of a private subprogram changes, I have to change it in both places (forward declaration and actual definition of the subprogram). I'd really rather not have to do that if I do not need to.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;So instead I rely on the compiler to tell me when my subprograms are "out of order", and I cut and paste the entire subprogram to an earlier point in the package body to make sure that all references can be resolved.&lt;/p&gt;
&lt;p&gt;Well, that's my viewpoint on forward declarations. What do you think?&lt;/p&gt;
&lt;/div&gt;&lt;br /&gt;&lt;a href=http://www.toadworld.com/Blogs/tabid/67/EntryId/696/Use-Forward-References-in-Package-Bodies.aspx&gt;More ...&lt;/a&gt;&lt;div class="tags"&gt;Tags: plsql,forward declaration&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/696/Use-Forward-References-in-Package-Bodies.aspx#Comments</comments>
      <slash:comments>5</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/696/Use-Forward-References-in-Package-Bodies.aspx</guid>
      <pubDate>Mon, 06 Jun 2011 19:52:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=696</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/227/Default.aspx">forward declaration</blog:tag>
    </item>
    <item>
      <title>Write Tiny Little Chunks of Code - or Maybe Not</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/692/Write-Tiny-Little-Chunks-of-Code-or-Maybe-Not.aspx</link>
      <description>&lt;div&gt;
&lt;p&gt;I have for many years now promoted "Write tiny little chunks of code" as one of the most impactful and important steps we can all take to improve the readability and maintainability of code. The basic idea is that you should not let your executable sections get to be more than 50 or 60 lines of code in length. You should, in other words, be able to at a single glance take in the full algorithm/logical flow of the subprogram. Compare that to a procedure whose executable section goes on and on for hundreds of lines. Sure, you can page through all that, but how easy is it to step back and gain an overall understanding of what the module does?&lt;/p&gt;
&lt;p&gt;The best way to achieve this goal is to modularize one's code: hide detailed logic behind a &lt;em&gt;name&lt;/em&gt; and then reference that logic by calling the procedure with that name. The name describes what is going on "under the covers"; you only drill down into the procedure as needed.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;You can modularize at any of thse levels:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Schema-level procedure or function: defined outside of a package, callable by any schema with execute authority on that module. I generally recommend against these. Put all your code in packages; easier to find, manage, enhance.&lt;/li&gt;
    &lt;li&gt;Packaged subprograms: this is the main method of modularization. You define a set of programs in the package specification that will be used by other subprograms in the appliation. You can also define &lt;em&gt;private&lt;/em&gt; subprograms that can only be called by other subprograms in that package.&lt;/li&gt;
    &lt;li&gt;Local or nested subprograms: a procedure or function that is defined in the declaration section of a PL/SQL block (anonymous or named). This module is considered local because it is defined only within the parent PL/SQL block. It cannot be called by any other PL/SQL blocks defined outside that enclosing block.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following anonymous block, for example, declares a local&lt;span&gt;  procedure:&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;p&gt;&lt;font color="#008000" size="2"&gt;&lt;font face="Courier New"&gt;DECLARE&lt;br /&gt;
   PROCEDURE show_date (date_in IN DATE) IS&lt;br /&gt;
   BEGIN&lt;br /&gt;
      DBMS_OUTPUT.PUT_LINE (TO_CHAR (date_in, 'Month DD, YYYY');&lt;br /&gt;
   END show_date;&lt;br /&gt;
BEGIN&lt;br /&gt;
   show_date (SYSDATE);&lt;br /&gt;
   show_date (SYSDATE+30);&lt;br /&gt;
END ;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p dir="ltr"&gt;I think that nested subprograms are one of the most powerful and underutilized techniques in the PL/SQL developer community. I use them all the time, all over the place. There are two central benefits to nested subprograms (aka, local modules):&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;font color="#ff0000" size="2"&gt;Reduce the size of the module by stripping it of repetitive code&lt;/font&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;div&gt;&lt;font color="#008000" size="2"&gt;Code reduction leads to higher code quality because you have fewer lines to test and fewer potential bugs. It takes less effort to maintain the code because there is less to maintain. And when you do have to make a change, you make it in one place in the local module, and the effects are felt immediately throughout the parent module.&lt;/font&gt;&lt;/div&gt;
&lt;/blockquote&gt;
&lt;p&gt; &lt;em&gt;&lt;font color="#ff0000" size="2"&gt;Improve the readability of your code&lt;/font&gt;&lt;/em&gt;&lt;/p&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;div&gt;&lt;font color="#008000" size="2"&gt;Even if you do not repeat sections of code within a module, you still may want to pull out a set of related statements and package them into a local module. This can make it easier to follow the logic of the main body of the parent module.&lt;/font&gt;&lt;/div&gt;
&lt;/blockquote&gt;
&lt;p&gt;When making use of lots of nested subprograms, your executable section becomes small and transparent in meaning. I will run through an example and then leave it to my readers to respond. The reason I say this is that I wrote this posting in response to a developer, who wrote to me as follows:&lt;/p&gt;
&lt;div&gt;&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;p&gt;"I would like to have a posting to discuss local sub programs or functions within a function or procedure. This could be a good debate because I have my issues on the subject but I was watching the "Say no to spaghetti code, say yes to Extreme Modularization" video and Steven was promoting that kind of programming."&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;There are certainly potential downsides to nested subprograms; you can "go overboard," as with any other technique or feature. But I certainly would be more worried about inadequate modularization and the resulting spaghetti code, rather than overdoing it.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;&lt;font size="5"&gt;&lt;font color="#4f81bd" size="4"&gt;An Example&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;Suppose my team is building a support application. Customers call with problems, and we put their call in a queue if it cannot be handled immediately. I must now write a program that distributes unhandled calls out to members of the support team. While there are still unhandled calls in the queue, assign them to employees who are under-utilized (have fewer calls assigned to them then the average for their department). The technical specifications run to 50 pages of detailed documentation, and I could just "start coding" - transcribing specs into code. Instead, I translate the "executive summary" into the following tiny little program.&lt;/p&gt;
&lt;/div&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;PROCEDURE distribute_calls (&lt;br /&gt;
   department_id_in IN employees.department_id%TYPE&lt;br /&gt;
)&lt;br /&gt;
IS&lt;br /&gt;
BEGIN&lt;br /&gt;
   WHILE (calls_still_unhandled ())&lt;br /&gt;
   LOOP&lt;br /&gt;
      FOR emp_rec IN support_dept_cur (department_id_in)&lt;br /&gt;
      LOOP&lt;br /&gt;
         IF call_analysis.current_caseload (emp_rec.employee_id) &lt;&lt;br /&gt;
            call_analysis.avg_caseload_for_dept (department_id_in)&lt;br /&gt;
         THEN&lt;br /&gt;
            assign_next_open_call_to (emp_rec.employee_id, l_case_id);&lt;br /&gt;
            notify_customer (l_case_id);&lt;br /&gt;
         END IF;&lt;br /&gt;
      END LOOP;&lt;br /&gt;
   END LOOP;&lt;br /&gt;
END distribute_calls;&lt;/font&gt;&lt;/div&gt;
&lt;/blockquote&gt;
&lt;div&gt;This executable section contains calls to predefined programs in the call_analysis, but also I simply come up with names for subprograms for other areas of functionality that are not yet implemented.&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;I then create stubs for the yet-to-be-defined programs:&lt;/p&gt;
&lt;/div&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;PROCEDURE distribute_calls (&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;   &lt;/span&gt;department_id_in IN employees.department_id%TYPE&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;)&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;IS&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;   &lt;/span&gt;l_case_id&lt;span&gt;   &lt;/span&gt;cases.ID%TYPE;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt; &lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;   &lt;/span&gt;CURSOR support_dept_cur (&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;      &lt;/span&gt;department_id_in IN employees.department_id%TYPE&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;   &lt;/span&gt;)&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;   &lt;/span&gt;IS&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;      &lt;/span&gt;SELECT *&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;        &lt;/span&gt;FROM employees&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;       &lt;/span&gt;WHERE department_id = department_id_in;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt; &lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;   &lt;/span&gt;FUNCTION calls_still_unhandled&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;      &lt;/span&gt;RETURN BOOLEAN&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;   &lt;/span&gt;IS&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;   &lt;/span&gt;BEGIN&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;font face="Courier New"&gt;      &lt;/font&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;          RETURN&lt;/span&gt; NULL;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;   &lt;/span&gt;END calls_still_unhandled;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt; &lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;   &lt;/span&gt;PROCEDURE assign_next_open_call_to (&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;      &lt;/span&gt;employee_id_in IN employees.employee_id%TYPE&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;    &lt;/span&gt;, case_id_out OUT cases.ID%TYPE&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;   &lt;/span&gt;)&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;   &lt;/span&gt;IS&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;   &lt;/span&gt;BEGIN&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;font face="Courier New"&gt;     NULL;&lt;/font&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;   &lt;/span&gt;END assign_next_open_call_to;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt; &lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;   &lt;/span&gt;PROCEDURE notify_customer (case_id_in IN cases.ID%TYPE)&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;   &lt;/span&gt;IS&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;   &lt;/span&gt;BEGIN&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;      NULL&lt;/span&gt;;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;   &lt;/span&gt;END notify_customer;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;BEGIN&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;   &lt;/span&gt;WHILE (calls_still_unhandled ())&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;   &lt;/span&gt;LOOP&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;      &lt;/span&gt;FOR emp_rec IN support_dept_cur (department_id_in)&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;      &lt;/span&gt;LOOP&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;         &lt;/span&gt;IF call_analysis.current_caseload (emp_rec.employee_id) &lt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;                    &lt;/span&gt;call_analysis.avg_caseload_for_dept (department_id_in)&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;         &lt;/span&gt;THEN&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;            &lt;/span&gt;assign_next_open_call_to (emp_rec.employee_id, l_case_id);&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;            &lt;/span&gt;notify_customer (l_case_id);&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;         &lt;/span&gt;END IF;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;      &lt;/span&gt;END LOOP;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;   &lt;/span&gt;END LOOP;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;END distribute_calls;&lt;/font&gt;&lt;/div&gt;
&lt;/blockquote&gt;
&lt;div&gt;I can now drill down into each nested subprogram and do the same thing: write the "executive summary," dream up new subprograms "on the fly" and delay worrying about the implementation details until I get down to that level.&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;This approach lets me focus on logic flow, makes it easier to identify - proactively - opportunities for code reuse, and results in code that is so very easy to read.&lt;/p&gt;
&lt;p&gt;I am pretty well addicted to nested subprograms, but I fear that not everyone shares my passion on this topic. So...please contribute your thoughts.&lt;/p&gt;
&lt;/div&gt;&lt;br /&gt;&lt;a href=http://www.toadworld.com/Blogs/tabid/67/EntryId/692/Write-Tiny-Little-Chunks-of-Code-or-Maybe-Not.aspx&gt;More ...&lt;/a&gt;&lt;div class="tags"&gt;Tags: plsql,oracle,package,anonymous block,procedure&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/692/Write-Tiny-Little-Chunks-of-Code-or-Maybe-Not.aspx#Comments</comments>
      <slash:comments>5</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/692/Write-Tiny-Little-Chunks-of-Code-or-Maybe-Not.aspx</guid>
      <pubDate>Fri, 27 May 2011 21:51:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=692</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/2/Default.aspx">oracle</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/164/Default.aspx">package</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/222/Default.aspx">anonymous block</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/223/Default.aspx">procedure</blog:tag>
    </item>
    <item>
      <title>REPLACE and CLOBs: Watch out for "_"!</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/678/REPLACE-and-CLOBs-Watch-out-for-_.aspx</link>
      <description>&lt;div&gt;
&lt;p&gt;The ecosystem of Oracle technology is vast, ever-changing and full of surprises. These surprises are sometimes referred to as "bugs", "undocumented features" and just plain "What? Are you &lt;em&gt;kidding &lt;/em&gt;me?"&lt;/p&gt;
&lt;p&gt;Michael Rosenblum of &lt;a target="_blank" href="http://dulcian.com/"&gt;Dulcian&lt;/a&gt;, and co-author of &lt;u&gt;&lt;a target="_blank" href="http://www.dummies.com/store/product/Oracle-PL-SQL-For-Dummies.productCd-0764599577.html"&gt;Oracle PL/SQL for Dummies&lt;/a&gt;&lt;/u&gt; (I know, I know, sounds a bit silly - but it is an excellent "intro" book for beginner PL/SQL developers), recently asked me about some strange behavior he'd found:&lt;/p&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;font color="#003366"&gt;One of my developers just noticed a strange behavior in all versions of Oracle 10g that we could test (10.2.0.3, 10.2.0.5). Here is the scenario:&lt;/font&gt;&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;font color="#003366"&gt;Use the REPLACE function with a CLOB variable&lt;/font&gt;&lt;/li&gt;
    &lt;li&gt;&lt;font color="#003366"&gt;Replace "T_" with "ZZ"; the variables contains a string "T(", as well as several occurrences of "T_".&lt;/font&gt;&lt;/li&gt;
    &lt;li&gt;&lt;font color="#003366"&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;In the result, Oracle replaces &lt;span&gt;both&lt;/span&gt; "T_" and "T(" with "ZZ"!&lt;/font&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;The underscore character is clearly being interpreted as a wild-card!&lt;/p&gt;
&lt;div&gt;
&lt;p&gt;This behavior does not occur with VARCHAR2 and it does not happen on Oracle Database 11g Release 2.&lt;/p&gt;
&lt;p&gt;Here's an example if you'd like to try this at home:&lt;/p&gt;
&lt;/div&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;DECLARE&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;   &lt;/span&gt;v_clob&lt;span&gt;   &lt;/span&gt;CLOB:='T_T(a number)';&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;BEGIN&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;   &lt;/span&gt;v_clob&lt;span&gt;   &lt;/span&gt;:=REPLACE(v_clob,'T_','ZZ');&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;span&gt;   &lt;/span&gt;&lt;em&gt;DBMS_OUTPUT.put_line&lt;/em&gt;(v_clob);&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;END;&lt;/font&gt;&lt;/div&gt;
&lt;/blockquote&gt;
&lt;p&gt;Result on 10g: "ZZZZa number)"&lt;/p&gt;
&lt;div&gt;Expected result (and result on 11g): "ZZT(a number)"&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;Michael wondered if he'd missed something in the documentation or if this was a bug...and a search in Metalink revealed the following:&lt;/p&gt;
&lt;/div&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;div&gt;Bug 4598943&lt;/div&gt;
&lt;div&gt;Database Version - 9.2.0.6&lt;/div&gt;
&lt;div&gt;Fixed in Product Version- 11.0.0.0.0&lt;/div&gt;
&lt;div&gt;Workaround: None&lt;/div&gt;
&lt;/blockquote&gt;
&lt;div&gt;So watch out for using REPLACE with clobs prior to 11g - you may not get the results you expect!&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;&lt;br /&gt;&lt;a href=http://www.toadworld.com/Blogs/tabid/67/EntryId/678/REPLACE-and-CLOBs-Watch-out-for-_.aspx&gt;More ...&lt;/a&gt;&lt;div class="tags"&gt;Tags: oracle,11g,10g,plsql,clob,replace&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/678/REPLACE-and-CLOBs-Watch-out-for-_.aspx#Comments</comments>
      <slash:comments>0</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/678/REPLACE-and-CLOBs-Watch-out-for-_.aspx</guid>
      <pubDate>Thu, 21 Apr 2011 15:21:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=678</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/2/Default.aspx">oracle</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/11/Default.aspx">11g</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/28/Default.aspx">10g</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/197/Default.aspx">clob</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/215/Default.aspx">replace</blog:tag>
    </item>
    <item>
      <title>QuickTips: Using FORALL with DML Statements</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/667/QuickTips-Using-FORALL-with-DML-Statements.aspx</link>
      <description>&lt;div&gt;
&lt;p&gt;This blog is the first in a series of "QuickTips" - a collection of advice and guidance on specific features of the Oracle PL/SQL language. The purpose of a QuickTip is &lt;em&gt;not&lt;/em&gt; to provide a comprehensive resource on the topic, such as full description of syntax, etc. Instead, I will point you to Oracle documentation for such things, and focus instead on some "added value" content.&lt;/p&gt;
&lt;p&gt;I will inaugurate the series with FORALL, undoubtedly one of the most important features of the PL/SQL.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;I assume that you are running an instance of Oracle Database 10 Release 2 or higher.&lt;/p&gt;
&lt;/div&gt;&lt;div class="tags"&gt;Tags: oracle,plsql,bulk collect,forall&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/667/QuickTips-Using-FORALL-with-DML-Statements.aspx#Comments</comments>
      <slash:comments>0</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/667/QuickTips-Using-FORALL-with-DML-Statements.aspx</guid>
      <pubDate>Wed, 23 Mar 2011 12:28:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=667</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/2/Default.aspx">oracle</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/54/Default.aspx">bulk collect</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/130/Default.aspx">forall</blog:tag>
    </item>
    <item>
      <title>Curious PL/SQL Code</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/662/Curious-PL-SQL-Code.aspx</link>
      <description>&lt;div&gt;I discovered something curious today. Check out the following block; it runs without any compilation or runtime error:&lt;/div&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;pre&gt;DECLARE&lt;br /&gt;   l_char   CHAR (1);&lt;br /&gt;&lt;br /&gt;   CURSOR x&lt;br /&gt;   IS&lt;br /&gt;      SELECT dummy INTO l_char FROM DUAL&lt;span&gt;;&lt;br /&gt;BEGIN&lt;br /&gt;&lt;/span&gt;   OPEN x&lt;span&gt;;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;   FETCH x INTO l_char&lt;span&gt;;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;   CLOSE x&lt;span&gt;;&lt;br /&gt;END;&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;div&gt;&lt;strong&gt; &lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;Can anyone see why I find it odd and curious? I have sent a note to the PL/SQL Product Manager asking what he thinks. What do &lt;em&gt;you&lt;/em&gt; think?&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Cheers, Steven&lt;/div&gt;&lt;br /&gt;&lt;a href=http://www.toadworld.com/Blogs/tabid/67/EntryId/662/Curious-PL-SQL-Code.aspx&gt;More ...&lt;/a&gt;&lt;div class="tags"&gt;Tags: plsql&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/662/Curious-PL-SQL-Code.aspx#Comments</comments>
      <slash:comments>4</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/662/Curious-PL-SQL-Code.aspx</guid>
      <pubDate>Tue, 15 Mar 2011 18:35:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=662</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
    </item>
    <item>
      <title>Take Care of Your Eyes!</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/655/Take-Care-of-Your-Eyes.aspx</link>
      <description>&lt;div&gt;
&lt;p&gt;About six years ago, I had Lasik surgery on my eyes. Wow, that was fantastic! I'd been wearing glasses since I was 8 years old. To able to walk outside in the rain and see clearly, to be able to see in the &lt;em&gt;shower &lt;/em&gt;- well, I was overjoyed with the results.&lt;/p&gt;
&lt;p&gt;Unfortunately, since then I have come to realize and accept that Lasik is not a panacea for all eye problems (not that I ever really thought that was true). In the past year or so, I have noticed my eyesight degrading a bit, and also that my eyes were getting really sore by the end of the day.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;Gee, big surprise, considering that I spent 6-8 hours a day in front of one screen or another (laptop, LCD monitor, etc.). Surprise or not, this is a serious problem, since I see no prospects of escaping from massive amounts of screen time for at least a couple of years.&lt;/p&gt;
&lt;p&gt;So what's a developer to do? Leaf through a Skymall magazine, of course!&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;On a recent flight, I noticed the following:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" width="245" height="222" src="/Portals/0/blogimages/Steven Feuerstein/SF-Blog-022211-1.png" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;
&lt;p&gt;They are described as follows:&lt;/p&gt;
&lt;p&gt;"These eyeglasses reduce eyestrain that results from viewing a computer screen for extended periods. The glasses combat the painful symptoms of Computer Vision Syndrome--at least 90% of the U.S. computer-using public is affected by the syndrome according to the National Institute of Occupational Safety and Health.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;"The yellow-tinted polycarbonate lenses' proprietary tinting blocks out 65% of blue light, a wavelength that reduces the sharpness of objects, leading to eye fatigue, tired or sore eyes, and the chance of headaches. The lenses protect against UV radiation up to 400nm, protecting eyes from harmful neon and halogen light sources. An inner anti-reflective coating on both the inner and outer side of the lens decreases the glare from overhead fluorescent lighting. Intended for use by those who wear contacts or do not require corrective lenses."&lt;/p&gt;
&lt;p&gt;I was skeptical, but my wife insisted I check them out. So I bought a pair and I must say that almost instantly I could tell the difference. They "warm up" the screen in a way that is hard to describe, but the bottom line is that my eyes do not have to strain to look at the screen and at the end of the day my eyes are not nearly so tired.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;I strongly encourage you to give them (or some other similar pair of glasses) a try. I don't intend to spend any more time in front of a computer screen unless I am wearing them.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;&lt;br /&gt;&lt;a href=http://www.toadworld.com/Blogs/tabid/67/EntryId/655/Take-Care-of-Your-Eyes.aspx&gt;More ...&lt;/a&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/655/Take-Care-of-Your-Eyes.aspx#Comments</comments>
      <slash:comments>2</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/655/Take-Care-of-Your-Eyes.aspx</guid>
      <pubDate>Wed, 23 Feb 2011 00:04:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=655</trackback:ping>
    </item>
    <item>
      <title>ORA-03113 and Getting CLOB Value from XMLTYPE</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/653/ORA-03113-and-Getting-CLOB-Value-from-XMLTYPE.aspx</link>
      <description>&lt;p&gt;The Quest Code Tester for Oracle development team is making more and more extensive use of the XMLTYPE datatype in the Oracle database. XML documents are a perfect fit for several requirements of Code Tester, in particular storing values for nested structures like collections of records, which in turn contain collections as fields.&lt;/p&gt;
&lt;div&gt;After adding an XMLTYPE column to our table, we then updated our table API packages to support retrieval of the XML document as a CLOB. You do this by invoking the GetClobVal method of the XMLTYPE object type.&lt;/div&gt;
&lt;p&gt;Here's an example of the way we did this:&lt;/p&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;DECLARE&lt;br /&gt;
   l_clob   CLOB;&lt;br /&gt;
BEGIN&lt;br /&gt;
   SELECT qu_attributes.dp_value.getclobval ()&lt;br /&gt;
     INTO l_clob&lt;br /&gt;
     FROM qu_attributes&lt;br /&gt;
    WHERE parent_guid = 'a' AND usage_type = 'a';&lt;br /&gt;
END; &lt;/font&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Sadly, when I run this block of code on 11.2 (and we've seen in on 10g as well), I get the following error:&lt;/p&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;pre&gt;ORA-03113: end-of-file on communication channel&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;That is one nasty error! And, as any of you who have encountered ORA-03113 must know, this error does not identify a problem in our code. It reflects a bug of some sort in Oracle's code.&lt;/p&gt;
&lt;p&gt;So the question that comes to mind immediately is: what's the workaround?&lt;/p&gt;
&lt;p&gt;It looks like the problem has to do with executing this method inside the query. I moved the call to the method into its own function:&lt;/p&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;CREATE OR REPLACE FUNCTION gcv (xmltype_in IN XMLTYPE)&lt;br /&gt;
   RETURN CLOB&lt;br /&gt;
IS&lt;br /&gt;
BEGIN&lt;br /&gt;
   RETURN xmltype_in.getclobval ();&lt;br /&gt;
END;&lt;br /&gt;
/&lt;/font&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;and then I called the function in my query:&lt;/p&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;DECLARE&lt;br /&gt;
   l_clob   CLOB;&lt;br /&gt;
BEGIN&lt;br /&gt;
   SELECT gcv (qu_attributes.dp_value)&lt;br /&gt;
     INTO l_clob&lt;br /&gt;
     FROM qu_attributes&lt;br /&gt;
    WHERE parent_guid = 'a' AND usage_type = 'a';&lt;br /&gt;
END;&lt;/font&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Then the ORA-03113 error disappeared. So that's the workaround, folks.&lt;/p&gt;
&lt;blockquote&gt;&lt;/blockquote&gt;
&lt;p&gt;If you get an ORA-03113 in a query that works with XMLType columns, check to see if GetClobVal is being called and if so, move it out to a separate function and call the function from within the query.&lt;br /&gt;
 &lt;/p&gt;&lt;br /&gt;&lt;a href=http://www.toadworld.com/Blogs/tabid/67/EntryId/653/ORA-03113-and-Getting-CLOB-Value-from-XMLTYPE.aspx&gt;More ...&lt;/a&gt;&lt;div class="tags"&gt;Tags: plsql,code tester,xml,clob,oracle,11g&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/10/Default.aspx&gt;Code Tester for Oracle&lt;/a&gt;&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/10/Default.aspx">Code Tester for Oracle</category>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/653/ORA-03113-and-Getting-CLOB-Value-from-XMLTYPE.aspx#Comments</comments>
      <slash:comments>3</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/653/ORA-03113-and-Getting-CLOB-Value-from-XMLTYPE.aspx</guid>
      <pubDate>Mon, 07 Feb 2011 17:28:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=653</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/1/Default.aspx">code tester</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/152/Default.aspx">xml</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/197/Default.aspx">clob</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/2/Default.aspx">oracle</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/11/Default.aspx">11g</blog:tag>
    </item>
    <item>
      <title>Code Metric Tools for PL/SQL?</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/640/Code-Metric-Tools-for-PL-SQL.aspx</link>
      <description>&lt;div&gt;I recently received this email:&lt;/div&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;div&gt;&lt;font color="#0000ff"&gt;Hi Steven,&lt;br /&gt;
&lt;br /&gt;
I am looking for tools to measure code quality and via which you can drill  down to the problem areas and for tools to refactor PL/SQL.&lt;br /&gt;
&lt;br /&gt;
Recently we insourced a team that is doing maintenance on an Oracle product. We are an Agile company and are now in the process of transforming the team to a Scrum team.&lt;br /&gt;
&lt;br /&gt;
The other teams develop Java desktop applications and have all the means to support Agile development. As a Scrum master of the insourced team I want to stimulate the team to explore ways to improve PL/SQL code quality, small steps at a time.  An important aspect of Scrum is continuous improvement. One of the bigger problems I see is code duplication.&lt;br /&gt;
&lt;br /&gt;
The Java teams have tooling to collect code metrics and there is a company goal that all code must have at least 4 out of 5 "stars". In conjunction with refactoring tools it helps to maintain the desired code quality level.&lt;br /&gt;
&lt;br /&gt;
I hope there are similar tools for PL/SQL.&lt;/font&gt;&lt;/div&gt;
&lt;/blockquote&gt;
&lt;div&gt;
&lt;p&gt;And my response:&lt;/p&gt;
&lt;p&gt;There are some similar tools, but generally the Java market is ahead of the PL/SQL market with tools like this. Here's a quick overview of what is available for PL/SQL development teams:&lt;/p&gt;
&lt;/div&gt;
&lt;ol&gt;
    &lt;li&gt;CodeXpert of &lt;a href="http://www.quest.com/toad-for-oracle/"&gt;Toad&lt;/a&gt; and &lt;a href="http://www.quest.com/sql-navigator/"&gt;SQL Navigator&lt;/a&gt; (Professional Editions): CodeXpert is a feature of Quest's popular IDEs that performs static code analysis (that is, the analysis does not require a connection to the Oracle database). Here are some examples of reports from CodeXpert:&lt;br /&gt;
     &lt;br /&gt;
    &lt;img alt="" width="628" height="251" src="/Portals/0/blogimages/Steven Feuerstein/SF-Blog-011111-1.png" /&gt; &lt;br /&gt;
    &lt;img alt="" src="/Portals/0/blogimages/Steven Feuerstein/SF-Blog-011111-2.png" /&gt;&lt;br /&gt;
     &lt;br /&gt;
    CodeXpert even includes standard industry analysis, such as the Halstead Volume computation:&lt;br /&gt;
     &lt;br /&gt;
    &lt;img alt="" src="/Portals/0/blogimages/Steven Feuerstein/SF-Blog-011111-3.png" /&gt;&lt;br /&gt;
     &lt;/li&gt;
    &lt;li&gt;ClearSQL: another third party tool that provides feedback on the quality of your code, quite similar to CodeXpert. Described as follows on their website [&lt;a href="http://www.conquestsoftwaresolutions.com/page/clearsql_at_a_glance"&gt;http://www.conquestsoftwaresolutions.com/page/clearsql_at_a_glance&lt;/a&gt;]: "ClearSQL is a code review and quality control tool for Oracle PL/SQL. With ClearSQL's code review feature you get recommendations for better coding style and check for error-prone places in your project."&lt;br /&gt;
     &lt;/li&gt;
    &lt;li&gt;&lt;a target="_blank" href="http://www.quest.com/code-tester-for-oracle/"&gt;Quest Code Tester for Oracle&lt;/a&gt; offers the only code coverage analysis in the PL/SQL market that includes an overall percentage of lines of code executed (SQL Developer does offer some code coverage reporting but not as strong as Code Tester). All such analysis and reporting is based on the built-in DBMS_PROFILER package. The profile data is a bit messy, making very accurate analyses a significant challenge, but we do the best we can. Here is a sample report:&lt;br /&gt;
     &lt;br /&gt;
    &lt;img alt="" src="/Portals/0/blogimages/Steven Feuerstein/SF-Blog-011111-4.png" /&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
&lt;p&gt;As for refactoring, Toad offers built-in refactoring tools, which are covered in this &lt;a href="http://www.toadworld.com/BLOGS/tabid/67/EntryId/346/Automatic-refactoring-in-PL-SQL-tools-Part-3.aspx"&gt;blog post&lt;/a&gt;. This screen shot gives you an idea of what is possible from the Editor; I especially like the Extract Procedure option.&lt;br /&gt;
 &lt;br /&gt;
&lt;img alt="" src="/Portals/0/blogimages/Steven Feuerstein/SF-Blog-011111-5.png" /&gt;&lt;/p&gt;
&lt;p&gt;Do any of my readers know of other code analysis tools that might be helpful? Please add your comments!&lt;/p&gt;
&lt;/div&gt;&lt;br /&gt;&lt;a href=http://www.toadworld.com/Blogs/tabid/67/EntryId/640/Code-Metric-Tools-for-PL-SQL.aspx&gt;More ...&lt;/a&gt;&lt;div class="tags"&gt;Tags: plsql,toad for oracle,sql navigator,code tester,refactoring,code xpert&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/1/Default.aspx&gt;Toad for Oracle&lt;/a&gt;&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/10/Default.aspx&gt;Code Tester for Oracle&lt;/a&gt;&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/13/Default.aspx&gt;SQL Navigator&lt;/a&gt;&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/1/Default.aspx">Toad for Oracle</category>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/10/Default.aspx">Code Tester for Oracle</category>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/13/Default.aspx">SQL Navigator</category>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/640/Code-Metric-Tools-for-PL-SQL.aspx#Comments</comments>
      <slash:comments>1</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/640/Code-Metric-Tools-for-PL-SQL.aspx</guid>
      <pubDate>Tue, 11 Jan 2011 16:28:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=640</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/10/Default.aspx">toad for oracle</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/127/Default.aspx">sql navigator</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/1/Default.aspx">code tester</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/79/Default.aspx">refactoring</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/76/Default.aspx">code xpert</blog:tag>
    </item>
    <item>
      <title>Incrementing Sequence Values</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/619/Incrementing-Sequence-Values.aspx</link>
      <description>&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style="line-height: 115%; font-family: 'Calibri','sans-serif'; font-size: 11pt; mso-fareast-font-family: Calibri; mso-fareast-language: EN-US; mso-ansi-language: EN-US; mso-bidi-language: AR-SA; mso-fareast-theme-font: minor-latin; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi"&gt;I love to hear from PL/SQL developers, and I love to help them out, but sometimes I am just too busy to respond quickly or in time. But sometimes, best of all, a developer asks me for help, and then solves his or her problem without my help.&lt;/span&gt; &lt;br /&gt;
 &lt;/p&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;That happened last week, and the result is a utility that I thought I would share with you. I received this email from Bryan Nyman (bnyman1@yahoo.com):&lt;/div&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;div&gt;" apologize if this is an easy tip, but was wondering if there's a bulk way to increase a sequence without EXECUTE IMMEDIATE 'alter sequence {sequence_name} begin with ... ' ?&lt;br /&gt;
 &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;"I'm copying data from one table (for test data) and altering a couple of  columns (namely ID_KEY and changing period value).  I am doing 1.3M rows in 25K increments using BULK COLLECT, a quick for i in FIRST..LAST to reset sequence ids using from DUAL (x25,000), then a FORALL...INSERT VALUES {row}. Suggestions ?  Is there a DBMS_SEQ package or anything that can take a sequence name and a numeric value ?" &lt;/div&gt;
&lt;/blockquote&gt;
&lt;p&gt;I gave the email a quick glance, but did not respond; I didn't have a quick and easy answer. &lt;font face="Wingdings"&gt;J&lt;br /&gt;
 &lt;/font&gt;&lt;/p&gt;
&lt;div style="margin: 0in 0in 10pt"&gt;Which worked out just fine, because a couple of days later, I received this follow-up from Bryan:&lt;br /&gt;
 &lt;/div&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;div&gt;"I sent you an email yesterday asking if you knew of any built-in DBMS packages that have this process. A friend at work directed me to the ALTER SEQUENCE INCREMENT property.  My company is running 11g, so it appears compilation issues aren't a concern (not sure if this would work in 10g or less).&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;
&lt;p&gt;"In my example I was BULK loading 1.3M rows 25k at a time to a COLLECTION and modifying the sequence (as well as another column) using a for i in FIRST..LAST loop. Using this procedure, I was able to reduce the number of FROM DUAL calls from 1.3M to 52.  I monitored the execution times and the entire original process ran in 640 seconds and the new ran in 492 for a 23% improvement."&lt;br /&gt;
 &lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;p dir="ltr"&gt; Wow! That's quite an improvement, so I thought I would share with you the utility Bryan put together; I look forward to your comments.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;CREATE OR REPLACE PROCEDURE prc_sequence_increment (&lt;br /&gt;
   p_in_seq_nm      IN     VARCHAR2&lt;br /&gt;
 , p_in_increment   IN     NUMBER&lt;br /&gt;
 , p_out_start         OUT NUMBER&lt;br /&gt;
 , p_out_end           OUT NUMBER)&lt;br /&gt;
AS&lt;br /&gt;
   v_nbr1      PLS_INTEGER := 0;&lt;br /&gt;
   v_nbr2      PLS_INTEGER := 0;&lt;br /&gt;
   v_cmd       VARCHAR2 (32767);&lt;br /&gt;
   v_hold_id   PLS_INTEGER := 0;&lt;br /&gt;
BEGIN&lt;br /&gt;
   EXECUTE IMMEDIATE   'alter sequence '&lt;br /&gt;
                    || p_in_seq_nm&lt;br /&gt;
                    || ' increment by '&lt;br /&gt;
                    || p_in_increment;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;   EXECUTE IMMEDIATE 'select ' || p_in_seq_nm || '.nextval from dual '&lt;br /&gt;
      INTO v_hold_id;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;   p_out_end := v_hold_id;&lt;br /&gt;
   p_out_start := p_out_end - p_in_increment + 1;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;   EXECUTE IMMEDIATE 'alter sequence ' || p_in_seq_nm || ' increment by 1 ';&lt;br /&gt;
END;&lt;br /&gt;
/&lt;/font&gt;&lt;/p&gt;&lt;br /&gt;&lt;a href=http://www.toadworld.com/Blogs/tabid/67/EntryId/619/Incrementing-Sequence-Values.aspx&gt;More ...&lt;/a&gt;&lt;div class="tags"&gt;Tags: plsql&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/619/Incrementing-Sequence-Values.aspx#Comments</comments>
      <slash:comments>4</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/619/Incrementing-Sequence-Values.aspx</guid>
      <pubDate>Mon, 08 Nov 2010 21:44:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=619</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
    </item>
    <item>
      <title>Help Me Avoid the Weekends!</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/613/Help-Me-Avoid-the-Weekends.aspx</link>
      <description>&lt;p&gt;I received this request from Jayme last week:&lt;/p&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;p&gt;"Hello Steven. In Transact-SQL I was able to have a block of code say if today was a  Monday give me Friday's date, else give me yesterday.  I have no idea how to do this in PL/SQL and you said if you spend more than 30 minutes on a problem to get a second set of eyes to look at it...will you be my second set of eyes?"&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We needed logic similar to this for the PL/SQL Challenge (you don't play the daily quiz on the weekend).&lt;/p&gt;
&lt;p&gt;So I generalized that function and sent it off to Jayme. I thought I would share it on this blog as well.&lt;/p&gt;
&lt;p&gt;I am quite certain there is a smarter way to get the job done. Please feel free to post your own implementation to share with others!&lt;/p&gt;
&lt;p&gt;Steven&lt;/p&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;pre&gt;&lt;br /&gt;CREATE OR REPLACE FUNCTION proximate_weekday (&lt;br /&gt;   date_in        IN DATE&lt;br /&gt; , direction_in   IN signtype DEFAULT 1)&lt;br /&gt;   RETURN DATE&lt;br /&gt;IS&lt;br /&gt;   c_before_weekend   CONSTANT VARCHAR2 (3) := 'FRI';&lt;br /&gt;   c_weekend_one      CONSTANT VARCHAR2 (3) := 'SAT';&lt;br /&gt;   c_weekend_two      CONSTANT VARCHAR2 (3) := 'SUN';&lt;br /&gt;   c_after_weekend    CONSTANT VARCHAR2 (3) := 'MON';&lt;br /&gt;   c_day_abbrev       CONSTANT VARCHAR2 (3)&lt;br /&gt;      := TO_CHAR (date_in, 'DY', 'NLS_DATE_LANGUAGE = AMERICAN') ;&lt;br /&gt;   l_return                    DATE;&lt;br /&gt;BEGIN&lt;br /&gt;   CASE&lt;br /&gt;      WHEN    c_day_abbrev IN ('TUE', 'WED', 'THU')&lt;br /&gt;           OR (c_day_abbrev = c_after_weekend AND direction_in = 1)&lt;br /&gt;           OR (c_day_abbrev = c_before_weekend AND direction_in = -1)&lt;br /&gt;      THEN&lt;br /&gt;         l_return := date_in + direction_in;&lt;br /&gt;      WHEN (c_day_abbrev = c_before_weekend AND direction_in = 1)&lt;br /&gt;           OR (c_day_abbrev = c_after_weekend AND direction_in = -1)&lt;br /&gt;      THEN&lt;br /&gt;         l_return := date_in + (direction_in * 3);&lt;br /&gt;      WHEN (c_day_abbrev = c_weekend_one AND direction_in = 1)&lt;br /&gt;           OR (c_day_abbrev = c_weekend_two AND direction_in = -1)&lt;br /&gt;      THEN&lt;br /&gt;         l_return := date_in + (direction_in * 2);&lt;br /&gt;      WHEN (c_day_abbrev = c_weekend_two AND direction_in = 1)&lt;br /&gt;           OR (c_day_abbrev = c_weekend_one AND direction_in = -1)&lt;br /&gt;      THEN&lt;br /&gt;         l_return := date_in + (direction_in * 1);&lt;br /&gt;   END CASE;&lt;/pre&gt;
&lt;pre&gt;   RETURN l_return;&lt;br /&gt;END proximate_weekday;&lt;br /&gt;/&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here's a test script to verify the behavior of the function:&lt;/p&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;pre&gt;&lt;strong&gt;&lt;strong&gt;&lt;strong&gt;&lt;p&gt;DECLARE&lt;br /&gt;   /* Start with a Monday */&lt;br /&gt;   l_date   DATE := DATE '2010-11-01';&lt;/p&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;p&gt;   PROCEDURE show_dates_around (date_in IN DATE)&lt;br /&gt;   IS&lt;br /&gt;   BEGIN&lt;br /&gt;      DBMS_OUTPUT.put_line ('Day is ' || TO_CHAR (date_in, 'Day'));&lt;br /&gt;      DBMS_OUTPUT.&lt;br /&gt;       put_line (&lt;br /&gt;         'One day before is '&lt;br /&gt;         || TO_CHAR (proximate_weekday (date_in, -1), 'Day'));&lt;br /&gt;      DBMS_OUTPUT.&lt;br /&gt;       put_line (&lt;br /&gt;         'One day after is ' || TO_CHAR (proximate_weekday (date_in, 1), 'Day'));&lt;br /&gt;   END;&lt;br /&gt;BEGIN&lt;br /&gt;   FOR indx IN 1 .. 7&lt;br /&gt;   LOOP&lt;br /&gt;      show_dates_around (l_date + indx - 1);&lt;br /&gt;   END LOOP;&lt;br /&gt;END;&lt;br /&gt;/&lt;/p&gt;&lt;/strong&gt;&lt;/pre&gt;
&lt;/blockquote&gt;&lt;br /&gt;&lt;a href=http://www.toadworld.com/Blogs/tabid/67/EntryId/613/Help-Me-Avoid-the-Weekends.aspx&gt;More ...&lt;/a&gt;&lt;div class="tags"&gt;Tags: plsql&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/613/Help-Me-Avoid-the-Weekends.aspx#Comments</comments>
      <slash:comments>8</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/613/Help-Me-Avoid-the-Weekends.aspx</guid>
      <pubDate>Mon, 01 Nov 2010 15:35:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=613</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
    </item>
    <item>
      <title>If a Tree Falls in a Forest...</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/610/If-a-Tree-Falls-in-a-Forest.aspx</link>
      <description>&lt;div&gt;I have written a &lt;em&gt;lot&lt;/em&gt; of PL/SQL code over the years, and I've collected the programs and scripts I reference in my training materials in the &lt;a href="http://www.toadworld.comhttp://www.toadworld.com/Portals/0/stevenf/demo.zip"&gt;demo.zip file&lt;/a&gt;, which you can download from &lt;a href="http://www.toadworld.com/LinkClick.aspx?link=153&amp;tabid=67"&gt;PL/SQL Obsession&lt;/a&gt;.&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;Sometimes when I present one of the packages I have written, I joke that:&lt;/p&gt;
&lt;p&gt;"I had fun writing this package, but I wonder if anyone will ever use it. And you must be familiar with that 'Zen of Programming' riddle: If you write a program and no one ever uses it, did you really write it?"&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;A good example of this would be the syscache package, found in the syscache.pkg file. It uses DBMS_PIPE as a proof of concept for sharing PGA-based information among multiple sessions. It is oh-so cool, but the chance of it being used is almost vanishingly small.&lt;/p&gt;
&lt;p&gt;And so I am always very pleased, indeed, when a developer informs me that she or he is using some of my code. Such a momentous event occurred last week:&lt;/p&gt;
&lt;/div&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;div&gt;
&lt;p&gt;&lt;font color="#333399"&gt;From: Pepijn Slappendel &lt;br /&gt;
Subject: Using the general parse package &lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font color="#333399"&gt;Hello Steven,&lt;/font&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;&lt;font color="#333399"&gt;Recently I have created a PL/SQL utility which can be used to Query data from Palo-cubes. Palo is an open-source cube-based BI Solution. The utility uses your generic parse package, which makes things very easy! We have now published the utility to the Palo-community on sourceforge.net, including the parse package. The files are stored at the following url: &lt;/font&gt;&lt;a href="http://palo.svn.sourceforge.net/viewvc/palo/contrib/scamander/"&gt;&lt;font color="#333399"&gt;http://palo.svn.sourceforge.net/viewvc/palo/contrib/scamander/&lt;/font&gt;&lt;/a&gt;&lt;font color="#333399"&gt; &lt;/font&gt;&lt;/div&gt;
&lt;p&gt;&lt;font color="#333399"&gt;Met vriendelijke groet,&lt;br /&gt;
Pepijn Slappendel&lt;/font&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For any of you wondering how to get your hands on this parse package, it may be found in the parse.pkg file in &lt;u&gt;&lt;a href="http://www.toadworld.comhttp://www.toadworld.com/Portals/0/stevenf/demo.zip"&gt;demo.zip&lt;/a&gt;&lt;/u&gt;.&lt;/p&gt;
&lt;div&gt;
&lt;p&gt;Thanks for informing me, Pepijn! I hope that lots of developers benefit from your contribution to the PL/SQL open source community.&lt;/p&gt;
&lt;p&gt;And if anyone reading this post has a similar story to tell, please &lt;u&gt;&lt;a href="http://www.toadworld.commailto:steven.feuerstein@quest.com"&gt;get in touch&lt;/a&gt;&lt;/u&gt;.&lt;/p&gt;
&lt;/div&gt;&lt;br /&gt;&lt;a href=http://www.toadworld.com/Blogs/tabid/67/EntryId/610/If-a-Tree-Falls-in-a-Forest.aspx&gt;More ...&lt;/a&gt;&lt;div class="tags"&gt;Tags: plsql,oracle&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/610/If-a-Tree-Falls-in-a-Forest.aspx#Comments</comments>
      <slash:comments>0</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/610/If-a-Tree-Falls-in-a-Forest.aspx</guid>
      <pubDate>Mon, 18 Oct 2010 14:38:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=610</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/2/Default.aspx">oracle</blog:tag>
    </item>
    <item>
      <title>"Insufficient Privileges" and DBMS_ERRLOG </title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/609/-Insufficient-Privileges-and-DBMS_ERRLOG.aspx</link>
      <description>&lt;p&gt;&lt;span style="line-height: 115%; font-family: "Calibri","sans-serif"; font-size: 11pt; mso-fareast-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-font-family: 'Times New Roman'; mso-bidi-theme-font: minor-bidi; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;One of the most persistent problems I hear about from PL/SQL developers is that of receiving an "insufficient privileges" error when trying to execute a SQL statement in a stored program unit. I received an email last week with another variation of this problem, this time involving DBMS_ERRLOG.&lt;/span&gt;&lt;/p&gt;&lt;div class="tags"&gt;Tags: oracle,plsql&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/609/-Insufficient-Privileges-and-DBMS_ERRLOG.aspx#Comments</comments>
      <slash:comments>0</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/609/-Insufficient-Privileges-and-DBMS_ERRLOG.aspx</guid>
      <pubDate>Mon, 11 Oct 2010 14:02:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=609</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/2/Default.aspx">oracle</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
    </item>
    <item>
      <title>Helping the CBO "cost out" SQL with PL/SQL functions</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/605/Helping-the-CBO-cost-out-SQL-with-PL-SQL-functions.aspx</link>
      <description>&lt;p&gt;Steven addresses a question from a user on how to set up a magic kingdom package using a magic_values table.&lt;/p&gt;&lt;div class="tags"&gt;Tags: plsql&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/605/Helping-the-CBO-cost-out-SQL-with-PL-SQL-functions.aspx#Comments</comments>
      <slash:comments>1</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/605/Helping-the-CBO-cost-out-SQL-with-PL-SQL-functions.aspx</guid>
      <pubDate>Thu, 30 Sep 2010 19:52:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=605</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
    </item>
    <item>
      <title>Using Conditional Compilation to Enforce Coding Guidelines</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/599/Using-Conditional-Compilation-to-Enforce-Coding-Guidelines.aspx</link>
      <description>&lt;p&gt;Conditional compilation is a feature of PL/SQL introduced in Oracle Database 10g that allows you to specify "meta" commands in PL/SQL that tell the compiler to include/exclude certain lines of code for compilation - and even raise a compilation error.&lt;/p&gt;&lt;div class="tags"&gt;Tags: plsql,oracle&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/599/Using-Conditional-Compilation-to-Enforce-Coding-Guidelines.aspx#Comments</comments>
      <slash:comments>0</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/599/Using-Conditional-Compilation-to-Enforce-Coding-Guidelines.aspx</guid>
      <pubDate>Wed, 15 Sep 2010 19:37:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=599</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/2/Default.aspx">oracle</blog:tag>
    </item>
    <item>
      <title>Should you use an associative array or a nested table?</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/584/Should-you-use-an-associative-array-or-a-nested-table.aspx</link>
      <description>&lt;div&gt;I recently received this question from Syed:&lt;/div&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;div&gt;"How does Oracle store the data for associative arrays and nested tables internally? Which type of collection is better for processing a huge volume of data without putting back into the database?"&lt;/div&gt;
&lt;/blockquote&gt;
&lt;div&gt;First, regarding the question of "internal" storage: I have no idea how Oracle manages these structures. I expect that the PL/SQL development team uses some kind of linked list implementation. I also suppose that I could ask Bryn Llewellyn (the PL/SQL Product Manager) about this, but I am certain his answers will be:&lt;/div&gt;
&lt;ol&gt;
    &lt;li&gt;Why should you care?&lt;/li&gt;
    &lt;li&gt;We don't give out information like this.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;And I agree with him: why should we care? We just need to know that we can use the data structures with confidence (no or minimal bugs, good performance). Why get caught up with "internal" details that can change from version to version anyway?&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Now, on to the question of which is better.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;If my memory serves me, back in the early days of the introduction of nested tables and varrays (Oracle8), the performance and memory management of associative arrays (the "original" collection type, introduced in Oracle7) was better than that for nested tables.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;These days (Oracle10g Release 2 and higher), I believe that you will see comparable levels of performance and memory usage, regardless of the type of collection you use.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;I don't have lots of time to build scripts that exercise lots of test cases, but I did put together a script to compare the amount of memory and time required to load over 1.2M rows into both an associative array and nested table.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;The code is shown below, and relies on several packages you will find in my &lt;a href="http://www.toadworld.comhttp://www.toadworld.com/Portals/0/stevenf/demo.zip"&gt;demo.zip&lt;/a&gt; file. The results of one row is as follows:&lt;/div&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;pre&gt;SQL&gt; @c:\work\demo-seminar\aa_vs_nt&lt;br /&gt;Connected.&lt;br /&gt;Associative memory&lt;br /&gt;1225043&lt;br /&gt;- Elapsed CPU : 3.02 seconds.&lt;br /&gt;Change in UGA memory: 65512 (Current = 373096)&lt;br /&gt;Change in PGA memory: 485490688 (Current = 486150372)&lt;br /&gt; &lt;br /&gt;PL/SQL procedure successfully completed.&lt;br /&gt; &lt;br /&gt;Connected.&lt;br /&gt;Nested table&lt;br /&gt;1225043&lt;br /&gt;- Elapsed CPU : 2.82 seconds.&lt;br /&gt;Change in UGA memory: 65512 (Current = 373096)&lt;br /&gt;Change in PGA memory: 485490688 (Current = 486150372)&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;div&gt;The bottom line? You will not see any discernable difference between the two.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;So when you are trying to decide which of the collection types you should use, base the decision on functionality, not performance.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;With associative arrays, you get:&lt;/div&gt;
&lt;ul&gt;
    &lt;li&gt;Ability to index by strings&lt;/li&gt;
    &lt;li&gt;Use of negative index values and a larger range of index values than with a nested table&lt;/li&gt;
    &lt;li&gt;Sparse collections (nested tables can be sparse, but they are more naturally used with densely-filled lists of information).&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;With nested tables, you get:&lt;/div&gt;
&lt;ul&gt;
    &lt;li&gt;Use of MULTISET operators to perform set-level operations, just like in SQL&lt;/li&gt;
    &lt;li&gt;Ability to query from nested tables using the TABLE operator&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;p&gt; &lt;hr /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;font size="3"&gt;The script (in &lt;a href="http://www.toadworld.comhttp://www.toadworld.com/Portals/0/stevenf/demo.zip"&gt;demo.zip&lt;/a&gt; - aa_vs_nt.sql)&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;pre&gt;connecthr/hr&lt;br /&gt; &lt;br /&gt;setserveroutputon&lt;br /&gt; &lt;br /&gt;DECLARE&lt;br /&gt;   TYPEemployees_aatISTABLEOFemployees%ROWTYPE&lt;br /&gt;                            INDEXBYPLS_INTEGER;&lt;br /&gt; &lt;br /&gt;   l_aat   employees_aat;&lt;br /&gt; &lt;br /&gt;   TYPEemployees_ntISTABLEOFemployees%ROWTYPE;&lt;br /&gt; &lt;br /&gt;   l_nt    employees_nt;&lt;br /&gt; &lt;br /&gt;   PROCEDUREstart_test(tVARCHAR2)&lt;br /&gt;   IS&lt;br /&gt;   BEGIN&lt;br /&gt;      DBMS_OUTPUT.put_line(t);&lt;br /&gt;      DBMS_SESSION.free_unused_user_memory;&lt;br /&gt;      plsql_memory.start_analysis;&lt;br /&gt;      sf_timer.start_timer;&lt;br /&gt;   END;&lt;br /&gt;BEGIN&lt;br /&gt;   start_test('Associative memory');&lt;br /&gt; &lt;br /&gt;   SELECTe1.*&lt;br /&gt;     BULKCOLLECTINTOl_aat&lt;br /&gt;     FROMemployees,employees,employeese1;&lt;br /&gt; &lt;br /&gt;   DBMS_OUTPUT.put_line(l_aat.COUNT);&lt;br /&gt;   sf_timer.show_elapsed_time;&lt;br /&gt;   plsql_memory.show_memory_usage;&lt;br /&gt;   l_aat.delete;&lt;br /&gt;END;&lt;br /&gt;/&lt;br /&gt; &lt;br /&gt;connecthr/hr&lt;br /&gt; &lt;br /&gt;setserveroutputon&lt;br /&gt; &lt;br /&gt;DECLARE&lt;br /&gt;   TYPEemployees_aatISTABLEOFemployees%ROWTYPE&lt;br /&gt;                            INDEXBYPLS_INTEGER;&lt;br /&gt; &lt;br /&gt;   l_aat   employees_aat;&lt;br /&gt; &lt;br /&gt;   TYPEemployees_ntISTABLEOFemployees%ROWTYPE;&lt;br /&gt; &lt;br /&gt;   l_nt    employees_nt;&lt;br /&gt; &lt;br /&gt;   PROCEDUREstart_test(tVARCHAR2)&lt;br /&gt;   IS&lt;br /&gt;   BEGIN&lt;br /&gt;      DBMS_OUTPUT.put_line(t);&lt;br /&gt;      DBMS_SESSION.free_unused_user_memory;&lt;br /&gt;      plsql_memory.start_analysis;&lt;br /&gt;      sf_timer.start_timer;&lt;br /&gt;   END;&lt;br /&gt;BEGIN&lt;br /&gt;   start_test('Nested table');&lt;br /&gt; &lt;br /&gt;   SELECTe1.*&lt;br /&gt;     BULKCOLLECTINTOl_nt&lt;br /&gt;     FROMemployees,employees,employeese1;&lt;br /&gt; &lt;br /&gt;   DBMS_OUTPUT.put_line(l_nt.COUNT);&lt;br /&gt;   sf_timer.show_elapsed_time;&lt;br /&gt;   plsql_memory.show_memory_usage;&lt;br /&gt;END;&lt;br /&gt;/&lt;/pre&gt;&lt;br /&gt;&lt;a href=http://www.toadworld.com/Blogs/tabid/67/EntryId/584/Should-you-use-an-associative-array-or-a-nested-table.aspx&gt;More ...&lt;/a&gt;&lt;div class="tags"&gt;Tags: oracle,plsql,nested table&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/584/Should-you-use-an-associative-array-or-a-nested-table.aspx#Comments</comments>
      <slash:comments>0</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/584/Should-you-use-an-associative-array-or-a-nested-table.aspx</guid>
      <pubDate>Tue, 17 Aug 2010 14:33:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=584</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/2/Default.aspx">oracle</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/149/Default.aspx">nested table</blog:tag>
    </item>
    <item>
      <title>PL/SQL Developers win over US$2000 in prizes at PL/SQL Challenge playoff</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/572/PL-SQL-Developers-win-over-US-2000-in-prizes-at-PL-SQL-Challenge-playoff.aspx</link>
      <description>&lt;p&gt;On 15 July 2010, 32 developers participated in the first-ever PL/SQL Challenge championship playoff. This playoff (consisting of ten questions to be answered in 15 minutes) was the culmination of a three-month competition in which PL/SQL developers from around the world tested their knowledge of PL/SQL against one another through daily quizzes.&lt;/p&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/572/PL-SQL-Developers-win-over-US-2000-in-prizes-at-PL-SQL-Challenge-playoff.aspx#Comments</comments>
      <slash:comments>0</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/572/PL-SQL-Developers-win-over-US-2000-in-prizes-at-PL-SQL-Challenge-playoff.aspx</guid>
      <pubDate>Tue, 20 Jul 2010 13:51:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=572</trackback:ping>
    </item>
    <item>
      <title>RAISE vs RAISE_APPLICATION_ERROR?</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/568/RAISE-vs-RAISE_APPLICATION_ERROR.aspx</link>
      <description>&lt;p&gt;Steven explains the difference between RAISE_APPLICATION_ERROR and RAISE and why you would use one vs. the other.&lt;/p&gt;&lt;div class="tags"&gt;Tags: plsql,oracle&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/568/RAISE-vs-RAISE_APPLICATION_ERROR.aspx#Comments</comments>
      <slash:comments>5</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/568/RAISE-vs-RAISE_APPLICATION_ERROR.aspx</guid>
      <pubDate>Wed, 14 Jul 2010 20:02:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=568</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/2/Default.aspx">oracle</blog:tag>
    </item>
    <item>
      <title>New Utilities in demo.zip</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/556/New-Utilities-in-demo-zip.aspx</link>
      <description>&lt;div&gt;I recently needed to move the contents of clobs and collections to and from files, and also write simple reporting routines. So I ended up creating the following and uploading them to my &lt;u&gt;&lt;a href="http://www.toadworld.com/Portals/0/stevenf/demo.zip"&gt;demo.zip&lt;/a&gt;&lt;/u&gt; download:&lt;/div&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;strong&gt;export_clob.sql&lt;/strong&gt; - move the contents of a clob to the specified file or to system output, if no file is specified. &lt;br /&gt;
     &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;file_to_clob.sql&lt;/strong&gt; - load the contents of a file into a clob&lt;br /&gt;
     &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;collection_to_file.sql&lt;/strong&gt; - writes the contents of a collection declared on the DBMS_SQL.varchar2a type to the specified file.&lt;br /&gt;
     &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;display_clob_by_cr.sql&lt;/strong&gt; - writes the contents of a clob to system output, using a line feed (CHR(10)) as the delimiter. &lt;em&gt;[Note: original publication of blog entry said "carriage return"; I changed it to "line feed"]&lt;/em&gt;&lt;br /&gt;
     &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;display_header.sql&lt;/strong&gt; - displays the specified string as a "header", which means that it looks like this:&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;pre&gt;===========================================================&lt;br /&gt;Written by Steven Feuerstein&lt;br /&gt;===========================================================&lt;/pre&gt;
&lt;div&gt;You can specify the length of the header, the border character, and more.&lt;/div&gt;
&lt;/blockquote&gt;
&lt;div&gt;I hope you find these utilities useful. As always, it is your responsibility to ensure that these programs meet your requirements and have no bugs.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;If you &lt;em&gt;do&lt;/em&gt; find a bug or a way to improve any of these programs, please don't hesitate to let me know.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;&lt;br /&gt;&lt;a href=http://www.toadworld.com/Blogs/tabid/67/EntryId/556/New-Utilities-in-demo-zip.aspx&gt;More ...&lt;/a&gt;&lt;div class="tags"&gt;Tags: plsql,oracle&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/556/New-Utilities-in-demo-zip.aspx#Comments</comments>
      <slash:comments>2</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/556/New-Utilities-in-demo-zip.aspx</guid>
      <pubDate>Mon, 28 Jun 2010 13:18:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=556</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/2/Default.aspx">oracle</blog:tag>
    </item>
    <item>
      <title>Handy new warning in Oracle 11.2</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/550/Handy-new-warning-in-Oracle-11-2.aspx</link>
      <description>&lt;div style="margin: 2pt 0in 3pt"&gt;Way back when Oracle10g was released, Oracle added compile-time warnings to the PL/SQL compiler.&lt;/div&gt;
&lt;div style="margin: 2pt 0in 3pt"&gt;
&lt;p&gt;When you enabled warnings in your session (or for a specific program), then at the time of compilation, Oracle will check to see if it can identify ways in which you might be able to improve the quality or performance of your code.&lt;/p&gt;
&lt;p&gt;You can read more about the compile time warnings feature &lt;a href="http://download.oracle.com/docs/cd/E11882_01/appdev.112/e10472/errors.htm#LNPLS00711"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div style="margin: 2pt 0in 3pt"&gt;You can see a list of all compile time warnings available &lt;a href="http://download.oracle.com/docs/cd/E11882_01/server.112/e10880/plwus.htm#sthref18222"&gt;here&lt;/a&gt;.&lt;/div&gt;
&lt;div style="margin: 2pt 0in 3pt"&gt;
&lt;p&gt;When this feature was first made available, I was both excited and disappointed.&lt;/p&gt;
&lt;/div&gt;
&lt;div style="margin: 2pt 0in 3pt"&gt;Excited, because I could now easily determine if, for example, my program unit had any "dead code" - code that would never execute, no matter what (that's warning PLW-06002).&lt;/div&gt;
&lt;div style="margin: 2pt 0in 3pt"&gt;
&lt;p&gt;Disappointed, because Oracle did not implement warnings for some of the most common and irritating coding mistakes, such as:&lt;/p&gt;
&lt;/div&gt;
&lt;pre style="margin: 0in 0in 0pt"&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;SQL&gt; &lt;/span&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;CREATE &lt;/span&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;OR &lt;/span&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;REPLACE &lt;/span&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;PROCEDURE &lt;/span&gt;&lt;span style="background: white; color: black; font-size: 10pt"&gt;my_prod&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="margin: 0in 0in 0pt"&gt;&lt;span style="background: white; color: black"&gt;  &lt;/span&gt;&lt;span style="background: white; color: maroon; font-size: 10pt"&gt;2&lt;/span&gt;&lt;span style="background: white; color: black"&gt;        &lt;/span&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;AUTHID &lt;/span&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;CURRENT_USER&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="margin: 0in 0in 0pt"&gt;&lt;span style="background: white; color: black"&gt;  &lt;/span&gt;&lt;span style="background: white; color: maroon; font-size: 10pt"&gt;3&lt;/span&gt;&lt;span style="background: white; color: black"&gt;   &lt;/span&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;IS&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="margin: 0in 0in 0pt"&gt;&lt;span style="background: white; color: black"&gt;  &lt;/span&gt;&lt;span style="background: white; color: maroon; font-size: 10pt"&gt;4&lt;/span&gt;&lt;span style="background: white; color: black"&gt;        &lt;/span&gt;&lt;span style="background: white; color: black; font-size: 10pt"&gt;l_string &lt;/span&gt;&lt;span style="background: white; color: red; font-size: 10pt"&gt;VARCHAR2&lt;/span&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;(&lt;/span&gt;&lt;span style="background: white; color: maroon; font-size: 10pt"&gt;1&lt;/span&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;) &lt;/span&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;:= &lt;/span&gt;&lt;span style="background: white; color: red; font-size: 10pt"&gt;'abc'&lt;/span&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;;&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="margin: 0in 0in 0pt"&gt;&lt;span style="background: white; color: black"&gt;  &lt;/span&gt;&lt;span style="background: white; color: maroon; font-size: 10pt"&gt;5&lt;/span&gt;&lt;span style="background: white; color: black"&gt;   &lt;/span&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;BEGIN&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="margin: 0in 0in 0pt"&gt;&lt;span style="background: white; color: black"&gt;  &lt;/span&gt;&lt;span style="background: white; color: maroon; font-size: 10pt"&gt;6&lt;/span&gt;&lt;span style="background: white; color: black"&gt;     &lt;/span&gt;&lt;span style="background: white; color: black; font-size: 10pt"&gt;l_string &lt;/span&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;:= &lt;/span&gt;&lt;span style="background: white; color: red; font-size: 10pt"&gt;'abc'&lt;/span&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;;&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="margin: 0in 0in 0pt"&gt;&lt;span style="background: white; color: black"&gt;  &lt;/span&gt;&lt;span style="background: white; color: maroon; font-size: 10pt"&gt;7&lt;/span&gt;&lt;span style="background: white; color: black"&gt;   &lt;/span&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;END;&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="margin: 0in 0in 0pt"&gt;&lt;span style="background: white; color: black"&gt;  &lt;/span&gt;&lt;span style="background: white; color: maroon; font-size: 10pt"&gt;8  &lt;/span&gt;&lt;span style="background: white; color: black"&gt; &lt;/span&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;/&lt;/span&gt;&lt;/pre&gt;
&lt;div style="margin: 2pt 0in 3pt"&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style="background: white"&gt;In this program, I try to assign a value that is too big for the variable, which will cause Oracle to raise a runtime VALUE_ERROR exception. But I want to hear about this problem at compile-time, not run-time.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div style="margin: 2pt 0in 3pt"&gt;&lt;span style="background: white"&gt;Well, in 11.2, code like that found in lines 4 and 6 are now flagged as problematic, as you can see when I show the errors after I attempt to compile this procedure:&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin: 2pt 0in 3pt"&gt; &lt;/div&gt;
&lt;pre style="margin: 0in 0in 0pt"&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;SQL&gt; &lt;/span&gt;&lt;span style="background: white; color: black; font-size: 10pt"&gt;sho &lt;/span&gt;&lt;span style="background: white; color: black; font-size: 10pt"&gt;err&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="margin: 0in 0in 0pt"&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;Errors &lt;/span&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;for &lt;/span&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;PROCEDURE &lt;/span&gt;&lt;span style="background: white; color: black; font-size: 10pt"&gt;MY_PROC&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="margin: 0in 0in 0pt"&gt; &lt;/pre&gt;
&lt;pre style="margin: 0in 0in 0pt"&gt;&lt;span style="background: white; color: black; font-size: 10pt"&gt;LINE&lt;/span&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;/&lt;/span&gt;&lt;span style="background: white; color: black; font-size: 10pt"&gt;COL &lt;/span&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;ERROR&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="margin: 0in 0in 0pt"&gt;&lt;span style="background: white; color: green; font-size: 10pt"&gt;-------- -----------------------------------------------------------------&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="margin: 0in 0in 0pt"&gt;&lt;span style="background: white; color: maroon; font-size: 10pt"&gt;4&lt;/span&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;/&lt;/span&gt;&lt;span style="background: white; color: maroon; font-size: 10pt"&gt;4&lt;/span&gt;&lt;span style="background: white; color: black"&gt;      &lt;/span&gt;&lt;span style="background: white; color: black; font-size: 10pt"&gt;PLW&lt;/span&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;-&lt;/span&gt;&lt;span style="background: white; color: maroon; font-size: 10pt"&gt;06017&lt;/span&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;: &lt;/span&gt;&lt;span style="background: white; color: black; font-size: 10pt"&gt;an &lt;/span&gt;&lt;span style="background: white; color: black; font-size: 10pt"&gt;operation &lt;/span&gt;&lt;span style="background: white; color: black; font-size: 10pt"&gt;will &lt;/span&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;raise &lt;/span&gt;&lt;span style="background: white; color: black; font-size: 10pt"&gt;an &lt;/span&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;exception&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="margin: 0in 0in 0pt"&gt;&lt;span style="background: white; color: maroon; font-size: 10pt"&gt;6&lt;/span&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;/&lt;/span&gt;&lt;span style="background: white; color: maroon; font-size: 10pt"&gt;4&lt;/span&gt;&lt;span style="background: white; color: black"&gt;      &lt;/span&gt;&lt;span style="background: white; color: black; font-size: 10pt"&gt;PLW&lt;/span&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;-&lt;/span&gt;&lt;span style="background: white; color: maroon; font-size: 10pt"&gt;06017&lt;/span&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;: &lt;/span&gt;&lt;span style="background: white; color: black; font-size: 10pt"&gt;an &lt;/span&gt;&lt;span style="background: white; color: black; font-size: 10pt"&gt;operation &lt;/span&gt;&lt;span style="background: white; color: black; font-size: 10pt"&gt;will &lt;/span&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;raise &lt;/span&gt;&lt;span style="background: white; color: black; font-size: 10pt"&gt;an &lt;/span&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;exception&lt;/span&gt;&lt;/pre&gt;
&lt;div style="margin: 2pt 0in 3pt"&gt;
&lt;p&gt;So that is very, very nice….but it would have been so much nicer if the warning message could have been a bit more specific. Here's the explanation for this warning:&lt;/p&gt;
&lt;/div&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;div style="margin: 2pt 0in 3pt"&gt;&lt;span style="color: blue; font-size: 10pt"&gt;"&lt;/span&gt;The compiler has determined that some operation near this location is certain to raise an exception during execution. This may be a programming error; consider rewriting the code. If the intention is to raise an exception, use an explicit RAISE statement."&lt;/div&gt;
&lt;/blockquote&gt;
&lt;div style="margin: 2pt 0in 3pt"&gt;
&lt;p&gt;Well, that covers a lot of territory.&lt;/p&gt;
&lt;p&gt;Another problem with this warning is that it only works for VARCHAR2; you will not see this warning if you write a line of code like:&lt;/p&gt;
&lt;/div&gt;
&lt;pre style="margin: 2pt 0in 3pt"&gt;&lt;span style="background: white; color: black; font-size: 10pt"&gt;l_string &lt;/span&gt;&lt;span style="background: white; color: red; font-size: 10pt"&gt;CHAR&lt;/span&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;(&lt;/span&gt;&lt;span style="background: white; color: maroon; font-size: 10pt"&gt;1&lt;/span&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;) &lt;/span&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;:= &lt;/span&gt;&lt;span style="background: white; color: red; font-size: 10pt"&gt;'abc'&lt;/span&gt;&lt;span style="background: white; color: blue; font-size: 10pt"&gt;;&lt;/span&gt;&lt;/pre&gt;
&lt;div style="margin: 2pt 0in 3pt"&gt;
&lt;p&gt;Still, it is a nice enhancement and I am very glad that Oracle did this for us. Thanks, PL/SQL development team!&lt;/p&gt;
&lt;/div&gt;&lt;br /&gt;&lt;a href=http://www.toadworld.com/Blogs/tabid/67/EntryId/550/Handy-new-warning-in-Oracle-11-2.aspx&gt;More ...&lt;/a&gt;&lt;div class="tags"&gt;Tags: plsql,oracle,11g&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/550/Handy-new-warning-in-Oracle-11-2.aspx#Comments</comments>
      <slash:comments>0</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/550/Handy-new-warning-in-Oracle-11-2.aspx</guid>
      <pubDate>Fri, 11 Jun 2010 20:18:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=550</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/2/Default.aspx">oracle</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/11/Default.aspx">11g</blog:tag>
    </item>
    <item>
      <title>Why can't I execute DDL natively in PL/SQL</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/549/Why-cant-I-execute-DDL-natively-in-PL-SQL.aspx</link>
      <description>&lt;div&gt;I recently received an email from Syed asking this very question as follows:&lt;/div&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;div&gt;"Could you please let me know why DDL statements are not allowed [natively] in PLSQL? I read somewhere that the reason is that DDL statements will cause objects to be invalidated and then require recompilation. As all objects are already in a compiled [VALID] state, compiling again will be an overhead. But when we execute DDL statements [with EXECUTE IMMEDIATE] objects will still be invalidated and require additional recompilation - the same drawback. So why not allow it in as static SQL?"&lt;/div&gt;
&lt;/blockquote&gt;
&lt;div&gt;There are generally two classes of questions that I prefer to not answer:&lt;/div&gt;
&lt;ol&gt;
    &lt;li&gt;Why did Oracle do X that way?&lt;/li&gt;
    &lt;li&gt;Why doesn't Oracle let us do X?&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;I don't like speaking for Oracle, nor do I like speculating about why Oracle decides to do or not do something (or do it in a particular way).&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;So I suggested to Syed that he contact the Oracle PL/SQL Product Manager, Bryn Llewellyn. Hey, it's Bryn's job to represent Oracle to the PL/SQL developer community (among other responsibilities, though none more important. &lt;font face="Wingdings"&gt;&lt;img alt="" src="/Providers/HtmlEditorProviders/Fck/FCKeditor/editor/images/smiley/msn/regular_smile.gif" /&gt;&lt;/font&gt; ).&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Syed did just that, and Bryn gave me approval to publish his reply. Here it is:&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;strong&gt;From the Keyboard of Bryn Llewellyn:&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;The answer is obvious, and not what you think.&lt;br /&gt;
&lt;br /&gt;
First off, it helps to remember that at run time, all SQL issued by a PL/SQL program is "dynamic" in that the sense that the text of the SQL statement is handed over, at run time, from the PL/SQL subsystem to the SQL subsystem for execution and the SQL subsystem processes it in the same way. This is the case even for PL/SQL's embedded SQL (I don't like to call it "static" because of the point I just made). For embedded SQL, whatever parsing of the SQL statement that the PL/SQL subsystem did at PL/SQL compile time (in order to work out how to do the &lt;em&gt;binds&lt;/em&gt; and &lt;em&gt;defines&lt;/em&gt;, to establish dependencies, and so on -- see below) is re-done at run time.&lt;br /&gt;
&lt;br /&gt;
PL/SQL's embedded SQL has these big advantages:&lt;br /&gt;
&lt;br /&gt;
(1) The text is checked at compile time for correct syntax and (unhelpfully for invoker's rights programs) for correct semantics. Following on from this, dependencies are set up to the referenced objects (but for IR units they might not be helpful).&lt;br /&gt;
&lt;br /&gt;
(2) When the statement includes local PL/SQL variables (which &lt;em&gt;select, insert, update, delete,&lt;/em&gt; and &lt;em&gt;merge&lt;/em&gt; statements, a.k.a. DML statements, typically do), these are converted to placeholders in the SQL that will be used at run time and appropriate binding code is included in your executable PL/SQL program. Appropriate code is also generated to handle values returned by &lt;em&gt;select &lt;/em&gt;statements, and by change-statements that use &lt;em&gt;returning&lt;/em&gt;. Embedded SQL makes all this highly usable.&lt;br /&gt;
&lt;br /&gt;
(3) The statement execution code that's generated implements a special soft-parse avoidance scheme. You can think of the benefit as rather like that by setting &lt;em&gt;Session_Cached_Cursors&lt;/em&gt; to a non-zero value for an ordinary OCI program -- only quite a lot better.&lt;br /&gt;
&lt;br /&gt;
Non-DML statements cannot benefit from these advantages. Notice that ready-to-go statements that are not &lt;em&gt;select, insert, update, delete,&lt;/em&gt; or &lt;em&gt;merge &lt;/em&gt;are never cached in the shared pool. Further, especially because the names of the target objects are typically not known until run time, and because only DML statements allow binding, these non-DML statements are almost always composed programmatically -- ideally with the help of the &lt;em&gt;DBMS_Assert&lt;/em&gt; functions. In other words, you never see an &lt;em&gt;into&lt;/em&gt; or &lt;em&gt;using&lt;/em&gt; clause when execute immediate is used for anything except DML.&lt;br /&gt;
&lt;br /&gt;
This means that there would be no real benefit if a scheme were invented to allow non-DML statements to be written in PL/SQL using a new kind of embedded SQL.&lt;/div&gt;&lt;br /&gt;&lt;a href=http://www.toadworld.com/Blogs/tabid/67/EntryId/549/Why-cant-I-execute-DDL-natively-in-PL-SQL.aspx&gt;More ...&lt;/a&gt;&lt;div class="tags"&gt;Tags: plsql,oracle,ddl&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/549/Why-cant-I-execute-DDL-natively-in-PL-SQL.aspx#Comments</comments>
      <slash:comments>0</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/549/Why-cant-I-execute-DDL-natively-in-PL-SQL.aspx</guid>
      <pubDate>Tue, 01 Jun 2010 19:29:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=549</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/2/Default.aspx">oracle</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/173/Default.aspx">ddl</blog:tag>
    </item>
    <item>
      <title>How big can my program get?</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/537/How-big-can-my-program-get.aspx</link>
      <description>&lt;p&gt;I recently received this question from a PL/SQL developer:&lt;/p&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;p&gt;&lt;em&gt;"What is the maximum size of a PL/SQL procedure?"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div&gt;
&lt;p&gt;The answer is interesting: there is not a maximum size, per se. Instead, the limitation has to do with the maximum number of &lt;em&gt;DIANA nodes&lt;/em&gt; your program generates in the compilation process.&lt;/p&gt;
&lt;p&gt;DIANA is an intermediate language produced and used by the compiler. DIANA standards for “Descriptive Intermediate Attributed Notation for Ada" - and reminds us that PL/SQL is based on Ada, a programming language originally developed for the U.S. Department of Defense.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;DIANA code is in the form of a tree structure, and nodes in the tree correspond to &lt;em&gt;tokens&lt;/em&gt; in your programs, which include identifiers, keywords and operators.&lt;/p&gt;
&lt;p&gt;So here's the actual limitation regarding "size" (quoting now from the &lt;a href="http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28370/limits.htm"&gt;Oracle documentation&lt;/a&gt;): "a package spec, object type spec, standalone subprogram, or anonymous block is limited to 67108864 (2**26) DIANA nodes....[which] allows for ~6,000,000 lines of code."&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;In other words, you &lt;em&gt;really&lt;/em&gt; should not have to worry about "running out of space" when building your PL/SQL program units.&lt;/p&gt;
&lt;p&gt;You will run up against maintainability issues way before you run into PL/SQL limitations. If your program unit is getting big enough that you are even wondering if it is &lt;em&gt;too big&lt;/em&gt;, you should break it up into smaller units, with different names and distinct purposes.&lt;/p&gt;
&lt;/div&gt;&lt;br /&gt;&lt;a href=http://www.toadworld.com/Blogs/tabid/67/EntryId/537/How-big-can-my-program-get.aspx&gt;More ...&lt;/a&gt;&lt;div class="tags"&gt;Tags: plsql,oracle&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/537/How-big-can-my-program-get.aspx#Comments</comments>
      <slash:comments>1</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/537/How-big-can-my-program-get.aspx</guid>
      <pubDate>Mon, 10 May 2010 13:09:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=537</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/2/Default.aspx">oracle</blog:tag>
    </item>
    <item>
      <title>Little things can get you</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/536/Little-things-can-get-you.aspx</link>
      <description>&lt;div&gt;
&lt;p&gt;I received yesterday this email from a PL/SQL developer:&lt;/p&gt;
&lt;/div&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;p&gt;I am stumped. My PL/SQL code does not seem to be handling dates properly. Here is a block of code I extracted from my actual program to demonstrate the problem:&lt;/p&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;pre&gt;DECLARE&lt;br /&gt;   global_end_date   DATE := '04-May-2010';&lt;br /&gt;   global_beg_date   DATE := '01-May-2010';&lt;br /&gt;BEGIN&lt;br /&gt;   IF TRUNC (SYSDATE) &gt; TO_DATE (global_end_date, 'DD-MON-YYYY')&lt;br /&gt;   THEN&lt;br /&gt;      DBMS_OUTPUT.put_line (TRUNC (SYSDATE));&lt;br /&gt;      DBMS_OUTPUT.put_line (TO_DATE (global_end_date, 'DD-MON-YYYY'));&lt;br /&gt;      DBMS_OUTPUT.put_line ('&gt; global_end_date');&lt;br /&gt;   ELSIF TRUNC (SYSDATE) &lt; TO_DATE (global_beg_date, 'DD-MON-YYYY')&lt;br /&gt;   THEN&lt;br /&gt;      DBMS_OUTPUT.put_line ('sysdate &lt; beg_date');&lt;br /&gt;   ELSE&lt;br /&gt;      DBMS_OUTPUT.put_line ('Neither');&lt;br /&gt;   END IF;&lt;br /&gt;END;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;My problem is that when I run this code (on 4 May 2010), it shows me "&gt; global_end_date".&lt;/p&gt;
&lt;p&gt;How can that be, when it is "obvious" that:&lt;/p&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;pre&gt;TRUNC (SYSDATE) &gt; TO_DATE (global_end_date, 'DD-MON-YYYY')&lt;/pre&gt;
&lt;/blockquote&gt;&lt;/blockquote&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;
&lt;p&gt;Being the nice guy that I am, I grabbed the code from the email, pasted it into Toad and ran it myself. She was &lt;em&gt;right!&lt;/em&gt;  What the heck is going on here?&lt;/p&gt;
&lt;p&gt;Perhaps some of you have seen the issue already; it actually took me a few minutes of playing with the code.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;If you have not yet seen it, DO NOT READ ANY FURTHER IN THIS BLOG.&lt;/p&gt;
&lt;p&gt;Instead, take a few moments to carefully read the code and make sure that it makes sense to you.&lt;/p&gt;
&lt;/div&gt;
&lt;div align="center"&gt;&lt;img alt="" width="300" height="300" src="/Portals/0/blogimages/Steven Feuerstein/SF-Blog050510-1.gif" /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;Did you read the code? Do you now see the problem?&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;The developer is calling TO_DATE on a &lt;em&gt;date&lt;/em&gt;. So what is actually happening is that the date value in global_end_date is being converted implicitly to a string, and then converted explicitly back to a date with TO_DATE.&lt;/p&gt;
&lt;p&gt;In fact, there is no reason to call TO_DATE (or TO_CHAR). Just perform a direct comparison:&lt;/p&gt;
&lt;/div&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;pre&gt;TRUNC (SYSDATE) &gt; global_end_date&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;If you hadn't yet caught the problem, you are probably now slapping yourself on the forehead and exclaiming "Duh! How could I miss something so obvious?"&lt;/p&gt;
&lt;div&gt;
&lt;p&gt;How can we miss, over and over again, such obvious problems in our code?&lt;/p&gt;
&lt;p&gt;Human psychology, is the answer.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;There are, I believe, several factors that make it hard to see issues in our programs, including:&lt;/div&gt;
&lt;ul type="disc"&gt;
    &lt;li&gt;We are inclined to believe that what we have written is correct or likely to be correct. So when we look at our code, we are not critical enough of what we are seeing.&lt;/li&gt;
    &lt;li&gt;We think we &lt;em&gt;know&lt;/em&gt; what we are reading (after all, we wrote it), so we &lt;em&gt;skim&lt;/em&gt; rather than read closely. This is true not just for reading code, but reading text as well.&lt;/li&gt;
    &lt;li&gt;We are too far "inside" our programs and our bugs to take a clear, unbiased look at our code.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;How can we avoid overlooking problems in our code?&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Ask someone else to look at the code. And ask for help sooner rather than later. I know, I know, you &lt;em&gt;hate&lt;/em&gt; to ask for help. But it's OK to admit that you are having trouble; the person you ask for help will feel very good about being &lt;em&gt;able&lt;/em&gt; to help you. And they will have fresh eyes, making it easier to identify the source of a problem.&lt;/li&gt;
    &lt;li&gt;Develop a habit of reading, truly &lt;em&gt;reading&lt;/em&gt;, your code. All too often, we type a bunch of statements, get it to compile and then "try it." "Let's just see what happens," is a common programmer refrain. &lt;em&gt;Trying&lt;/em&gt; something is very different from either actually &lt;em&gt;testing it&lt;/em&gt; or using &lt;em&gt;symbolic logic&lt;/em&gt; to step through your code (with your eyes, not the runtime PL/SQL engine) and verify the algorithm.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;My sense is that relatively few developers spend the requisite time to simply sit and read their code. They instead rely on tracing, debugging, &lt;em&gt;trying&lt;/em&gt;.  A de-emphasis on reading/verifying logic results in a poorly-trained eye and the likelihood that you will "skip over" bugs and other kinds of weaknesses in your programs.&lt;/p&gt;
&lt;div&gt;So next time you are truly puzzled by what your program is doing, the next time you say to yourself "That's impossible!", recognize that it is not only possible, but happening, and go back to the code and read it line by line with care and objectivity.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;&lt;br /&gt;&lt;a href=http://www.toadworld.com/Blogs/tabid/67/EntryId/536/Little-things-can-get-you.aspx&gt;More ...&lt;/a&gt;&lt;div class="tags"&gt;Tags: plsql&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/536/Little-things-can-get-you.aspx#Comments</comments>
      <slash:comments>4</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/536/Little-things-can-get-you.aspx</guid>
      <pubDate>Wed, 05 May 2010 13:17:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=536</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
    </item>
    <item>
      <title>New standards document available</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/533/New-standards-document-available.aspx</link>
      <description>&lt;div&gt;The &lt;a href="http://www.toadworld.com/LinkClick.aspx?link=580&amp;tabid=67"&gt;PL/SQL Standards page&lt;/a&gt; of &lt;a href="http://www.toadworld.com/LinkClick.aspx?link=153&amp;tabid=67"&gt;PL/SQL Obsession&lt;/a&gt; now offers a third choice for pre-defined standards for PL/SQL development.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;This document has been fine-tuned by Bill Coulam (&lt;a href="http://www.dbartisans.com/"&gt;www.dbartisans.com&lt;/a&gt;) as part of his effort to construct a development framework for PL/SQL applications. You don't have to use his framework, however, to benefit from his standards. Many thanks to Bill for sharing his experience and efforts with us!&lt;/div&gt;&lt;br /&gt;&lt;a href=http://www.toadworld.com/Blogs/tabid/67/EntryId/533/New-standards-document-available.aspx&gt;More ...&lt;/a&gt;&lt;div class="tags"&gt;Tags: plsql,standards,oracle&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/533/New-standards-document-available.aspx#Comments</comments>
      <slash:comments>0</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/533/New-standards-document-available.aspx</guid>
      <pubDate>Mon, 26 Apr 2010 19:49:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=533</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/172/Default.aspx">standards</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/2/Default.aspx">oracle</blog:tag>
    </item>
    <item>
      <title>Collaborate 10 - A report from the casinos</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/531/Collaborate-10-A-report-from-the-casinos.aspx</link>
      <description>&lt;div&gt;
&lt;p&gt;I've just returned from Collaborate 10, the international Oracle conference organized through a collaboration (hence the name!) between IOUG, Quest (the user group) and OAUG.&lt;/p&gt;
&lt;p&gt;It was held at the Mandalay Bay Convention Center in Las Vegas. Now, I must admit, I really don't like Las Vegas (the pretend parts) very much at all. The &lt;em&gt;real&lt;/em&gt; parts, like the &lt;a href="http://www.redrockcanyonlv.org/"&gt;Red Rock Canyon National Conservation Area&lt;/a&gt;, are beautiful and I very much enjoy. Forests of slot machines surrounded by posters hawking various forms of excess? They just don't do much for me.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;Fortunately, I was there to "work" (as if you can really call what I and most programmers do &lt;em&gt;work&lt;/em&gt;). So I could bury my curmudgeonly inclinations under a burning obsession with the PL/SQL language.&lt;/p&gt;
&lt;p&gt;I did a couple of presentations, including my first ever PL/SQL quiz. As you may know, I recently started the &lt;a href="http://www.plsqlchallenge.com/"&gt;&lt;font color="#800080"&gt;PL/SQL Challenge&lt;/font&gt;&lt;/a&gt;, a daily PL/SQL quiz that culminates in a quarterly championship, with a grand prize of $1000 USD (with other prizes along the way). Needless to say, if you haven't already started playing the Challenge, get over there fast, register, and start taking the quiz!&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;Reading documentation and books are fine, but I think that taking a quiz, getting the competitive juices flowing, is a great way to focus our brains and learn more effectively. So I have decided to start offering PL/SQL quizzes as technical sessions at conferences.&lt;/p&gt;
&lt;p&gt;On Monday afternoon, over 150 developers filled the Palm C room to take the quiz. In addition, my session was streamed out over the Internet, so hopefully hundreds more also played. I presented ten multiple choice questions (which I will &lt;em&gt;not&lt;/em&gt; repeat here! You may, after all, attend such a quiz in the future.) We then went through the answers.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;I was very impressed with how many people knew about AUTHID CURRENT_USER (invoker rights). And I found that the number of people aware of and using collections (with all their related benefits, like FORALL and BULK COLLECT) seems to be growing. Excllent!&lt;/p&gt;
&lt;p&gt;Many people came up afterwards to tell me they enjoyed taking the quiz. I heard later from another attendee that her co-worker, who had attended one of my trainings last year, was very excited. He says he got the quiz 100% right. That &lt;em&gt;is&lt;/em&gt; impressive.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;I also learned about ways to improve the quiz:&lt;/div&gt;
&lt;ul type="disc"&gt;
    &lt;li&gt;It would be nice to provide answer forms, so you can easily mark your choices and compare them to my answers later.&lt;/li&gt;
    &lt;li&gt;You need to have hard-copies of any questions with more than a few lines of code. It is very hard to stare at a screen and absorb the details of a block of code.&lt;/li&gt;
    &lt;li&gt;I need to have example scripts pre-written to verify all answers, clearly and quickly. Can't afford to waste time fumbling around typing up blocks of code on the fly!&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;p&gt;I will be able to apply all these lessons almost immediately. On 29 June 2010, at ODTUG's &lt;a href="http://odtugkaleidoscope.com/"&gt;Kaleidoscope conference&lt;/a&gt;, ODTUG and the &lt;a href="http://www.plsqlchallenge.com/"&gt;&lt;font color="#800080"&gt;PL/SQL Challenge&lt;/font&gt;&lt;/a&gt; will co-sponsor a special evening event, "PL/SQL Developer, Quiz Thyself," that will feature another PL/SQL quiz, this time with a first place cash prize of $500, and many other fantastic prizes. This will be a &lt;em&gt;monitored&lt;/em&gt; quiz - we will grade your answers, rather than rely on the honor system (hey, there's money involved!). It will, therefore, be a great opportunity to demonstrate your deep knowledge of PL/SQL.&lt;/p&gt;
&lt;p&gt;But to win, you must attend &lt;a href="http://odtugkaleidoscope.com/"&gt;Kaleidoscope&lt;/a&gt; &lt;em&gt;and&lt;/em&gt; come to the quiz event. I hope to see you there, and best of luck in both the &lt;a href="http://www.plsqlchallenge.com/"&gt;&lt;font color="#800080"&gt;PL/SQL Challenge&lt;/font&gt;&lt;/a&gt; and the &lt;a href="http://odtugkaleidoscope.com/"&gt;Kaleidoscope&lt;/a&gt; quiz.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;My second presentation on error management also went well. Another full room, lots of good questions, not enough time to get through all the material.&lt;/p&gt;
&lt;p&gt;Here are the main points from that presentation:&lt;/p&gt;
&lt;/div&gt;
&lt;ul type="disc"&gt;
    &lt;li&gt;When an exception is raised in the declaration section, it always propagates unhandled to the outer block.&lt;/li&gt;
    &lt;li&gt;Call DBMS_UTILITY.FORMAT_CALL_STACK whenever you log or trace. It answers the question "How did I get here?"&lt;/li&gt;
    &lt;li&gt;Call DBMS_UTILITY.FORMAT_ERROR_STACK instead of SQLERRM, to avoid possible truncation of error message text.&lt;/li&gt;
    &lt;li&gt;Call DBMS_UTILITY.FORMAT_ERROR_BACKTRACE whenever you log an error. It answers the question "On what line of code was my error raised?" (RDBMS version 10.2 and higher)&lt;/li&gt;
    &lt;li&gt;All developers should use a shared utility to raise, handle, log and communicate errors. If you don't already have one in place, check out the &lt;a href="http://toadworld.com/LinkClick.aspx?link=685&amp;tabid=153"&gt;Quest Error Manager&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;p&gt;In between my presentations, I took advantage of the Luxor Hotel's very nice fitness center. I also spent a most enjoyable evening at a party sponsored by Oracle Magazine. They reserved the whole Red Square restaurant to celebrate a thorough re-design of the magazine. They even had new photos taken of all their columnists. Oh, and Oracle has penned an agreement with Marvel Comics to use the Iron Man character (and upcoming sequel movie) to promote Oracle technology. So...look for references to Oracle in Iron Man 2.&lt;/p&gt;
&lt;p&gt;From what I could tell, the Collaborate conference bounced back very nicely from a big drop in attendance experienced in 2009 (when everyone was worried that the fall of capitalism would throw us into a deep depression). There seemed to be a whole lot of people hurrying from session to casino to restaurant to session to pool to....doing whatever it is people do in Vegas that "stays in Vegas."&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;&lt;br /&gt;&lt;a href=http://www.toadworld.com/Blogs/tabid/67/EntryId/531/Collaborate-10-A-report-from-the-casinos.aspx&gt;More ...&lt;/a&gt;&lt;div class="tags"&gt;Tags: plsql&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/531/Collaborate-10-A-report-from-the-casinos.aspx#Comments</comments>
      <slash:comments>0</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/531/Collaborate-10-A-report-from-the-casinos.aspx</guid>
      <pubDate>Thu, 22 Apr 2010 14:44:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=531</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
    </item>
    <item>
      <title>Making sure invoker rights is defined properly</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/527/Making-sure-invoker-rights-is-defined-properly.aspx</link>
      <description>&lt;p&gt;"Invoker rights, what's that?" you may be asking.&lt;/p&gt;
&lt;p&gt;That wouldn't surprise me, greatly, though one might consider it a bit odd because the invoker rights feature of PL/SQL was added in Oracle8i - many years ago!&lt;/p&gt;
&lt;p&gt;So I will first offer a brief overview of invoker rights, why you'd use it, how you use it. Then I will introduce one of the major challenges with invoker rights. Finally, I offer a utility that can help you overcome that challenge.&lt;/p&gt;
&lt;p&gt;When you create a PL/SQL program unit, you can include an optional AUTHID clause. There are two forms of this clause:&lt;/p&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;p style="margin-right: 0px" dir="ltr"&gt;AUTHID DEFINER&lt;br /&gt;
AUTHID CURRENT_USER&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p style="margin-right: 0px" dir="ltr"&gt;AUTHID DEFINER is the default. So these two procedures specify "definer rights"&lt;/p&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;pre style="margin-right: 0px" dir="ltr"&gt;PROCEDURE show_emp_count AUTHID DEFINER&lt;br /&gt;PROCEDURE show_emp_count&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p style="margin-right: 0px" dir="ltr"&gt;And this version specifies "invoker rights":&lt;/p&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;pre style="margin-right: 0px" dir="ltr"&gt;PROCEDURE show_emp_count AUTHID CURRENT_USER&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p style="margin-right: 0px" dir="ltr"&gt;So that's the syntax. What does it do for you?&lt;/p&gt;
&lt;p style="margin-right: 0px" dir="ltr"&gt;In many application environments, the code is owned by one schema (let's call it CODE_SCHEMA), and then privileges are granted to execute that code to other schemas (USER_SCHEMA).&lt;/p&gt;
&lt;p style="margin-right: 0px" dir="ltr"&gt;When a program unit is created in CODE_SCHEMA with definer rights, then when a user connected to USER_SCHEMA runs that program, it runs under the privileges of CODE_SCHEMA.&lt;/p&gt;
&lt;p style="margin-right: 0px" dir="ltr"&gt;When a program unit is created in CODE_SCHEMA with invoker rights, then when a user connected to USER_SCHEMA runs that program, it runs under the privileges of USER_SCHEMA. And all such privileges must be directly granted (no role-based privileges).&lt;/p&gt;
&lt;p style="margin-right: 0px" dir="ltr"&gt;In other words, at the time an invoker rights program is executed, Oracle resolves all references to SQL-related database objects (tables and views, for the most part) according to the current user's privileges, and not the privileges of the owner of the program. And role-based privileges are used by Oracle with invoker rights programs.&lt;/p&gt;
&lt;p style="margin-right: 0px" dir="ltr"&gt;I will step through a simple demonstration below. You are, however, probably wondering what invoker rights is good for. Invoker rights comes in very handy whenever you have a program that needs to work differently (with different tables) depending on who is running the code.&lt;/p&gt;
&lt;p style="margin-right: 0px" dir="ltr"&gt;Consider &lt;a href="http://www.quest.com/code-tester-for-oracle"&gt;Quest Code Tester for Oracle&lt;/a&gt;. This automated testing tool for PL/SQL is built around a test repository: 30+ tables and associated code. Usually, this repository is installed in a central schema, and then access to the repository is allowed through synonyms.&lt;/p&gt;
&lt;p style="margin-right: 0px" dir="ltr"&gt;As a use of Quest Code Tester, I connect to my own development schema, and then call Code Tester programs to define and run my tests.&lt;/p&gt;
&lt;p style="margin-right: 0px" dir="ltr"&gt;If Quest Code Tester relied on definer rights, then the test repository schema would need to have the authority to execute code in all the development schemas, and probably have directly granted privileges on underlying tables as well. That is a very risky test repository and most DBAs will not create such a powerful schema.&lt;/p&gt;
&lt;p style="margin-right: 0px" dir="ltr"&gt;Instead, many of the packages in Quest Code Tester are defined as invoker rights. So when the developer asks Code Tester to run a test of the program in her schema, no special privileges are needed in the test repository schema. And Code Tester is not able to do anything to application data that the developer's code does not specifically allow.&lt;br /&gt;
In essence, with invoker rights, Oracle "reflects" back into the invoking schema to resolve references as you see below:&lt;/p&gt;
&lt;p style="margin-right: 0px" dir="ltr"&gt;&lt;img alt="" src="/Portals/0/blogimages/Steven Feuerstein/SF-Blog041310-1.gif" /&gt;&lt;br /&gt;
 &lt;br /&gt;
Now let's walk through a simple demonstration. I will first create a table in SCOTT with two rows:&lt;/p&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;pre style="margin-right: 0px" dir="ltr"&gt;&lt;font color="#0000ff"&gt;CONNECT&lt;/font&gt; scott&lt;font color="#0000ff"&gt;/&lt;/font&gt;tiger&lt;/pre&gt;
&lt;pre&gt;&lt;font color="#0000ff"&gt;CREATE TABLE&lt;/font&gt; authid_demo &lt;font color="#0000ff"&gt;(&lt;/font&gt;n &lt;font color="#ff0000"&gt;NUMBER&lt;/font&gt;&lt;font color="#0000ff"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;/&lt;/font&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;BEGIN&lt;br /&gt;   INSERT INTO&lt;/strong&gt;&lt;/font&gt; authid_demo&lt;br /&gt;   &lt;strong&gt;&lt;font color="#0000ff"&gt;VALUES (&lt;/font&gt;&lt;font color="#800000"&gt;1&lt;/font&gt;&lt;font color="#0000ff"&gt;);&lt;/font&gt;&lt;/strong&gt;&lt;/pre&gt;
&lt;pre&gt;   &lt;font color="#0000ff"&gt;&lt;strong&gt;INSERT INTO&lt;/strong&gt;&lt;/font&gt; authid_demo&lt;br /&gt;   &lt;strong&gt;&lt;font color="#0000ff"&gt;VALUES (&lt;/font&gt;&lt;font color="#800000"&gt;2&lt;/font&gt;&lt;font color="#0000ff"&gt;);&lt;/font&gt;&lt;/strong&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;strong&gt;  &lt;/strong&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt; COMMIT;&lt;br /&gt;END;&lt;br /&gt;/&lt;/strong&gt;&lt;/font&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;I will create the "same" table in HR, but with no rows:&lt;/p&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;pre&gt;&lt;font color="#0000ff"&gt;CONNECT&lt;/font&gt; hr&lt;font color="#0000ff"&gt;/&lt;/font&gt;hr&lt;/pre&gt;
&lt;pre&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;CREATE TABLE&lt;/strong&gt;&lt;/font&gt; authid_demo &lt;font color="#0000ff"&gt;(&lt;/font&gt;n &lt;font color="#ff0000"&gt;NUMBER&lt;/font&gt;&lt;font color="#0000ff"&gt;)&lt;br /&gt;&lt;strong&gt;/&lt;/strong&gt;&lt;/font&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;Then in SCOTT, I create three procedures, each of which do mostly the same thing: show the number of rows in the authid_demo table.&lt;/p&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;pre&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;CREATE OR REPLACE PROCEDURE&lt;/strong&gt;&lt;/font&gt; proc1 &lt;font color="#0000ff"&gt;&lt;strong&gt;AUTHID CURRENT_USER&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;IS&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;   num   &lt;font color="#0000ff"&gt;&lt;strong&gt;PLS_INTEGER;&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;BEGIN&lt;br /&gt;   SELECT COUNT (&lt;/strong&gt;&lt;/font&gt;*&lt;font color="#0000ff"&gt;&lt;strong&gt;) INTO&lt;/strong&gt;&lt;/font&gt; num &lt;font color="#0000ff"&gt;&lt;strong&gt;FROM&lt;/strong&gt;&lt;/font&gt; authid_demo;&lt;br /&gt;   &lt;em&gt;DBMS_OUTPUT.put_line&lt;/em&gt; &lt;font color="#0000ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="#ff0000"&gt;'proc 1 invoker authid_demo count = '&lt;/font&gt; || num&lt;font color="#0000ff"&gt;&lt;strong&gt;);&lt;br /&gt;END;&lt;br /&gt;/&lt;/strong&gt;&lt;/font&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;CREATE OR REPLACE PROCEDURE&lt;/strong&gt;&lt;/font&gt; proc2 &lt;font color="#0000ff"&gt;&lt;strong&gt;AUTHID DEFINER&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#0000ff"&gt;IS&lt;br /&gt;&lt;/font&gt;&lt;/strong&gt;   &lt;font color="#0000ff"&gt;&lt;font color="#000000" size="+0"&gt;num&lt;/font&gt;   &lt;strong&gt;PLS_INTEGER;&lt;br /&gt;BEGIN&lt;br /&gt;   SELECT COUNT (&lt;/strong&gt;&lt;/font&gt;*&lt;font color="#0000ff"&gt;&lt;strong&gt;) INTO&lt;/strong&gt;&lt;/font&gt; num &lt;font color="#0000ff"&gt;&lt;strong&gt;FROM&lt;/strong&gt;&lt;/font&gt; authid_demo;&lt;br /&gt;   &lt;em&gt;DBMS_OUTPUT.put_line&lt;/em&gt; &lt;font color="#0000ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="#ff0000"&gt;'proc 2 definer authid_demo count = '&lt;/font&gt; || num&lt;font color="#0000ff"&gt;&lt;strong&gt;);&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;   proc1;&lt;br /&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;END;&lt;br /&gt;/&lt;/strong&gt;&lt;/font&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;CREATE OR REPLACE PROCEDURE&lt;/strong&gt;&lt;/font&gt; proc3 &lt;font color="#0000ff"&gt;&lt;strong&gt;AUTHID CURRENT_USER&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;IS&lt;br /&gt;&lt;/strong&gt;&lt;/font&gt;   num   &lt;font color="#0000ff"&gt;&lt;strong&gt;PLS_INTEGER;&lt;br /&gt;BEGIN&lt;br /&gt;   SELECT COUNT (&lt;/strong&gt;&lt;/font&gt;*&lt;font color="#0000ff"&gt;&lt;strong&gt;) INTO&lt;/strong&gt;&lt;/font&gt; num &lt;font color="#0000ff"&gt;&lt;strong&gt;FROM&lt;/strong&gt;&lt;/font&gt; authid_demo;&lt;br /&gt;   &lt;em&gt;DBMS_OUTPUT.put_line&lt;/em&gt; &lt;font color="#0000ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="#ff0000"&gt;'proc 3 invoker authid_demo count = '&lt;/font&gt; || num&lt;font color="#0000ff"&gt;&lt;strong&gt;);&lt;br /&gt;&lt;/strong&gt;&lt;/font&gt;   proc1;&lt;br /&gt;   proc2;&lt;br /&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;END;&lt;br /&gt;/&lt;/strong&gt;&lt;/font&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;Note that we have these two sequence of calls:&lt;/p&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;pre&gt;PROC3 -&gt; PROC1&lt;br /&gt;PROC3 -&gt; PROC2 -&gt; PROC1&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;and that PROC3 and PROC1 are invoker rights, while PROC2 is definer rights.&lt;/p&gt;
&lt;p&gt;I then allow HR to run all this code and access the underlying table in SCOTT:&lt;/p&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;pre&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;GRANT&lt;/strong&gt; EXECUTE &lt;strong&gt;ON&lt;/strong&gt;&lt;/font&gt; proc1 &lt;font color="#0000ff"&gt;&lt;strong&gt;TO&lt;/strong&gt;&lt;/font&gt; hr&lt;br /&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;/&lt;/strong&gt;&lt;/font&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;GRANT&lt;/strong&gt; EXECUTE &lt;strong&gt;ON&lt;/strong&gt;&lt;/font&gt; proc2 &lt;font color="#0000ff"&gt;&lt;strong&gt;TO&lt;/strong&gt;&lt;/font&gt; hr&lt;br /&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;/&lt;/strong&gt;&lt;/font&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;GRANT&lt;/strong&gt; EXECUTE &lt;strong&gt;ON&lt;/strong&gt;&lt;/font&gt; proc3 &lt;font color="#0000ff"&gt;&lt;strong&gt;TO&lt;/strong&gt;&lt;/font&gt; hr&lt;br /&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;/&lt;/strong&gt;&lt;/font&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;GRANT&lt;/strong&gt; SELECT &lt;strong&gt;ON&lt;/strong&gt;&lt;/font&gt; scott.authid_demo &lt;font color="#0000ff"&gt;&lt;strong&gt;TO&lt;/strong&gt;&lt;/font&gt; hr&lt;br /&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;/&lt;/strong&gt;&lt;/font&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;Finally, I run PROC3 - from HR:&lt;/p&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;pre&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;BEGIN&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;   scott.proc3&lt;font color="#0000ff"&gt;&lt;strong&gt;;&lt;br /&gt;END;&lt;br /&gt;/&lt;/strong&gt;&lt;/font&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here's the output I see:&lt;/p&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;pre&gt;Line 1: proc 3 invoker authid_demo count = 0&lt;br /&gt;Line 2: proc 1 invoker authid_demo count = 0&lt;br /&gt;Line 3: proc 2 definer authid_demo count = 2&lt;br /&gt;Line 4: proc 1 invoker authid_demo count = 2&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;Lines 1 and 2 demonstrate invoker rights at work: even though HR called SCOTT's PROC3 and PROC1 programs, the count of rows in authid_demo is retuned as 0, not 2.&lt;/p&gt;
&lt;p&gt;Line 3 demonstrates definer rights: it shows the number of rows in SCOTT's authid_demo table, even though the program was called by HR.&lt;/p&gt;
&lt;p&gt;But line 4 - now that is puzzling, isn't it? Notice that I got an answer of 2, not 0, for the count in the authid_demo table. Yet I called the same program (PROC1) that two lines earlier showed 2.&lt;/p&gt;
&lt;p&gt;So: same code executes, but returns different answer. Very troubling, wouldn't you say?&lt;/p&gt;
&lt;p&gt;Here's the problem: if at any point along the execution call stack (in this case, PROC3 -&gt; PROC2 -&gt; PROC1), a definer rights program is executed, then from that point on down the stack the "current user" is resolved by Oracle to be the owner of that definer rights program and not the currently connected user.&lt;/p&gt;
&lt;p&gt;When PROC3 called PROC1, that was invoker rights calling invoker rights, and so the current user was HR and the procedure showed 0 rows.&lt;/p&gt;
&lt;p&gt;When PROC3 called PROC2, Oracle reset "current user" to SCOTT. Then when PROC2 called PROC1, Oracle resolved the reference to the authid_demo table using SCOTT, and theprocedure therefore showed 2 rows.&lt;/p&gt;
&lt;p&gt;This change in expected behavior can cause many problems in your application, ranging from raising "table or view does not exist" and "insufficient privileges" errors to returning or changing the wrong rows of data.&lt;/p&gt;
&lt;p&gt;Assuming this is not the behavior you want, you need to make sure that all the program units executed in your call stack are all definer rights or all invoker rights, or at least that once you call a definer rights program, you only call other definer rights programs from that point on.&lt;/p&gt;
&lt;p&gt;Fine advice (at least I think so), but how do you apply it? Call stacks in real applications can be very deep, easily a dozen or more entries. Plus, how can you even get hold of the call stack to analyze it?&lt;/p&gt;
&lt;p&gt;First, you can call the DBMS_UTILITY.FORMAT_CALL_STACK at any point in your code, and Oracle will return a string that contains the call stack. Here's an example of the formatted call stack Oracle returns, taken from the Quest Code Tester log:&lt;/p&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;p style="margin-right: 0px" dir="ltr"&gt; &lt;/p&gt;
&lt;pre&gt;----- PL/SQL Call Stack -----&lt;br /&gt;  object      line  object&lt;br /&gt;  handle    number  name&lt;br /&gt;3B6C8C64         1  anonymous block&lt;br /&gt;3FA473E8      1012  package body QCTO183.QU_RUNTIME&lt;br /&gt;3FA473E8      1042  package body QCTO183.QU_RUNTIME&lt;br /&gt;3FA32EF8      3120  package body QCTO183.QU_ALL_OBJECTS&lt;br /&gt;3FA32EF8      3138  package body QCTO183.QU_ALL_OBJECTS&lt;br /&gt;3FA12F2C      2613  package body QCTO183.QU_GENERATE&lt;br /&gt;3FA12F2C      3269  package body QCTO183.QU_GENERATE&lt;br /&gt;3FA12F2C      3341  package body QCTO183.QU_GENERATE&lt;br /&gt;3FA12F2C      3601  package body QCTO183.QU_GENERATE&lt;br /&gt;3FA12F2C      6192  package body QCTO183.QU_GENERATE&lt;br /&gt;3FA12F2C      8835  package body QCTO183.QU_GENERATE&lt;br /&gt;3FA12F2C      9138  package body QCTO183.QU_GENERATE&lt;br /&gt;3FA12F2C      9196  package body QCTO183.QU_GENERATE&lt;br /&gt;3FA12F2C      9487  package body QCTO183.QU_GENERATE&lt;br /&gt;4DA12F23      9737  package body QCTO183.QU_HARNESS&lt;br /&gt;3BC12F2C      9800  package body QCTO183.QU_TEST&lt;br /&gt;3BC12F2C     10130  package body QCTO183.QU_TEST&lt;br /&gt;3B6F83F8         4  anonymous block&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p style="margin-right: 0px" dir="ltr"&gt;So to follow my own advice, I would now have to open each of these package specifications and check the AUTHID setting. That's rather tedious.&lt;/p&gt;
&lt;p style="margin-right: 0px" dir="ltr"&gt;Perhaps there is another way. Consider the ALL_PROCEDURES data dictionary view:&lt;/p&gt;
&lt;p style="margin-right: 0px" dir="ltr"&gt;&lt;img alt="" src="/Portals/0/blogimages/Steven Feuerstein/SF-Blog041310-2.gif" /&gt;&lt;br /&gt;
 &lt;br /&gt;
Notice the AUTHID column. You can look up the AUTHID setting for your program unit from this view. So it seems as though you could write a program to parse the call stack and then look up the AUTHID setting for each program unit in the stack, and make sure there are no problems with  a switch from invoker rights to definer rights, and back, in that stack.&lt;/p&gt;
&lt;p style="margin-right: 0px" dir="ltr"&gt;Yes, you &lt;em&gt;could&lt;/em&gt; do that. But likely you want, because you have a &lt;em&gt;real job&lt;/em&gt; and a &lt;em&gt;real life&lt;/em&gt; and very little time to write such programs.&lt;/p&gt;
&lt;p style="margin-right: 0px" dir="ltr"&gt;Fortunately, I don't have a "real job" (well, believe you me, they keep me very busy here at Quest, but they also more or less let me do what I want. &lt;font face="Wingdings"&gt;J&lt;/font&gt; ) and I sure don't have a real life. My office is at home, so the boundaries between work (PL/SQL) and non-work crumbled years ago.&lt;/p&gt;
&lt;p style="margin-right: 0px" dir="ltr"&gt;Well, enough about me and my life. The bottom line is that I have created a package, called authid_analysis, available in authid_analysis.pkg file of my &lt;a href="http://www.toadworld.com/Portals/0/stevenf/demo.zip"&gt;demo.zip&lt;/a&gt;, that will perform precisely this analysis on your behalf.&lt;/p&gt;
&lt;p style="margin-right: 0px" dir="ltr"&gt;Here's the header of the package:&lt;/p&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;pre style="margin-right: 0px" dir="ltr"&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;CREATE OR REPLACE PACKAGE&lt;/strong&gt;&lt;/font&gt; authid_analysis&lt;br /&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;IS&lt;br /&gt;   FUNCTION&lt;/strong&gt;&lt;/font&gt; authid_setting &lt;font color="#0000ff"&gt;(&lt;/font&gt;program_owner_in &lt;font color="#0000ff"&gt;&lt;strong&gt;IN&lt;/strong&gt;&lt;/font&gt; &lt;font color="#ff0000"&gt;VARCHAR2&lt;/font&gt;&lt;br /&gt;                          &lt;font color="#0000ff"&gt;,&lt;/font&gt; program_name_in  &lt;font color="#0000ff"&gt;&lt;strong&gt;IN&lt;/strong&gt;&lt;/font&gt; &lt;font color="#ff0000"&gt;VARCHAR2&lt;/font&gt;&lt;br /&gt;                           &lt;font color="#0000ff"&gt;)&lt;br /&gt;&lt;/font&gt;      &lt;font color="#0000ff"&gt;&lt;strong&gt;RETURN&lt;/strong&gt;&lt;/font&gt; &lt;font color="#ff0000"&gt;VARCHAR2&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;/font&gt;&lt;/pre&gt;
&lt;pre&gt;   &lt;font color="#0000ff"&gt;&lt;strong&gt;FUNCTION&lt;/strong&gt;&lt;/font&gt; is_current_user &lt;font color="#0000ff"&gt;(&lt;/font&gt;program_owner_in &lt;font color="#0000ff"&gt;&lt;strong&gt;IN&lt;/strong&gt;&lt;/font&gt; &lt;font color="#ff0000"&gt;VARCHAR2&lt;/font&gt;&lt;br /&gt;                           &lt;font color="#0000ff"&gt;,&lt;/font&gt; program_name_in  &lt;font color="#0000ff"&gt;&lt;strong&gt;IN&lt;/strong&gt;&lt;/font&gt; &lt;font color="#ff0000"&gt;VARCHAR2&lt;/font&gt;&lt;br /&gt;                            &lt;font color="#0000ff"&gt;)&lt;/font&gt;&lt;br /&gt;      &lt;font color="#0000ff"&gt;&lt;strong&gt;RETURN&lt;/strong&gt;&lt;/font&gt; &lt;font color="#0000ff"&gt;&lt;strong&gt;BOOLEAN&lt;/strong&gt;&lt;/font&gt;;&lt;/pre&gt;
&lt;pre&gt;   &lt;font color="#0000ff"&gt;&lt;strong&gt;FUNCTION&lt;/strong&gt;&lt;/font&gt; is_definer &lt;font color="#0000ff"&gt;(&lt;/font&gt;program_owner_in &lt;font color="#0000ff"&gt;&lt;strong&gt;IN&lt;/strong&gt;&lt;/font&gt; &lt;font color="#ff0000"&gt;VARCHAR2&lt;/font&gt;&lt;br /&gt;                      &lt;font color="#0000ff"&gt;,&lt;/font&gt; program_name_in  &lt;font color="#0000ff"&gt;&lt;strong&gt;IN&lt;/strong&gt;&lt;/font&gt; &lt;font color="#ff0000"&gt;VARCHAR2&lt;/font&gt;&lt;br /&gt;                       &lt;font color="#0000ff"&gt;)&lt;/font&gt;&lt;br /&gt;      &lt;font color="#0000ff"&gt;&lt;strong&gt;RETURN BOOLEAN;&lt;/strong&gt;&lt;/font&gt;&lt;/pre&gt;
&lt;pre&gt;   &lt;font color="#0000ff"&gt;&lt;strong&gt;PROCEDURE&lt;/strong&gt;&lt;/font&gt; analyze_callstack &lt;font color="#0000ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;callstack_in &lt;font color="#0000ff"&gt;&lt;strong&gt;IN&lt;/strong&gt;&lt;/font&gt; &lt;font color="#ff0000"&gt;VARCHAR2&lt;/font&gt; &lt;font color="#0000ff"&gt;&lt;strong&gt;DEFAULT NULL);&lt;br /&gt;END&lt;/strong&gt;&lt;/font&gt; authid_analysis&lt;font color="#0000ff"&gt;&lt;strong&gt;;&lt;/strong&gt;&lt;/font&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;You can retrieve the AUTHID setting of a program from ALL_PROCEDURES and find out if a program is invoker rights (is_current_user) or definer rights (is_definer).&lt;/p&gt;
&lt;p&gt;Finally, call the analyze_callstack procedure to identify possible problems, as described above. If you do not pass the call stack, analyze_callstack will call the FORMAT_CALL_STACK function for you.&lt;/p&gt;
&lt;p&gt;You can easily integrate this package into your error logging and tracing routine, making it easy to identify possible program areas in your code. I plan to add this to &lt;a href="http://www.toadworld.com/LinkClick.aspx?link=685&amp;tabid=67"&gt;Quest Error Manager&lt;/a&gt; as soon as I have a moment.&lt;/p&gt;
&lt;p&gt;The authid_analysis.tst scritp will allow you run a quick test of this utility. Here's what I see:&lt;/p&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;pre&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;CREATE OR REPLACE PROCEDURE&lt;/strong&gt;&lt;/font&gt; proc1&lt;br /&gt;   &lt;font color="#0000ff"&gt;&lt;strong&gt;AUTHID CURRENT_USER&lt;br /&gt;IS&lt;br /&gt;BEGIN&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;   authid_analysis.analyze_callstack;&lt;br /&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;END;&lt;br /&gt;/&lt;/strong&gt;&lt;/font&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;CREATE OR REPLACE PROCEDURE&lt;/strong&gt;&lt;/font&gt; proc2&lt;br /&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;IS&lt;br /&gt;BEGIN&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;   proc1;&lt;br /&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;END;&lt;br /&gt;/&lt;/strong&gt;&lt;/font&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;CREATE OR REPLACE PROCEDURE&lt;/strong&gt;&lt;/font&gt; proc3&lt;br /&gt;   &lt;font color="#0000ff"&gt;&lt;strong&gt;AUTHID CURRENT_USER&lt;br /&gt;IS&lt;br /&gt;BEGIN&lt;br /&gt;&lt;/strong&gt;&lt;/font&gt;   proc2;&lt;br /&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;END;&lt;br /&gt;/&lt;/strong&gt;&lt;/font&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;BEGIN&lt;br /&gt;&lt;/strong&gt;&lt;/font&gt;   proc3;&lt;br /&gt;&lt;strong&gt;&lt;font color="#0000ff"&gt;END;&lt;br /&gt;/&lt;br /&gt;&lt;/font&gt;&gt; DEFINER      package body HR.AUTHID_ANALYSIS called by...&lt;br /&gt;&gt; CURRENT_USER procedure HR.PROC1 called by...&lt;br /&gt;&gt; DEFINER      procedure HR.PROC2 called by...&lt;br /&gt;&gt; CURRENT_USER procedure HR.PROC3 called by...&lt;br /&gt;&gt;              anonymous block&lt;/strong&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;As you can see, I have a switch from invoker rights to definer rights in the call to PROC2 and that will likely cause problems.&lt;/p&gt;
&lt;p&gt;I hope you find this utility useful.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;&lt;br /&gt;&lt;a href=http://www.toadworld.com/Blogs/tabid/67/EntryId/527/Making-sure-invoker-rights-is-defined-properly.aspx&gt;More ...&lt;/a&gt;&lt;div class="tags"&gt;Tags: plsql,oracle,invoker rights&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/527/Making-sure-invoker-rights-is-defined-properly.aspx#Comments</comments>
      <slash:comments>0</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/527/Making-sure-invoker-rights-is-defined-properly.aspx</guid>
      <pubDate>Tue, 13 Apr 2010 12:54:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=527</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/2/Default.aspx">oracle</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/171/Default.aspx">invoker rights</blog:tag>
    </item>
    <item>
      <title>Books That Taught Me Lots</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/521/Books-That-Taught-Me-Lots.aspx</link>
      <description>I have certainly learned a lot over the years from other authors, and I thought I would share with you my fairly eclectic collection of favorite books (those that have informed my programming, in any case). </description>
      <author>Steven Feuerstein</author>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/521/Books-That-Taught-Me-Lots.aspx#Comments</comments>
      <slash:comments>1</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/521/Books-That-Taught-Me-Lots.aspx</guid>
      <pubDate>Mon, 29 Mar 2010 13:01:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=521</trackback:ping>
    </item>
    <item>
      <title>Beta Testing Starts for the PL/SQL Challenge</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/516/Beta-Testing-Starts-for-the-PL-SQL-Challenge.aspx</link>
      <description>&lt;p&gt;The PL/SQL Challenge is a daily quiz that culminates every three months in a championship tournament to determine the most knowledgeable PL/SQL developers in the world. You could win cash, O'Reilly Media books and other goodies - but only if you play!&lt;/p&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/516/Beta-Testing-Starts-for-the-PL-SQL-Challenge.aspx#Comments</comments>
      <slash:comments>0</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/516/Beta-Testing-Starts-for-the-PL-SQL-Challenge.aspx</guid>
      <pubDate>Thu, 18 Mar 2010 15:14:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=516</trackback:ping>
    </item>
    <item>
      <title>Say goodbye to hard-coding!</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/510/Say-goodbye-to-hard-coding.aspx</link>
      <description>&lt;p&gt;We all know that hard-coding is a bad thing in software. But most developers think of hard-coding simply as typing a literal value into your program whenever you need it.&lt;/p&gt;&lt;div class="tags"&gt;Tags: plsql,package,oracle&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/510/Say-goodbye-to-hard-coding.aspx#Comments</comments>
      <slash:comments>1</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/510/Say-goodbye-to-hard-coding.aspx</guid>
      <pubDate>Mon, 01 Mar 2010 16:26:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=510</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/164/Default.aspx">package</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/2/Default.aspx">oracle</blog:tag>
    </item>
    <item>
      <title>Code Tester Version 1.9 Now Available!</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/506/Code-Tester-Version-1-9-Now-Available.aspx</link>
      <description>&lt;div&gt;You can now &lt;a href="http://unittest.inside.quest.com/downloads.jspa"&gt;download&lt;/a&gt; version 1.9 of Code Tester. This release features the following enhancements:&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;strong&gt;Object type support&lt;/strong&gt;   You can now test directly the methods of object types, test the contents of object type instances for equality and inequality, and specify the values of attributes through a grid.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;strong&gt;Default value support&lt;/strong&gt;   You now request that the default of a parameter be used when testing your program. The generated test code will not pass a value for this argument.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;strong&gt;Improved code coverage support&lt;/strong&gt;   You can now specify your code coverage target as a percentage, both as a preference (global target) and for specific program units. Actual code coverage % and target % values are now shown in Test Editor and code coverage reports. These reports have also been expanded.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;strong&gt;Specifying order of execution of test suites&lt;/strong&gt;   You can now specify the order of execution of tests in a suite through the Dashboard (right-click on suite name, choose "Specify order of tests in suite").&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;strong&gt;Random test execution&lt;/strong&gt;   You can request through the Test Editor that unit tests and test cases within a unit test be executed in random order.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;We have also cleaned up various parts of the user interface, most notably the Preferences Window, which has finally caught up with the rest of the tool (greatly expanded preferences, such as for export/import, as well as removal of old, unused preferences). All preferences are also now stored in their own preferences ini file, so that you can copy it to the workstations of other Code Tester users and easily apply a standard set of preferences to a development team.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;If you have not yet checked out Code Tester, I urge you to do so. There is no better way to build and run regression tests that can finally break out of the vicious cycle of....&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;"I don't have enough time to do it right because I am too busy fixing bugs from the last release."&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;a href="http://unittest.inside.quest.com/downloads.jspa"&gt;Download Quest Code Tester for Oracle v1.9&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;a href=http://www.toadworld.com/Blogs/tabid/67/EntryId/506/Code-Tester-Version-1-9-Now-Available.aspx&gt;More ...&lt;/a&gt;&lt;div class="tags"&gt;Tags: code tester&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/10/Default.aspx&gt;Code Tester for Oracle&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/10/Default.aspx">Code Tester for Oracle</category>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/506/Code-Tester-Version-1-9-Now-Available.aspx#Comments</comments>
      <slash:comments>0</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/506/Code-Tester-Version-1-9-Now-Available.aspx</guid>
      <pubDate>Thu, 18 Feb 2010 14:15:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=506</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/1/Default.aspx">code tester</blog:tag>
    </item>
    <item>
      <title>Retrieving values from a record dynamically</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/501/Retrieving-values-from-a-record-dynamically.aspx</link>
      <description>&lt;p&gt;Steven discusses generic retrieval/change challenges when it comes to PL/SQL records.&lt;/p&gt;&lt;div class="tags"&gt;Tags: plsql&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/501/Retrieving-values-from-a-record-dynamically.aspx#Comments</comments>
      <slash:comments>1</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/501/Retrieving-values-from-a-record-dynamically.aspx</guid>
      <pubDate>Tue, 09 Feb 2010 19:19:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=501</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
    </item>
    <item>
      <title>Binding sparse arrays in a FORALL statement</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/477/Binding-sparse-arrays-in-a-FORALL-statement.aspx</link>
      <description>&lt;p&gt;FORALL was introduced into PL/SQL in Version 8i. It is a &lt;em&gt;fantastic &lt;/em&gt;feature; you should use it in place of all loops that contain DML statements performing row-by-row processing. You will generally see performance improvements of at least an order of magnitude. &lt;/p&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;If you are not familiar with FORALL, make it a priority to &lt;em&gt;get&lt;/em&gt; familiar. You can start with my brand new 5&lt;sup&gt;th&lt;/sup&gt; edition of &lt;a href="http://oreilly.com/catalog/9780596009779/"&gt;Oracle PL/SQL Programming&lt;/a&gt;, complemented by the &lt;a href="http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14261/tuning.htm#sthref2181"&gt;Oracle documentation&lt;/a&gt;. Follow up with a perusal of my &lt;a href="http://toadworld.com/Education/StevenFeuersteinsPLSQLExperience/TrainingandPresentations/PLSQLNewFeatures/tabid/161/Default.aspx#21st%20Century"&gt;21&lt;sup&gt;st&lt;/sup&gt; Century PL/SQL&lt;/a&gt; course materials.&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt; &lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;I assume a working knowledge of FORALL for the remainder of this post.&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt; &lt;/div&gt;
&lt;p style="margin: 0in 0in 0pt"&gt;The typical (and, in Oracle8i and Oracle9i, the &lt;em&gt;only&lt;/em&gt;) way to construct a FORALL statement is to use a header that is very similar to a numeric FOR loop. Here is an example:&lt;/p&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;
&lt;pre&gt;&lt;font color="#0000ff"&gt;DECLARE&lt;br /&gt;   TYPE&lt;/font&gt; namelist_t &lt;font color="#0000ff"&gt;IS TABLE OF&lt;/font&gt; employees.first_name%&lt;font color="#0000ff"&gt;TYPE&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;/font&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;pre style="margin: 0in 0in 0pt"&gt;   l_enames   namelist_t := namelist_t &lt;font color="#0000ff"&gt;(&lt;/font&gt;&lt;font color="#ff0000"&gt;'ABC'&lt;/font&gt;&lt;font color="#0000ff"&gt;,&lt;/font&gt; &lt;font color="#ff0000"&gt;'DEF'&lt;/font&gt;&lt;font color="#0000ff"&gt;,&lt;/font&gt; &lt;font color="#ff0000"&gt;'SMITHIE'&lt;/font&gt;&lt;font color="#0000ff"&gt;);&lt;/font&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;BEGIN&lt;br /&gt;   FORALL&lt;/font&gt; indx &lt;font color="#0000ff"&gt;IN&lt;/font&gt; 1 .. l_enames&lt;font color="#0000ff"&gt;.COUNT&lt;/font&gt;&lt;br /&gt;      &lt;font color="#0000ff"&gt;UPDATE&lt;/font&gt; employees&lt;br /&gt;         &lt;font color="#0000ff"&gt;SET&lt;/font&gt; first_name = l_enames &lt;font color="#0000ff"&gt;(&lt;/font&gt;indx&lt;font color="#0000ff"&gt;);&lt;/font&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;END;&lt;/font&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;More generally, the FORALL header looks like this:&lt;/div&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;
&lt;pre&gt;&lt;font color="#0000ff"&gt;FORALL&lt;/font&gt; &lt;em&gt;integer_index&lt;/em&gt; &lt;font color="#0000ff"&gt;IN&lt;/font&gt; &lt;font color="#800000"&gt;&lt;em&gt;low_value&lt;/em&gt; .. &lt;em&gt;high_value&lt;/em&gt;&lt;/font&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;where integer_index is an implicitly declared integer iterator, low_value is the low end of the integer range and high_value is the high end. Each integer between low and high must reference a defined index value in any of the collections that are bound into the FORALL's DML statement (in the above case, there is just one: l_enames).&lt;/div&gt;
&lt;/blockquote&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;In other words, the binding array must be &lt;em&gt;densely filled&lt;/em&gt; between the low and high values.&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;
&lt;p&gt;If the collection is sparse and the FORALL statement tries to read an element at an undefined element, it will raise an exception as shown below:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" width="534" height="309" src="/Portals/0/blogimages/Steven Feuerstein/SF-Blog112309-1.gif" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;Notice that it does not raise NO_DATA_FOUND. I point this out because it seems like Oracle goes out of its way to raise this exception whenever the error bears even the &lt;em&gt;remotest&lt;/em&gt; resemblance to "I tried to get something and it wasn't there" (SELECT INTO, read an element in a collection at an undefined index value, read past the end of a file).&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt; &lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;Notice also that even if I include the SAVE EXCEPTIONS clause in my FORALL statement, &lt;em&gt;this &lt;/em&gt;exception is &lt;em&gt;not&lt;/em&gt; "saved" to the SQL%BULK_EXCEPTIONS pseudo-collection. That's because this is a "meta-error" for the FORALL statement. The exception is not raised by the SQL engine as it performs the DML statement. It is, instead, raised by the PL/SQL engine &lt;em&gt;before&lt;/em&gt; the SQL statements are passed along to the SQL engine.&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt; &lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;So what's a programmer to do if your binding array is not densely-filled?&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt; &lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;In Oracle10g Release 2, Oracle added support for two new ways to construct the FORALL header:  INDICES OF and VALUES OF. With either of these, your FORALL header no longer looks like a numeric FOR loop. Instead you specify that you want the FORALL statement to reference only those elements in the binding array whose index value is defined in the INDICES OF array.&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt; &lt;/div&gt;
&lt;p style="margin: 0in 0in 0pt"&gt;The simplest form uses the same collection as the binding and INDICES OF arrays, as in:&lt;/p&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;
&lt;pre&gt;   &lt;font color="#0000ff"&gt;FORALL&lt;/font&gt; indx &lt;font color="#0000ff"&gt;IN&lt;/font&gt; INDICES &lt;font color="#0000ff"&gt;OF&lt;/font&gt; l_enames&lt;br /&gt;      &lt;font color="#0000ff"&gt;UPDATE&lt;/font&gt; &lt;font color="#808080"&gt;employees&lt;/font&gt; &lt;font color="#0000ff"&gt;SET&lt;/font&gt; first_name &lt;font color="#0000ff"&gt;=&lt;/font&gt; l_enames &lt;font color="#0000ff"&gt;(&lt;/font&gt;indx&lt;font color="#0000ff"&gt;);&lt;/font&gt; &lt;/pre&gt;
&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;Now, an update statement will be sent to the PL/SQL engine only for this index values that are defined in the collection.&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt; &lt;/div&gt;
&lt;p style="margin: 0in 0in 0pt"&gt;But the collection referenced in the INDICES OF clause need not be the same as the binding array. Here is an example of using INDICES OF with a distinct collection:&lt;/p&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;
&lt;pre&gt;&lt;font color="#0000ff"&gt;DECLARE&lt;br /&gt;   TYPE&lt;/font&gt; employee_aat &lt;font color="#0000ff"&gt;IS TABLE OF&lt;/font&gt; employees.employee_id%&lt;font color="#0000ff"&gt;TYPE&lt;/font&gt;&lt;br /&gt;      &lt;font color="#0000ff"&gt;INDEX BY PLS_INTEGER;&lt;/font&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;pre style="margin: 0in 0in 0pt"&gt;   l_employees          employee_aat;&lt;/pre&gt;
&lt;pre style="margin: 0in 0in 0pt"&gt; &lt;/pre&gt;
&lt;pre style="margin: 0in 0in 0pt"&gt;   &lt;font color="#0000ff"&gt;TYPE&lt;/font&gt; boolean_aat &lt;font color="#0000ff"&gt;IS TABLE OF BOOLEAN&lt;br /&gt;      INDEX BY PLS_INTEGER;&lt;/font&gt;&lt;/pre&gt;
&lt;pre style="margin: 0in 0in 0pt"&gt; &lt;/pre&gt;
&lt;pre style="margin: 0in 0in 0pt"&gt;   l_employee_indices   boolean_aat;&lt;br /&gt;&lt;font color="#0000ff"&gt;BEGIN&lt;/font&gt;&lt;br /&gt;   l_employees &lt;font color="#0000ff"&gt;(&lt;/font&gt;&lt;font color="#800000"&gt;1&lt;/font&gt;&lt;font color="#0000ff"&gt;)&lt;/font&gt; := &lt;font color="#800000"&gt;137&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;/font&gt;&lt;br /&gt;   l_employees &lt;font color="#0000ff"&gt;(&lt;/font&gt;&lt;font color="#800000"&gt;100&lt;/font&gt;&lt;font color="#0000ff"&gt;)&lt;/font&gt; := &lt;font color="#800000"&gt;126&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;br /&gt;&lt;/font&gt;   l_employees &lt;font color="#0000ff"&gt;(&lt;/font&gt;&lt;font color="#800000"&gt;500&lt;/font&gt;&lt;font color="#0000ff"&gt;)&lt;/font&gt; := &lt;font color="#800000"&gt;147&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;br /&gt;&lt;/font&gt;   &lt;br /&gt;   l_employee_indices &lt;font color="#0000ff"&gt;(&lt;/font&gt;&lt;font color="#800000"&gt;1&lt;/font&gt;&lt;font color="#0000ff"&gt;)&lt;/font&gt; &lt;font color="#0000ff"&gt;:= FALSE;&lt;/font&gt;&lt;br /&gt;   l_employee_indices &lt;font color="#0000ff"&gt;(&lt;/font&gt;&lt;font color="#800000"&gt;500&lt;/font&gt;&lt;font color="#0000ff"&gt;)&lt;/font&gt; &lt;font color="#0000ff"&gt;:= TRUE;&lt;/font&gt;&lt;br /&gt;   l_employee_indices &lt;font color="#0000ff"&gt;(&lt;/font&gt;&lt;font color="#800000"&gt;799&lt;/font&gt;&lt;font color="#0000ff"&gt;)&lt;/font&gt; &lt;font color="#0000ff"&gt;:= NULL;&lt;/font&gt;&lt;/pre&gt;
&lt;pre style="margin: 0in 0in 0pt"&gt; &lt;/pre&gt;
&lt;pre style="margin: 0in 0in 0pt"&gt;   &lt;font color="#0000ff"&gt;FORALL&lt;/font&gt; l_index &lt;font color="#0000ff"&gt;IN&lt;/font&gt; INDICES &lt;font color="#0000ff"&gt;OF&lt;/font&gt; l_employee_indices &lt;br /&gt;                  &lt;font color="#0000ff"&gt;BETWEEN&lt;/font&gt; &lt;font color="#800000"&gt;1&lt;/font&gt; &lt;font color="#0000ff"&gt;AND&lt;/font&gt; &lt;font color="#800000"&gt;500&lt;/font&gt;&lt;br /&gt;      &lt;font color="#0000ff"&gt;UPDATE&lt;/font&gt; employees&lt;br /&gt;         &lt;font color="#0000ff"&gt;SET&lt;/font&gt; salary &lt;font color="#0000ff"&gt;=&lt;/font&gt; &lt;font color="#800000"&gt;10000&lt;/font&gt;&lt;br /&gt;       &lt;font color="#0000ff"&gt;WHERE&lt;/font&gt; employee_id &lt;font color="#0000ff"&gt;=&lt;/font&gt; l_employees &lt;font color="#0000ff"&gt;(&lt;/font&gt;l_index&lt;font color="#0000ff"&gt;);&lt;/font&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;END;&lt;/font&gt; &lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p style="margin: 0in 0in 0pt"&gt;Updates will be run only for employee IDs 137 and 147.&lt;/p&gt;
&lt;div style="margin: 0in 0in 0pt"&gt; &lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;The VALUES_OF clause offers an additional layer of "indirection." With VALUES_OF, the FORALL statement executes a DML statement for each index value in the binding array that is an element in (not an index value in) the VALUES OF collection.&lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt; &lt;/div&gt;
&lt;p style="margin: 0in 0in 0pt"&gt;Here is an example:&lt;/p&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;
&lt;pre&gt;&lt;font color="#0000ff"&gt;DECLARE&lt;br /&gt;   TYPE&lt;/font&gt; employee_aat &lt;font color="#0000ff"&gt;IS TABLE OF&lt;/font&gt; employees.employee_id%&lt;font color="#0000ff"&gt;TYPE&lt;br /&gt;      INDEX BY PLS_INTEGER;&lt;/font&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;pre style="margin: 0in 0in 0pt"&gt;   l_employees          employee_aat;&lt;/pre&gt;
&lt;pre style="margin: 0in 0in 0pt"&gt; &lt;/pre&gt;
&lt;pre style="margin: 0in 0in 0pt"&gt;   &lt;font color="#0000ff"&gt;TYPE&lt;/font&gt; indices_aat &lt;font color="#0000ff"&gt;IS TABLE OF PLS_INTEGER&lt;br /&gt;      INDEX BY PLS_INTEGER;&lt;/font&gt;&lt;/pre&gt;
&lt;pre style="margin: 0in 0in 0pt"&gt; &lt;/pre&gt;
&lt;pre style="margin: 0in 0in 0pt"&gt;   l_employee_indices   indices_aat;&lt;br /&gt;&lt;font color="#0000ff"&gt;BEGIN&lt;/font&gt;&lt;br /&gt;   l_employees &lt;font color="#0000ff"&gt;(&lt;/font&gt;&lt;font color="#800000"&gt;-77&lt;/font&gt;&lt;font color="#0000ff"&gt;) :=&lt;/font&gt; &lt;font color="#800000"&gt;134&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;br /&gt;&lt;/font&gt;   l_employees &lt;font color="#0000ff"&gt;(&lt;/font&gt;&lt;font color="#800000"&gt;13067&lt;/font&gt;&lt;font color="#0000ff"&gt;) :=&lt;/font&gt; &lt;font color="#800000"&gt;123&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;br /&gt;&lt;/font&gt;   l_employees &lt;font color="#0000ff"&gt;(&lt;/font&gt;&lt;font color="#800000"&gt;99999999&lt;/font&gt;&lt;font color="#0000ff"&gt;) :=&lt;/font&gt; &lt;font color="#800000"&gt;147&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;/font&gt;&lt;br /&gt;   l_employees &lt;font color="#0000ff"&gt;(&lt;/font&gt;&lt;font color="#800000"&gt;1070&lt;/font&gt;&lt;font color="#0000ff"&gt;) :=&lt;/font&gt; &lt;font color="#800000"&gt;429&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;br /&gt;&lt;/font&gt;   &lt;br /&gt;   l_employee_indices &lt;font color="#0000ff"&gt;(&lt;/font&gt;&lt;font color="#800000"&gt;100&lt;/font&gt;&lt;font color="#0000ff"&gt;) :=&lt;/font&gt; &lt;font color="#800000"&gt;-77&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;br /&gt;&lt;/font&gt;   l_employee_indices &lt;font color="#0000ff"&gt;(&lt;/font&gt;&lt;font color="#800000"&gt;200&lt;/font&gt;&lt;font color="#0000ff"&gt;) :=&lt;/font&gt; &lt;font color="#800000"&gt;13067&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;/font&gt;&lt;br /&gt;   l_employee_indices &lt;font color="#0000ff"&gt;(&lt;/font&gt;&lt;font color="#800000"&gt;300&lt;/font&gt;&lt;font color="#0000ff"&gt;) :=&lt;/font&gt; &lt;font color="#800000"&gt;1070&lt;/font&gt;&lt;font color="#0000ff"&gt;;&lt;/font&gt;&lt;br /&gt;   &lt;br /&gt;   &lt;font color="#0000ff"&gt;FORALL&lt;/font&gt; l_index &lt;font color="#0000ff"&gt;IN VALUES&lt;/font&gt; OF l_employee_indices&lt;br /&gt;      &lt;font color="#0000ff"&gt;UPDATE&lt;/font&gt; employees&lt;br /&gt;         &lt;font color="#0000ff"&gt;SET&lt;/font&gt; salary &lt;font color="#0000ff"&gt;=&lt;/font&gt; &lt;font color="#800000"&gt;10000&lt;/font&gt;&lt;br /&gt;       &lt;font color="#0000ff"&gt;WHERE&lt;/font&gt; employee_id &lt;font color="#0000ff"&gt;=&lt;/font&gt; l_employees &lt;font color="#0000ff"&gt;(&lt;/font&gt;l_index&lt;font color="#0000ff"&gt;);&lt;/font&gt;&lt;br /&gt;   &lt;em&gt;DBMS_OUTPUT.put_line&lt;/em&gt; &lt;font color="#0000ff"&gt;(SQL&lt;/font&gt;%&lt;font color="#0000ff"&gt;ROWCOUNT);&lt;/font&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;END;&lt;/font&gt; &lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p style="margin: 0in 0in 0pt"&gt;In this block of code, an UPDATE is executed for employee IDs134, 123 and 429.&lt;/p&gt;
&lt;div style="margin: 0in 0in 0pt"&gt; &lt;/div&gt;
&lt;div style="margin: 0in 0in 0pt"&gt;So if you are using FORALL but running into situations where your binding array may not be sequentially filled, give INDICES OF or VALUES_OF a try. It might simplify your life and code dramatically.&lt;/div&gt;&lt;br /&gt;&lt;a href=http://www.toadworld.com/Blogs/tabid/67/EntryId/477/Binding-sparse-arrays-in-a-FORALL-statement.aspx&gt;More ...&lt;/a&gt;&lt;div class="tags"&gt;Tags: plsql,oracle,forall&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/477/Binding-sparse-arrays-in-a-FORALL-statement.aspx#Comments</comments>
      <slash:comments>0</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/477/Binding-sparse-arrays-in-a-FORALL-statement.aspx</guid>
      <pubDate>Mon, 23 Nov 2009 15:44:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=477</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/2/Default.aspx">oracle</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/130/Default.aspx">forall</blog:tag>
    </item>
    <item>
      <title>The Subtleties of Programming </title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/474/The-Subtleties-of-Programming.aspx</link>
      <description>&lt;div&gt;I recently published the following puzzle in the ToadWorld newsletter:&lt;/div&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;strong&gt;&lt;font size="2" face="arial"&gt;Which of the following queries return the names of programs (without duplication) defined in the currently connected schema whose source contains a call to DBMS_OUTPUT.PUT_LINE (assume that this program name does not appear inside comments)?&lt;/font&gt; &lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;strong&gt;A.&lt;/strong&gt;   &lt;font face="Courier New"&gt;SELECT name FROM USER_DEPENDENCIES&lt;br /&gt;
    WHERE referenced_name = 'DBMS_OUTPUT.PUT_LINE'&lt;br /&gt;
&lt;/font&gt;&lt;br /&gt;
&lt;strong&gt;B.   &lt;/strong&gt;&lt;font face="Courier New"&gt;SELECT name from ALL_SOURCE&lt;br /&gt;
    WHERE owner = USER&lt;br /&gt;
      AND name = 'DBMS_OUTPUT.PUT_LINE'&lt;br /&gt;
&lt;/font&gt;&lt;br /&gt;
&lt;strong&gt;C.&lt;/strong&gt;   &lt;font face="Courier New"&gt;SELECT DISTINCT name from ALL_SOURCE&lt;br /&gt;
 &lt;/font&gt;&lt;span&gt;&lt;font face="Courier New"&gt;   WHERE INSTR (text, 'DBMS_OUTPUT.PUT_LINE') &gt; 0 &lt;br /&gt;
&lt;/font&gt;&lt;br /&gt;
&lt;strong&gt;D.&lt;/strong&gt;   &lt;font face="Courier New"&gt;SELECT DISTINCT name from USER_SOURCE&lt;br /&gt;
    WHERE INSTR (UPPER (text), 'DBMS_OUTPUT.PUT_LINE') &gt; 0&lt;/font&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/blockquote&gt;
&lt;div&gt;I believed that (D) was correct. Certainly, A, B and C do not do the trick (click &lt;u&gt;&lt;a href="http://www.toadworld.com/LinkClick.aspx?link=396&amp;tabid=67"&gt;here&lt;/a&gt;&lt;/u&gt; to see my explanation). But I recently received the following email from Wim de Lange of the Netherlands:&lt;/div&gt;
&lt;blockquote style="margin-right: 0px" dir="ltr"&gt;
&lt;div&gt;"None of the answers below is correct. (D) &lt;em&gt;could&lt;/em&gt; be the solution, but DBMS_OUTPUT.PUT_LINE could be spelled as DBMS_OUTPUT . PUT_LINE (spaces around the dot) and that code will still compile and run. So the spaces are destroying the solution here."&lt;/div&gt;
&lt;/blockquote&gt;
&lt;div&gt;Wim is absolutely correct. You could put spaces between the package name, dot and subprogram name, and the PL/SQL compiler will have no trouble with that code.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Thanks, Wim, for your very close reading of my puzzle, and for reminding me that programming can be a very subtle and nuanced craft. Oh, and also that it is so difficult to come up with all the test cases for a program.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;And just to show you that I am not the least bit upset about someone finding an error in my code and writing, Wim is hereby declared &lt;em&gt;another&lt;/em&gt; winner of that contest and will receive a Toad World t-shirt in addition to the randomly selected four winners.&lt;/div&gt;&lt;br /&gt;&lt;a href=http://www.toadworld.com/Blogs/tabid/67/EntryId/474/The-Subtleties-of-Programming.aspx&gt;More ...&lt;/a&gt;&lt;div class="tags"&gt;Tags: plsql,oracle&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/474/The-Subtleties-of-Programming.aspx#Comments</comments>
      <slash:comments>3</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/474/The-Subtleties-of-Programming.aspx</guid>
      <pubDate>Mon, 16 Nov 2009 15:54:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=474</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/2/Default.aspx">oracle</blog:tag>
    </item>
    <item>
      <title>The Most Important Language to Learn</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/468/The-Most-Important-Language-to-Learn.aspx</link>
      <description>&lt;p&gt;I was recently in Germany, and did an interview with Erik Franz of database|pro. One of the questions he asked me was: "Which programming language would you recommend a college student learn to give them the strongest chance at a good job upon graduation?" I would have loved to be able to answer: "Learn PL/SQL!&lt;/p&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/468/The-Most-Important-Language-to-Learn.aspx#Comments</comments>
      <slash:comments>0</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/468/The-Most-Important-Language-to-Learn.aspx</guid>
      <pubDate>Mon, 02 Nov 2009 13:54:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=468</trackback:ping>
    </item>
    <item>
      <title>An Amazing Visit to Mexico City</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/463/An-Amazing-Visit-to-Mexico-City.aspx</link>
      <description>&lt;div&gt;As I write this, I am flying back to Chicago now, 9 PM Oct 21, from Mexico City, after a very nice two day visit.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Quest Mexico asked me to come down to help celebrate the release of &lt;a href="http://www.toadworld.com/LandingPages/ToadforOracleVersion10/tabid/622/Default.aspx"&gt;&lt;font color="#800080"&gt;Toad Version 10&lt;/font&gt;&lt;/a&gt;. I said "OK."&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;And, wow, they did a really fantastic job of making me feel appreciated. Besides putting me up in a fabulous, old but very excellent hotel, &lt;a href="http://www.caminoreal.com/mexico_i/main.php"&gt;El Camino Real Polenco&lt;/a&gt;, and making sure I enjoyed outstanding meals of (surprise) Mexican cuisine, they pulled together an enormous gathering of over 250 Oracle technologists for an evening presentation at the beautiful &lt;a href="http://www.haciendadelosmorales.com/index.php"&gt;http://www.haciendadelosmorales.com/index.php&lt;/a&gt; by Claudia Fernandez, Quest product manager supreme, to talk about Toad 10, and me to talk about, well, pretty much whatever I felt like talking about, which turned out to be the function result cache feature of Oracle11g.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Quest Mexico also ordered 100 of my Oracle PL/SQL Best Practices books to give away to the first 100 people who arrived on the 20th. That turned out to be a fine motivator. Developers started arriving at 2 PM or so for a 5 PM start time. Unfortunately, due to problems with Customs in Mexico, we didn't have those orange books. Fortunately, we had a nice big pile of a book that Claudia co-authored, &lt;a href="http://www.rampant-books.com/book_0701_database_benchmarking.htm"&gt;Database Benchmarking&lt;/a&gt;. So attendees received those. And then they lined up for autographs. As I signed books, I got to meet a lot of very enthusiastic PL/SQL developers - several of which said that they benefited greatly from my writing. How satisfying!&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;On the wall behind our signing table was a banner with a reproduction of my head that must have been five feet high. I kid you not - in fact, you can see it &lt;a href="http://www.flickr.com/photos/stevenfeuerstein/4035323125/in/set-72157622517976999/"&gt;&lt;font color="#800080"&gt;here&lt;/font&gt;&lt;/a&gt;. Fortunately, I am a humble fellow, so I only posed in front of the banner for a few photos.&lt;/div&gt;
&lt;div&gt;Many attendees also asked to have their photo taken with me. And Ricardo of Quest was kind enough to use my camera to also capture those moments. You can view all those photos &lt;a href="http://www.flickr.com/photos/stevenfeuerstein/sets/72157622517976999/"&gt;here&lt;/a&gt;.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;I must tell you that years ago, when people first asked for autographs, asked to have their picture taken with me, I was a little bit embarrassed by the whole situation. C'mon, I just wrote a few (well, 10) books about this one language, PL/SQL. Why are they getting so excited? They are being weird, ridiculous. But I eventually came to realize that it really doesn't matter what I think. What matters is that for whatever reason (I have some idea of why this happened, but it is still a bit of a mystery to me) my books, my writings, my trainings have had a substantial impact on the lives of these developers. My ideas and my ways of expressing them have improved their lives.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Now, that realization is/was a continually humbling experience. Now, I am honored that anyone would care to have me sign their book or share a photo with them. And I have decided to start celebrating this honor and, at least this is my intention, honor my readers by &lt;a href="http://www.flickr.com/photos/stevenfeuerstein/sets/72157622517976999/"&gt;posting on Flickr&lt;/a&gt; the photos we took together (and others from the event in La Hacienda Morales in Mexico City).&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;strong&gt;If anyone sees their photo on this page and does not want it to be available publicly, please &lt;/strong&gt;&lt;a href="http://www.toadworld.commailto:steven.feuerstein@quest.com"&gt;&lt;strong&gt;let me know immediately&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt; and I will remove it. My apologies in advance for any liberties taken.&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Many thanks to Diana, Belen, Daniel, Pablo, Ricardo and others at Quest Mexico for organizing a fantastic set of events (beyond just the public program), media interviews and overall stay. I look forward to a triumphant return, or perhaps a visit to Monterey.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Once again, I find myself marveling at my good fortune and the fine life I have. I only wish I was able to spend time with all my PL/SQL friends around the world and not be away from wife, Veva, and my boys. That is a substantial price to pay. Sigh....&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Finally, I very much enjoyed having an opportunity to resurrect my rusty (not) command of the Spanish language. I am not sure whether it is a blessing or a curse, but they tell me that I am able to pronounce words in Spanish very well (roll those r's, put the accent on the correct syllable, etc.). This leads native speakers to believe that I can speak and understand much more than I actually can. So I start out strong, but immediately stumble over a serious lack of vocabulary, and very poor comprehension (I can talk better than I can understand - big surprise, I spend so much of my life talking at others).&lt;/div&gt;&lt;br /&gt;&lt;a href=http://www.toadworld.com/Blogs/tabid/67/EntryId/463/An-Amazing-Visit-to-Mexico-City.aspx&gt;More ...&lt;/a&gt;</description>
      <author>Steven Feuerstein</author>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/463/An-Amazing-Visit-to-Mexico-City.aspx#Comments</comments>
      <slash:comments>0</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/463/An-Amazing-Visit-to-Mexico-City.aspx</guid>
      <pubDate>Fri, 23 Oct 2009 12:38:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=463</trackback:ping>
    </item>
    <item>
      <title>Resolving an LTRIM mystery</title>
      <link>http://www.toadworld.com/Blogs/tabid/67/EntryId/461/Resolving-an-LTRIM-mystery.aspx</link>
      <description>&lt;p&gt;Steven discusses how LTRIM works and an alternative solution for a user's problem.&lt;/p&gt;&lt;div class="tags"&gt;Tags: plsql,oracle,ltrim&lt;/div&gt;&lt;div class="category"&gt;Category: &lt;a href=http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx&gt;PL/SQL Obsession&lt;/a&gt;&lt;/div&gt;</description>
      <author>Steven Feuerstein</author>
      <category domain="http://www.toadworld.com/Blogs/tabid/67/CatID/15/Default.aspx">PL/SQL Obsession</category>
      <comments>http://www.toadworld.com/Blogs/tabid/67/EntryId/461/Resolving-an-LTRIM-mystery.aspx#Comments</comments>
      <slash:comments>3</slash:comments>
      <guid isPermaLink="true">http://www.toadworld.com/Blogs/tabid/67/EntryId/461/Resolving-an-LTRIM-mystery.aspx</guid>
      <pubDate>Thu, 15 Oct 2009 13:42:00 GMT</pubDate>
      <trackback:ping>http://www.toadworld.comDesktopModules/BlogTrackback.aspx?id=461</trackback:ping>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/5/Default.aspx">plsql</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/2/Default.aspx">oracle</blog:tag>
      <blog:tag blog:url="http://www.toadworld.com/Blogs/tabid/67/TagID/150/Default.aspx">ltrim</blog:tag>
    </item>
  </channel>
</rss>
