<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss'><id>tag:blogger.com,1999:blog-15861274</id><updated>2009-12-02T20:43:47.047Z</updated><title type='text'>Oracle WTF</title><subtitle type='html'>Living the dream</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://oracle-wtf.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default?start-index=26&amp;max-results=25'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>89</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-15861274.post-8582046489776760636</id><published>2009-11-29T13:44:00.000Z</published><updated>2009-11-29T13:44:13.179Z</updated><title type='text'>The £10 UKOUG Weak Joke Challenge</title><content type='html'>&lt;p&gt;Oracle-WTF will pay the sum of £10 to the first person who makes the following weak Brummie joke to a conference audience at UKOUG:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Are there any Brummies here today?&lt;/p&gt;
&lt;p&gt;Is it true that Ozzy Osbourne thought the Spice Girls were astronauts?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;i&gt;(Note for visitors to England: it's about the accent. And The Spice Girls used to be a pop group. And Ozzy Osbourne, oh never mind.)&lt;/i&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-8582046489776760636?l=oracle-wtf.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-wtf.blogspot.com/feeds/8582046489776760636/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=15861274&amp;postID=8582046489776760636' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/8582046489776760636'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/8582046489776760636'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2009/11/10-ukoug-weak-joke-challenge.html' title='The £10 UKOUG Weak Joke Challenge'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15419749305409395293'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-8893380144201761490</id><published>2009-10-31T15:21:00.003Z</published><updated>2009-10-31T15:32:49.462Z</updated><title type='text'>Now where are those user accounts?</title><content type='html'>&lt;p&gt;The IM conversation below is part of a much longer one (notice the date stamps) between a friend who we'll just call 'TR' and a developer.&lt;/p&gt;
&lt;blockquote&gt;
&lt;i&gt;&lt;b&gt;Developer (11 Oct 2009 14:39:51):&lt;/b&gt; I created some users and now they are gone?&lt;/i&gt;&lt;br /&gt;
&lt;b&gt;TR (11 Oct 2009 14:40:01):&lt;/b&gt; We have implemented a daily flashback to the data baseline so that repeatable tests can run every day in that database.&lt;br /&gt;
&lt;b&gt;TR (11 Oct 2009 14:40:03):&lt;/b&gt; You need to notify us (as per the mail I sent out) when you make data changes that you want to keep from day to day.&lt;br /&gt;
&lt;b&gt;TR (11 Oct 2009 14:40:06):&lt;/b&gt; Ok, so could you please create those users again and let me know? I'll create a new baseline for the refresh....&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (11 Oct 2009 14:45:51):&lt;/b&gt; i wonder if i ll be able this afternoon&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (11 Oct 2009 14:46:12):&lt;/b&gt; so i can do it tomorrow and send you the list&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (11 Oct 2009 14:46:25):&lt;/b&gt; You can go ahead wit the refreh of today without my users&lt;/i&gt;&lt;br /&gt;
&lt;b&gt;TR (11 Oct 2009 14:48:29):&lt;/b&gt; Ok, I don't need the list, just to know once you have created them.&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (11 Oct 2009 14:50:18):&lt;/b&gt; ok &lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (20 Oct 2009 16:57:53):&lt;/b&gt; hi TR&lt;/i&gt;&lt;br /&gt;
&lt;b&gt;TR (20 Oct 2009 16:57:59):&lt;/b&gt; Hi&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (20 Oct 2009 16:58:06):&lt;/b&gt; Are you still doing the DB refresh on daily basis?&lt;/i&gt;&lt;br /&gt;
&lt;b&gt;TR (20 Oct 2009 16:58:20):&lt;/b&gt; Yes. It's automatic, I don't actually *do* anything.&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (20 Oct 2009 16:58:24):&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (20 Oct 2009 16:58:27):&lt;/b&gt; ok&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (20 Oct 2009 16:58:33):&lt;/b&gt; then&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (20 Oct 2009 16:59:22):&lt;/b&gt; i see&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (20 Oct 2009 17:01:42):&lt;/b&gt; actually i m looking for this user on alpha qa2_PN3D8J20aa&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (20 Oct 2009 17:01:52):&lt;/b&gt; i can't find it in the db&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (20 Oct 2009 17:02:04):&lt;/b&gt; and when i m logged in with it, I added it yesterday and now it's gone&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (20 Oct 2009 17:03:02):&lt;/b&gt; i ll try using other users&lt;/i&gt;&lt;br /&gt;
&lt;b&gt;TR (20 Oct 2009 17:16:21):&lt;/b&gt; You didn't tell me that you had created these users. The database is refreshed every night back to the baseline...as we discussed&lt;br /&gt;
&lt;b&gt;TR (20 Oct 2009 17:16:21):&lt;/b&gt; If you add data you have to let me know and I will create a new baseline.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;TR (21 Oct 2009 16:08:49):&lt;/b&gt; These users that you need. Are they in the database now?&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (21 Oct 2009 16:09:02):&lt;/b&gt; not yet&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (21 Oct 2009 16:09:07):&lt;/b&gt; but i can ping them to you&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (21 Oct 2009 16:09:12):&lt;/b&gt; at least the login&lt;/i&gt;&lt;br /&gt;
&lt;b&gt;TR (21 Oct 2009 16:09:19):&lt;/b&gt; You don't need to ping them to me. Just tell me when they're created&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (21 Oct 2009 16:09:25):&lt;/b&gt; ok&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (21 Oct 2009 16:09:52):&lt;/b&gt; but got too much to do today probably will have them ready monday morning&lt;/i&gt;&lt;br /&gt;
&lt;b&gt;TR (21 Oct 2009 16:10:20):&lt;/b&gt; Ok, so as per last time....when they are created please let me know.&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (21 Oct 2009 16:10:30):&lt;/b&gt; ok&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (25 Oct 2009 13:18:21):&lt;/b&gt; hi TR&lt;/i&gt;&lt;br /&gt;
&lt;b&gt;TR (25 Oct 2009 13:18:27):&lt;/b&gt; Hi&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (25 Oct 2009 13:18:31):&lt;/b&gt; what's time is the DB refresh taking time ?&lt;/i&gt;&lt;br /&gt;
&lt;b&gt;TR (25 Oct 2009 13:18:41):&lt;/b&gt; 00:00GMT&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (25 Oct 2009 13:18:44):&lt;/b&gt; ok&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (25 Oct 2009 13:18:52):&lt;/b&gt; i ll ping you by the end of the day my new users&lt;/i&gt;&lt;br /&gt;
&lt;b&gt;TR (25 Oct 2009 13:18:57):&lt;/b&gt; Ok, you don't need to ping me the users, just create them and tell me when you have done it&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (25 Oct 2009 13:19:01):&lt;/b&gt; in the mean time&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (25 Oct 2009 13:19:25):&lt;/b&gt; I'm working on a script to insert our users in the Db before each time&lt;/i&gt;&lt;br /&gt;
&lt;b&gt;TR (25 Oct 2009 13:19:39):&lt;/b&gt; Ok, you don't need to do that, just create them and tell me when you've done it.&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (25 Oct 2009 13:19:48):&lt;/b&gt; so this will help us lot and you will be free to do your updates as you want and delete our users if you need to&lt;/i&gt;&lt;br /&gt;
&lt;b&gt;TR (25 Oct 2009 13:20:02):&lt;/b&gt; Ok great. But the process is already working, you just have to tell me once you've created them and they will always be there&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (25 Oct 2009 15:00:26):&lt;/b&gt; hi TR&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (25 Oct 2009 15:00:34):&lt;/b&gt; what do i have to give you about the created users? only login&lt;/i&gt;&lt;br /&gt;
&lt;b&gt;TR (25 Oct 2009 15:00:43):&lt;/b&gt; nothing, just tell me when you've create them.&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (25 Oct 2009 15:00:48):&lt;/b&gt; or Zid, Xid...&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (25 Oct 2009 15:00:54):&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;
&lt;b&gt;TR (25 Oct 2009 15:00:54):&lt;/b&gt; just tell me WHEN they are created...so I can add them to the baseline.&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (25 Oct 2009 15:01:04):&lt;/b&gt; today&lt;/i&gt;&lt;br /&gt;
&lt;b&gt;TR (25 Oct 2009 15:01:17):&lt;/b&gt; they are there now?&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (25 Oct 2009 15:01:21):&lt;/b&gt; not yet, but I will create these users&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (25 Oct 2009 15:02:07):&lt;/b&gt; ppm_alpha_4 ppm_alpha_5&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (25 Oct 2009 15:02:21):&lt;/b&gt; ppm_alpha_2 ppm_alpha_3 ppm_alpha_4 ppm_alpha_5&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Developer (25 Oct 2009 15:02:21):&lt;/b&gt; please don't delete them this time&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-8893380144201761490?l=oracle-wtf.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-wtf.blogspot.com/feeds/8893380144201761490/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=15861274&amp;postID=8893380144201761490' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/8893380144201761490'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/8893380144201761490'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2009/10/now-where-are-those-user-accounts.html' title='Now where are those user accounts?'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15419749305409395293'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-9046417030658760478</id><published>2009-09-02T11:57:00.002+01:00</published><updated>2009-09-02T12:02:21.674+01:00</updated><title type='text'>If at first you don't succeed...</title><content type='html'>&lt;p&gt;...then try again. Then try again more 125 times. Then quit.&lt;/p&gt;
&lt;pre&gt;PROCEDURE get_id
    ( p_id_out         OUT NUMBER
    , p_name_in        IN VARCHAR2
    , p_create_user_in IN VARCHAR2 )
IS
    v_new_id      NUMBER := 0;
    v_max_tries   PLS_INTEGER := 127;
    v_default_id  NUMBER := 0;
BEGIN
    v_new_id := lookup_id(p_name_in); -- will be 0 if not found

    WHILE v_new_id = 0 AND v_max_tries &gt; 0
    LOOP
        BEGIN
            INSERT INTO entry
            ( entry_id
            , entry_name
            , create_date
            , create_user
            , create_app
            , mod_date
            , mod_user
            , mod_app)
            VALUES
            ( entry_seq.NEXTVAL
            , p_name_in
            , SYSDATE
            , p_create_user_in
            , 'get_id'
            , SYSDATE
            , p_create_user_in
            , 'get_id' )
            RETURNING entry_id INTO v_new_id;

        EXCEPTION
            WHEN OTHERS THEN NULL;
        END;
    
        v_max_tries := v_max_tries - 1;
    END LOOP;

    p_id_out := v_new_id;
END get_id;&lt;/pre&gt;
&lt;p&gt;Thanks BB for sending this.&lt;/tt&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-9046417030658760478?l=oracle-wtf.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-wtf.blogspot.com/feeds/9046417030658760478/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=15861274&amp;postID=9046417030658760478' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/9046417030658760478'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/9046417030658760478'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2009/09/if-at-first-you-dont-succeed.html' title='If at first you don&apos;t succeed...'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15419749305409395293'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-6684392869768607105</id><published>2009-05-03T12:32:00.001+01:00</published><updated>2009-05-03T12:32:55.870+01:00</updated><title type='text'>The Undocumented "/1000" currency formatting function</title><content type='html'>&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=890147"&gt;Forum question&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Hi,&lt;/p&gt;&lt;p&gt;How can I format currency values to shorthand?&lt;/p&gt;&lt;p&gt;i.e. how can I display 12500 as 12.5, 2700 as 2.7, 700 as 0.7 etc?&lt;/p&gt;&lt;p&gt;I have tried using various masks but can't achieve the results I'm looking for.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;That's a tough one. How to make 700 into 0.7? Could there be some Oracle feature to help with this?&lt;/p&gt;&lt;p&gt;Two quick replies later:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Thanks for the replies guys&lt;/p&gt;&lt;p&gt;I wasnt aware of the "/1000" feature, but it has done exactly what I need.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Oracle needs to do more to promote these display format features. What else are they hiding? That's what we want to know.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-6684392869768607105?l=oracle-wtf.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-wtf.blogspot.com/feeds/6684392869768607105/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=15861274&amp;postID=6684392869768607105' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/6684392869768607105'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/6684392869768607105'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2009/05/undocumented-1000-currency-formatting.html' title='The Undocumented &quot;/1000&quot; currency formatting function'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15419749305409395293'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-7526221537717579389</id><published>2009-04-10T08:31:00.001+01:00</published><updated>2009-04-10T08:32:34.418+01:00</updated><title type='text'>How to talk your way out of a hole</title><content type='html'>&lt;p&gt;One last shot from our favourite &lt;a href="http://oracle-wtf.blogspot.com/2009/03/consultant-on-backups.html"&gt;consultant&lt;/a&gt;:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Be careful what you expect from this proof of concept. We can’t prove the performance will match the requirements, and I would argue that performance isn’t a function of this architecture, it’s a function of technology.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;The issue is not the architecture, it’s that [this company] doesn’t have the technology. I would even argue that the technology required might not exist yet.&lt;p&gt;&lt;/p&gt;&lt;p&gt;We can say that indicatively if the technology did exist, then this architecture would hit that performance requirement.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Let's hear it for &lt;a href="http://www.joelonsoftware.com/items/2008/05/01.html"&gt;architecture astronauts&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-7526221537717579389?l=oracle-wtf.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-wtf.blogspot.com/feeds/7526221537717579389/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=15861274&amp;postID=7526221537717579389' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/7526221537717579389'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/7526221537717579389'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2009/04/how-to-talk-your-way-out-of-hole.html' title='How to talk your way out of a hole'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15419749305409395293'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-7945167208236007944</id><published>2009-03-20T07:57:00.004Z</published><updated>2009-03-20T08:03:11.732Z</updated><title type='text'>Rollback segments explained</title><content type='html'>&lt;p&gt;I recently read this in a book about data warehousing:&lt;/p&gt;&lt;blockquote&gt;&lt;h3 style="margin-top: 0.5em;margin-bottom: 1em;"&gt;Source System Rollback Segments&lt;/h3&gt;When extracting from a relational source, extracts that take a long time can be problematic. If an extract asks for all records updated in the last 24 hours, the system must locate the appropriate set of records. This means that no user can change the updated_date field while your query is being processed. As transactions flow in during your query, they are queued up in a separate place called a rollback segment, to be applied once your request is finished. If your query takes too long, this queue gets too large and runs out of space. The system then kills your job and processes the transactions that have been queued up. In general, the folks responsible for the transaction system don't like this kind of behavior.&lt;/blockquote&gt;&lt;p&gt;Now to be fair, the book was published in 1998 and is not specifically about Oracle. Does anyone know whether there has ever been a commercial DBMS that worked anything like this, or did they just make it up?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-7945167208236007944?l=oracle-wtf.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-wtf.blogspot.com/feeds/7945167208236007944/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=15861274&amp;postID=7945167208236007944' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/7945167208236007944'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/7945167208236007944'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2009/03/rollback-segments-explained.html' title='Rollback segments explained'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15419749305409395293'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-8876133168218652012</id><published>2009-03-14T17:30:00.001Z</published><updated>2009-03-14T17:32:26.872Z</updated><title type='text'>The Consultant on Backups</title><content type='html'>&lt;p&gt;Our correspondent overheard &lt;a href="http://oracle-wtf.blogspot.com/2009/02/consultant.html"&gt;The Consultant&lt;/a&gt; sorting out the backup requirements for the new system:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;b&gt;Consultant:&lt;/b&gt; You have a 6 hour window overnight, now as the queues get longer under heavy loading the end of day queue clearing will run into that 6 hours. Your backup window will start to get squeezed, so we need to know the minimum time to back-up this amount of data, including the time to shut down and start up the databases.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Technical guy:&lt;/b&gt; Why?&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Consultant:&lt;/b&gt; Because it has to take place in that 6 hour window.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Technical guy:&lt;/b&gt; Why is that?&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Consultant:&lt;/b&gt; Because then the users will come back on line and want to use the system.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Technical guy:&lt;/b&gt; So?&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Consultant: &lt;/b&gt;They can't use the system if it's down to be backed up.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Technical guy: &lt;/b&gt;We'll use an online backup and they can do whatever they like.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Consultant:&lt;/b&gt; Well, if I was in auditing I'd fire you right now. You simply have to shut a database down to back it up. It's the only way you can get a consistent backup.&lt;/p&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-8876133168218652012?l=oracle-wtf.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-wtf.blogspot.com/feeds/8876133168218652012/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=15861274&amp;postID=8876133168218652012' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/8876133168218652012'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/8876133168218652012'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2009/03/consultant-on-backups.html' title='The Consultant on Backups'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15419749305409395293'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-8844457069260996002</id><published>2009-02-17T07:22:00.003Z</published><updated>2009-05-03T19:02:22.510+01:00</updated><title type='text'>The Consultant</title><content type='html'>&lt;p&gt;The Consultant has a Ph. D, vast experience of high-performance systems architecture, a black belt in karate and a reputation as a genius. He's been brought in by senior management at vast but necessary expense for a strategic rethink of the way data is shared between systems, while implementing SOA, improving performance and finding the Higgs Boson. Needless to say, he tends towards the view that database development is overrated. He's already sorted out the data warehouse. Overheard by our correspondent:
&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;I’ve finished the design for the data warehouse. Although I say design, it’s pretty simple. That’s why it was so quick. All data warehouses are essentially the same in that they are a dimensional model. That means that you essentially have everything that is a fact, an immutable fact [waves arms expressively], in the fact table. Just the one, big, table. That’s why they’re so attractive as reporting solutions - everything is in the same place so it’s easy to understand and the reporting is easy to automate. So in that fact table you’ve got all trades, the cashflows, positions, accounting information, accounts, exceptions, counterparties. Anything that’s a fact goes in that table [does wide googly eyes expression with dramatic pause]. Then anything derived is called a dimension, like for instance P&amp;amp;L calculations, whether the account is on balance sheet, or off... they go in the dimension table.  Basically all we have to do is just pump messages into that fact table from the bus and then recalculate the dimensions in the dimension table periodically, and that’s the technical job. Getting the facts in there and getting the calculations done.&lt;/p&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-8844457069260996002?l=oracle-wtf.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-wtf.blogspot.com/feeds/8844457069260996002/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=15861274&amp;postID=8844457069260996002' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/8844457069260996002'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/8844457069260996002'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2009/02/consultant.html' title='The Consultant'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15419749305409395293'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-7219476775729158465</id><published>2008-11-01T07:43:00.008Z</published><updated>2008-11-03T08:33:06.049Z</updated><title type='text'>More Fake Performance Tips</title><content type='html'>&lt;p&gt;We're not sure if this is a joke or just (more likely) the work of an idiot. Here are &lt;a href="http://latest360.blogspot.com/2008/04/tips-for-better-performance-and-tuning.html" ref="nofollow"&gt;15 Tips for better performance and tuning in Oracle SQL and PL/SQL&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;&lt;ol&gt;
&lt;li&gt;FTS (Full Table Scans) are always bad and Index usage is always good.&lt;/li&gt;
&lt;li&gt;Usage of dynamic SQL within the stored procedure code is always bad even for search procedures.&lt;/li&gt;
&lt;li&gt;Empty Space in an index that gets created due to the DML operations do not get used.&lt;/li&gt;
&lt;li&gt;Indexes should be rebuilt at regular intervals.&lt;/li&gt;
&lt;li&gt;Indexes and statistics are the same thing. Also, histograms are needed only on indexed columns.&lt;/li&gt;
&lt;li&gt;Usage of cursors is always bad so avoid them like the plague.&lt;/li&gt;
&lt;li&gt;Truncate command cannot be rolled back because it is a non-logged operation.&lt;/li&gt;
&lt;li&gt;Table variables in SQL Server are always only memory resident.&lt;/li&gt;
&lt;li&gt;Column order in a covered index does not matter.&lt;/li&gt;
&lt;li&gt;In the case of SQL Server, one can separate the clustered index from the table.&lt;/li&gt;
&lt;li&gt;Only committed data gets written to the disk.&lt;/li&gt;
&lt;li&gt;Logical I/Os (LIO) are not a cause of concern, only Physical IO (PIO) are.&lt;/li&gt;
&lt;li&gt;Count(1) is better performing than count(*).&lt;/li&gt;
&lt;li&gt;Issue frequent commits in the application to make the transaction faster and also improve concurrency.&lt;/li&gt;
&lt;li&gt;Views are evil evil DB Objects that always slow down performance. &lt;/li&gt;&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;We like the fact that 8, 9 and 10 appear to be about SQL Server, despite the heading. Probably Nawal could only think of 12 fake Oracle tips but thought nobody would notice. Can you help him out with some more misleading tips for Oracle? (Or SQL Server. Nobody will notice.) For example,&lt;/p&gt;&lt;ol start="16"&gt;
&lt;li&gt;The buffer cache hit ratio is a reliable indicator of system performance.&lt;/li&gt;
&lt;li&gt;Bitmap indexes are perfect for columns with a small number of distinct values, like 'Y' and 'N'.&lt;/li&gt;
&lt;li&gt;The Inuit have fifty words for snow.
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Spotted by Michel Cadot on Oracle-L.&lt;/p&gt;
&lt;p style="font-style: italic;"&gt;&lt;b&gt;Update:&lt;/b&gt; Yong Huang pointed out that the source of the article appears to be a list of common myths posted on a SQL Server blog, which makes it slightly less funny than it first seemed. Oh well.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-7219476775729158465?l=oracle-wtf.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-wtf.blogspot.com/feeds/7219476775729158465/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=15861274&amp;postID=7219476775729158465' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/7219476775729158465'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/7219476775729158465'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2008/11/more-fake-performance-tips.html' title='More Fake Performance Tips'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15419749305409395293'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-732908617249311457</id><published>2008-08-01T11:57:00.003+01:00</published><updated>2008-08-01T12:04:36.727+01:00</updated><title type='text'>TGI g_friday</title><content type='html'>&lt;p&gt;Found in a package body:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;g_friday CONSTANT VARCHAR2(6) := 'Friday';&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;...then a couple of hundred lines later:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;if to_char(business_date,'fmDay') = g_friday then
    &lt;i&gt;...end-of-week processing...&lt;/i&gt;
else
    &lt;i&gt;...regular processing...&lt;/i&gt;
end if;&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;Now that's flexible. If end-of-week processing is ever moved to the weekend, all you have to do is set &lt;tt&gt;g_friday := 'Saturday'&lt;/tt&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-732908617249311457?l=oracle-wtf.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-wtf.blogspot.com/feeds/732908617249311457/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=15861274&amp;postID=732908617249311457' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/732908617249311457'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/732908617249311457'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2008/08/tgi-gfriday.html' title='TGI g_friday'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15419749305409395293'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-5907826070431757676</id><published>2008-06-21T23:24:00.005+01:00</published><updated>2009-05-03T19:12:54.144+01:00</updated><title type='text'>Auxiliary Constructs Appeal</title><content type='html'>&lt;p&gt;Will somebody give &lt;a href="http://forums.oracle.com/forums/thread.jspa?messageID=2597237"&gt;this guy&lt;/a&gt; some auxiliary constructs? He just needs to know what's the auxiliary constructs, and examples in the auxiliary constructs. So if you have any auxiliary constructs you don't need, now's the time to dig deep. The appeal starts here.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-5907826070431757676?l=oracle-wtf.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://forums.oracle.com/forums/thread.jspa?messageID=2597237' title='Auxiliary Constructs Appeal'/><link rel='replies' type='application/atom+xml' href='http://oracle-wtf.blogspot.com/feeds/5907826070431757676/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=15861274&amp;postID=5907826070431757676' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/5907826070431757676'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/5907826070431757676'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2008/06/auxiliary-constructs-appeal.html' title='Auxiliary Constructs Appeal'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15419749305409395293'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-3669780349250863678</id><published>2008-04-27T20:15:00.002+01:00</published><updated>2008-05-03T16:41:15.201+01:00</updated><title type='text'>Fine tuning</title><content type='html'>&lt;p&gt;Mike is doing some work on an application that started life as SQL Server. Now that it has been converted to Oracle, there are one or two bits that could still do with a little fine tuning.&lt;/p&gt;&lt;p&gt;One particular procedure seemed to take rather a lot of time, and several developers had tried to get better performance out of it without much success. Here it is:&lt;/p&gt;&lt;blockquote&gt;
&lt;pre&gt;CREATE OR REPLACE PROCEDURE getupdatedrunids
    ( p_customer_id  IN VARCHAR2 DEFAULT NULL
    , pc_results_out IN OUT SYS_REFCURSOR )
AS
    v_fetch_status     INTEGER := 0;
    v_sql_status       INTEGER;
    v_fetch_status1    INTEGER := 0;
    v_sql_status1      INTEGER;
    v_event_id         VARCHAR2(50);
    v_runid            NUMBER(10, 0);
    v_count_run_conns  INTEGER := 0;
    v_temp_runs        INTEGER;

BEGIN
    DELETE FROM temp_runs;

    DELETE FROM temp_run_connections;

    INSERT INTO temp_runs
         ( run_id )
    SELECT DISTINCT i.run_id
    FROM   event_status i
         , run_status    b
    WHERE  i.run_id = b.run_id
    AND    i.event_id IN
           ( SELECT DISTINCT i.event_id
             FROM   event_status i
                  , run_status   b
             WHERE  i.run_id = b.run_id
             AND    b.customer_id = p_customer_id
             GROUP  BY i.event_id
             HAVING COUNT(i.run_id) &gt; 1)
             AND    b.customer_id = p_customer_id;

    BEGIN
        v_temp_runs := 0;
        SELECT COUNT(*)
        INTO   v_temp_runs
        FROM   dual
        WHERE  EXISTS
               ( SELECT *
                 FROM   temp_runs );
    END;

    IF v_temp_runs &gt; 0 THEN
    
        DECLARE
            CURSOR c_runs IS
                SELECT DISTINCT run_id
                FROM   temp_runs;
        BEGIN
            OPEN c_runs;
            FETCH c_runs INTO v_runid;

            IF c_runs%NOTFOUND
            THEN
                v_sql_status1   := 2;
                v_fetch_status1 := -1;
            ELSE
                v_sql_status1   := 0;
                v_fetch_status1 := 0;
            END IF;
        
            WHILE v_fetch_status1 = 0
            LOOP
                BEGIN
                    DECLARE
                        CURSOR cust_incidents_cs IS
                        
                            SELECT DISTINCT i.event_id
                            FROM   event_status i
                            WHERE  i.run_id = v_runid
                            AND    i.rejected = 0;
                    BEGIN
                        OPEN cust_incidents_cs;
                    
                        FETCH cust_incidents_cs INTO v_event_id;

                        IF cust_incidents_cs%NOTFOUND
                        THEN
                            v_sql_status   := 2;
                            v_fetch_status := -1;
                        ELSE
                            v_sql_status   := 0;
                            v_fetch_status := 0;
                        END IF;

                        &amp;lt;&amp;lt;i_loop1&gt;&gt;
                        WHILE v_fetch_status = 0
                        LOOP
                            BEGIN
                                INSERT INTO temp_run_connections
                                     ( run_id
                                     , connectedids)
                                SELECT DISTINCT v_runid
                                     , i.run_id AS connectedids
                                FROM   event_status i
                                WHERE  i.run_id &amp;lt; v_runid
                                AND    i.event_id = v_event_id
                                AND    i.rejected = 0
                                AND    i.run_id IN
                                       ( SELECT DISTINCT run_id
                                         FROM   temp_runs );

                                &amp;lt;&amp;lt;fetchnext&gt;&gt;
                                FETCH cust_incidents_cs INTO v_event_id;

                                IF cust_incidents_cs%NOTFOUND
                                THEN
                                    v_sql_status   := 2;
                                    v_fetch_status := -1;
                                ELSE
                                    v_sql_status   := 0;
                                    v_fetch_status := 0;
                                END IF;
                            END;
                        END LOOP;

                        CLOSE cust_incidents_cs;
                    END;
                
                    FETCH c_runs INTO v_runid;

                    IF c_runs%NOTFOUND
                    THEN
                        v_sql_status1   := 2;
                        v_fetch_status1 := -1;
                    ELSE
                        v_sql_status1   := 0;
                        v_fetch_status1 := 0;
                    END IF;
                END;
            END LOOP;
            CLOSE c_runs;
        END;
    END IF;

    SELECT COUNT(*)
    INTO   v_count_run_conns
    FROM   temp_run_connections;

    IF v_count_run_conns &gt; 0
    THEN
        OPEN pc_results_out FOR
            SELECT DISTINCT run_id, connectedids
            FROM   temp_run_connections;
    END IF;

END getupdatedrunids;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;His final version was much faster. See if you can spot the difference:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;CREATE OR REPLACE PROCEDURE getupdatedrunids
    ( p_customer_id  IN VARCHAR2 DEFAULT NULL
    , pc_results_out IN OUT SYS_REFCURSOR )
AS
BEGIN
    OPEN pc_results_out FOR
        SELECT DISTINCT e2.run_id, ic.run_id AS connectedids
        FROM   run_status r1
             , run_status r2
             , event_status e1
             , event_status e2
        WHERE  r1.customer_id = p_customer_id
        AND    r2.customer_id = r1.customer_id
        AND    e1.run_id = r2.run_id
        AND    e1.rejected = 0
        AND    e2.run_id = r1.run_id
        AND    e2.event_id = e1.event_id
        AND    e2.run_id &gt; e1.run_id
        AND    e2.rejected = 0
        ORDER BY 1, 2;

END getupdatedrunids;&lt;/pre&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-3669780349250863678?l=oracle-wtf.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-wtf.blogspot.com/feeds/3669780349250863678/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=15861274&amp;postID=3669780349250863678' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/3669780349250863678'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/3669780349250863678'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2008/04/fine-tuning.html' title='Fine tuning'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15419749305409395293'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-118925958724705034</id><published>2008-02-10T12:35:00.000Z</published><updated>2008-02-10T19:36:24.669Z</updated><title type='text'>WREAK_APPLICATION_HAVOC</title><content type='html'>&lt;p&gt;&lt;a href="http://tkyte.blogspot.com/2008/01/why-do-people-do-this.html"&gt;Tom Kyte recently blogged&lt;/a&gt; about the senseless and yet strangely common practice of coding something like this:&lt;/p&gt;&lt;pre&gt;WHEN OTHERS THEN
   RAISE_APPLICATION_ERROR(-20001,'Following Error Occured:' || SQLERRM);&lt;/pre&gt;
&lt;p&gt;which fairly obviously achieves nothing except take a standard message like this:&lt;/p&gt;&lt;pre&gt;ORA-06501: PL/SQL: program error
ORA-06512: at line 6&lt;/pre&gt;&lt;p&gt;and pointlessly scramble it into this:&lt;/p&gt;&lt;pre&gt;ORA-20001:&amp;nbsp;Following&amp;nbsp;Error&amp;nbsp;Occured:ORA-06501:&amp;nbsp;PL/SQL:&amp;nbsp;program&amp;nbsp;error
ORA-06512:&amp;nbsp;at&amp;nbsp;line&amp;nbsp;11&lt;/pre&gt;&lt;p&gt;which adds some meaningless text, hides the original line number, and miss-spells "occurred". Not bad for a day's work.&lt;/p&gt;&lt;p&gt;It turned out that some people had been doing this for years because they were simply too stupid to realise that they didn't have to.&lt;/p&gt;&lt;p&gt;Anyway you know all this because you read Tom Kyte's blog. But have a look at &lt;a href="http://www.techonthenet.com/oracle/exceptions/sqlerrm.php" rel="nofollow"&gt;this helpful page of advice&lt;/a&gt; from Tech On The Net, under &lt;i&gt;"Oracle/PLSQL: SQLERRM Function"&lt;/i&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;You could use the SQLERRM function to raise an error as follows:&lt;/p&gt;&lt;pre&gt;EXCEPTION
   WHEN OTHERS THEN
      raise_application_error
      (-20001,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM);
END;&lt;/pre&gt;&lt;p&gt;Or you could log the error to a table as follows:&lt;/p&gt;&lt;pre&gt;EXCEPTION
   WHEN OTHERS THEN
      err_code := SQLCODE;
      err_msg := substr(SQLERRM, 1, 200);

      INSERT INTO audit_table (error_number, error_message)
      VALUES (err_code, err_msg);
END;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;Now that is even better. The first example adds some meaningless text, hides the original line number, and duplicates the error code (unless it's a NO_DATA_FOUND exception, but let's not go there), to produce something like this:&lt;/p&gt;
&lt;pre&gt;ORA-20001:&amp;nbsp;An&amp;nbsp;error&amp;nbsp;was&amp;nbsp;encountered&amp;nbsp;-&amp;nbsp;-6501&amp;nbsp;-ERROR-&amp;nbsp;ORA-06501:&amp;nbsp;PL/SQL:&amp;nbsp;program&amp;nbsp;error&lt;br&gt;ORA-06512: at line 11&lt;/pre&gt;&lt;p&gt;The error logging example pointlessly captures &lt;tt&gt;SQLCODE&lt;/tt&gt; (nobody will ever use it), throws away all but the first 200 characters of the error stack, logs nothing about what happened, and fails to re-raise the exception so if you don't check the log you won't know anything went wrong until your customers start asking where their stuff is.&lt;/p&gt;
&lt;p&gt;Wouldn't it be great if there were, say, a Boolean third parameter to &lt;a href="http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14261/errors.htm#sthref2006"&gt;RAISE_APPLICATION_ERROR&lt;/a&gt; that would make it retain the existing error stack, freeing up the message line for you to put something intelligent and helpful, like, I don't know,&lt;/p&gt;
&lt;pre&gt;BEGIN
    RAISE program_error;
EXCEPTION
    WHEN OTHERS THEN
        RAISE_APPLICATION_ERROR
        ( -20001
        , 'Biscuits cannot be ordered on a ' || TO_CHAR(SYSDATE,'fmDay') ||
          ' without a hot beverage'
        , &lt;b&gt;TRUE&lt;/b&gt;);
END;&lt;/pre&gt;&lt;p&gt;to produce something like this:&lt;/p&gt;&lt;pre&gt;ORA-20001: Biscuits cannot be ordered on a Sunday without a hot beverage
ORA-06512: at line 5
ORA-06501: PL/SQL: program error&lt;/pre&gt;&lt;p&gt;We can but dream.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-118925958724705034?l=oracle-wtf.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-wtf.blogspot.com/feeds/118925958724705034/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=15861274&amp;postID=118925958724705034' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/118925958724705034'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/118925958724705034'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2008/02/wreakapplicationhavoc.html' title='WREAK_APPLICATION_HAVOC'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15419749305409395293'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-2499204318775308735</id><published>2007-10-26T08:33:00.000+01:00</published><updated>2007-10-26T08:36:04.200+01:00</updated><title type='text'>Frameworkia</title><content type='html'>&lt;p&gt;We thought long and hard about possible titles for &lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=575556&amp;tstart=0"&gt;this new PL/SQL development standard&lt;/a&gt; proposed on OTN, but we couldn't improve on the one it came with.&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;I want share a new IDEA to create a new standard PL/SQL developing:&lt;/p&gt;
&lt;pre&gt;&lt;br&gt;
Function &lt;name&gt;( Standard Buffer) return number
    variable Number;
    variable1 Varchar2;
begin
    variable := get from Standard Buffer;
    variable1 := get from Standard Buffer;

    { make your business }

    put in standard buffer your results
end;&lt;/br&gt;
&lt;/pre&gt;
&lt;p&gt;Give me feedback if you are interested at the new STANDARD called &lt;b&gt;"FRAMEWORKIA"&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;A lot possibilities are ready.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Do you see the genius of it?&lt;/p&gt;
&lt;p&gt;Er, no.&lt;/p&gt;
&lt;p&gt;Sensing that there were people who still needed convincing, user601181 posted some sample code developed using the new Frameworkia:&lt;/p&gt;
&lt;pre&gt;CREATE OR REPLACE FUNCTION iacore
    ( eobufferia IN OUT typeeodata )
    RETURN NUMBER
IS
    CURSOR cur_getroutingcondition
        ( idc_workflow IN VARCHAR2
        , idc_operation_node IN VARCHAR2 ) IS
        SELECT *
        FROM   wf_condition
        WHERE  id_workflow = idc_workflow
        AND    id_operation_node = idc_operation_node;

    rec_getroutingcondition cur_getroutingcondition%ROWTYPE;

    CURSOR cur_dobufferiaassign
        ( idc_workflow IN VARCHAR2
        , idc_operation_node IN VARCHAR2 ) IS
        SELECT *
        FROM   wf_assignement
        WHERE  id_workflow = idc_workflow
        AND    id_operation_node = idc_operation_node;

    rec_dobufferiaassign cur_dobufferiaassign%ROWTYPE;

    next_node         NUMBER;
    next_node_ck      NUMBER;
    stop_node         NUMBER;
    operation         VARCHAR2(256);
    operation_call    VARCHAR2(256);
    type_node         VARCHAR2(32);
    workflow          VARCHAR2(32);
    line              VARCHAR2(256);
    status_wf_v       VARCHAR2(3);
    pid_chain_node    NUMBER;
    ia_tid            VARCHAR2(64);
    ia_tid_micro      VARCHAR2(64);
    ret_code_default  NUMBER;
    ret_code          NUMBER;
    retval1           NUMBER;
    statementexc      VARCHAR2(256);
    schema_function   VARCHAR2(32);
    package_function  VARCHAR2(32);
    dblink_function   VARCHAR2(32);
    first_node_flag   VARCHAR2(2) := 'NO';
    id_debug_source   NUMBER;
    mapin_keyp        VARCHAR2(1024);

    headerbufferia typebufferia;
    assignbufferia typebufferia;
    checkbufferia  typebufferia;

    rec_wfnode               wf_node%ROWTYPE;
    rec_wffunctionsourcecode wf_function_source_code%ROWTYPE;
    rec_wflogger             wf_logger%ROWTYPE;
    rec_wfbusiness           wf_business%ROWTYPE;
    rec_wffieldmapping       wf_fieldmapping%ROWTYPE;
BEGIN
    headerbufferia := eobufferia(1);

    workflow := frameworkia.getvalue(headerbufferia,'ID_WORKFLOW');

    ---- DETERMINO QUALE NODO INVOCARE
    pid_chain_node := frameworkia.getvalue(headerbufferia,'WF_NODE_ID');

    ----- SE IL NODO E' NULL ALLORA E' IL PRIMO NODO
    IF pid_chain_node IS NULL
    THEN
        -------DETERMINO HANDLER E FILENAME PER IL LOGGER
        SELECT *
        INTO   rec_wflogger
        FROM   wf_logger
        WHERE  id_workflow = workflow;
        -- rec_WfLogger.ID_WORKFLOW
        -- rec_WfLogger.ID_DEBUG_LEVEL
        -- rec_WfLogger.ID_DIRHANDLER
        -- rec_WfLogger.ID_FILENAME

        --------INSERISCO NELL'HEADER
        frameworkia.setvalue
        ( headerbufferia
        , 'ID_DEBUG_WF'
        , rec_wflogger.id_debug_level );

        frameworkia.setvalue
        ( headerbufferia
        , 'ID_DIRHANDLER'
        , rec_wflogger.id_dirhandler );

        frameworkia.setvalue
        ( headerbufferia
        , 'ID_FILENAME'
        , rec_wflogger.id_filename );

        frameworkia.setvalue
        ( headerbufferia
        , 'CHARACTER_EVIDENCE'
        , '§§§§§§§§§§§§§§§§§§§§' );

        -------DETERMINO L'ID NODE
        SELECT wf_node_id
        INTO   pid_chain_node
        FROM   wf_node
        WHERE  id_workflow = workflow
        AND    wf_first_node = 'YES';

        SELECT *
        INTO   rec_wfnode
        FROM   wf_node
        WHERE  id_workflow = workflow
        AND    wf_first_node = 'YES';

        frameworkia.setvalue
        ( headerbufferia
        , 'WF_NODE_ID'
        , rec_wfnode.wf_node_id );

        SELECT b.status
        INTO   status_wf_v
        FROM   wf_node a
             , wf_name b
        WHERE  a.id_workflow = workflow
        AND    a.wf_node_id = rec_wfnode.wf_node_id
        AND    a.id_workflow = b.id_workflow;

        IF status_wf_v = 'OFF'
        THEN
            RETURN -1;
        END IF;

        ia_tid := frameworkia.getvalue(headerbufferia,'IA_TID');
        ret_code_default := 0;
        ret_code         := 0;

        frameworkia.setvalue
        ( headerbufferia
        , 'RET_CODE_DEFAULT'
        , ret_code_default );

        frameworkia.setvalue
        ( headerbufferia
        , 'RET_CODE'
        , ret_code);

        IF ia_tid IS NULL
        THEN
            ia_tid := 'TIA' || dbms_random.STRING('U',1 * 1 + 6) ||
                      TO_CHAR(SYSTIMESTAMP,'YYYYMMDDHH24MISSFF6');

            frameworkia.setvalue
            ( headerbufferia
            , 'IA_TID'
            , ia_tid );
        END IF;&lt;/pre&gt;
&lt;p&gt;That's just the first hundred lines, and I've formatted it. The complete &lt;tt&gt;iacore&lt;/tt&gt; function was well over 600 lines long.&lt;/p&gt;
&lt;p&gt;I for one welcome the new standard.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-2499204318775308735?l=oracle-wtf.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-wtf.blogspot.com/feeds/2499204318775308735/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=15861274&amp;postID=2499204318775308735' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/2499204318775308735'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/2499204318775308735'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2007/10/frameworkia.html' title='Frameworkia'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15419749305409395293'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-7521429017992529484</id><published>2007-08-14T18:08:00.000+01:00</published><updated>2007-08-14T18:16:27.383+01:00</updated><title type='text'>What is this "testing" thing?</title><content type='html'>&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?forumID=75&amp;threadID=542567"&gt;Recently asked&lt;/a&gt; on the OTN PL/SQL forum:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;I am reading a book: Learning Oracle PL/SQL by Bill Pribyl and Steven Feuerstein.&lt;/p&gt;&lt;p&gt;I am a newbie of PL/SQL and I got no other programming XPs. but in the very first of this book they are introducing something called: testing, to make some test programms /utilites.&lt;/p&gt;&lt;p&gt;I found that is very hard to make, is it neccessary?&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Apparently, after you've typed the final semicolon, you can either sit back and open a beer with the satisfaction of a job well done, or you can check whether the thing works. And apparently it's hard, so, do we really have to?&lt;/p&gt;&lt;p&gt;Well, another poster was recently arguing that &lt;a href="http://forums.oracle.com/forums/thread.jspa?messageID=1881571#1881571"&gt;PL/SQL is not suited to unit testing anyway&lt;/a&gt;, or refactoring either for that matter, because &lt;i&gt;it isn't object oriented&lt;/i&gt;. I think that will be my excuse from now on. You want me to test stuff, go make PL/SQL more objecty.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-7521429017992529484?l=oracle-wtf.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-wtf.blogspot.com/feeds/7521429017992529484/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=15861274&amp;postID=7521429017992529484' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/7521429017992529484'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/7521429017992529484'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2007/08/what-is-this-testing-thing.html' title='What is this &quot;testing&quot; thing?'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15419749305409395293'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-1091133067457129331</id><published>2007-08-10T11:16:00.000+01:00</published><updated>2007-08-10T13:47:25.561+01:00</updated><title type='text'>Welcome back</title><content type='html'>&lt;p&gt;Our guest administrator "Splogger" has now left the building, along with his page of helpful links to items on Amazon.com and a range of gentlemen's health products.&lt;/p&gt;&lt;p&gt;Suspiciously, a couple of days before he arrived we were taken off air by Blogger's spambots, presumably alerted by the amount of &lt;a href="http://radiofreetooting.blogspot.com/2007/07/roy-batty-writes.html"&gt;irrelevant, repetitive, and nonsensical text&lt;/a&gt; and links to Viagra sites they found here. &lt;a href="http://bloggerstatusforreal.blogspot.com/2006/07/stolen-computers.html"&gt;From what I read&lt;/a&gt;, it seems possible that the Blogger automated suspension to prevent blog spam might have actually left the account vulnerable to blog spammers. As ironies go, that is up there with rain on your wedding day and good advice that you just didn't take.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-1091133067457129331?l=oracle-wtf.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-wtf.blogspot.com/feeds/1091133067457129331/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=15861274&amp;postID=1091133067457129331' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/1091133067457129331'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/1091133067457129331'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2007/08/welcome-back.html' title='Welcome back'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15419749305409395293'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-2576207396364451697</id><published>2007-05-03T01:38:00.000+01:00</published><updated>2007-05-03T02:05:28.691+01:00</updated><title type='text'>One liner</title><content type='html'>&lt;br&gt;I was untangling a query when I came across eight variations of this code where only the literals 'a' to 'e' changed. Two of these were nested within an additional &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;NVL&lt;/span&gt;&lt;/span&gt; so that the second would execute if the first returned null.

&lt;pre&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;nvl&lt;/span&gt;&lt;/span&gt;(decode(2, 1, 'a', 2, 'b', 3, 'c', 4, 'd', 5, 'e', ' '), '&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;na&lt;/span&gt;&lt;/span&gt;')
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-2576207396364451697?l=oracle-wtf.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-wtf.blogspot.com/feeds/2576207396364451697/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=15861274&amp;postID=2576207396364451697' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/2576207396364451697'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/2576207396364451697'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2007/05/one-liner.html' title='One liner'/><author><name>3360</name><uri>http://www.blogger.com/profile/15154122363413824960</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='13602772465233799293'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-8228621318724798864</id><published>2007-04-08T13:37:00.000+01:00</published><updated>2007-04-08T13:39:15.783+01:00</updated><title type='text'>DATE comparisons: the scenic route</title><content type='html'>&lt;p&gt;Need to calculate the number of minutes between two dates? Yes, the dull way is to subtract one from the other and multiply by 1440. But why do that, when you can simply convert each date into Julian format by converting it into a string and then back to a date, and converting the resulting date into a Julian string, and (in a separate step) applying &lt;tt&gt;TO_NUMBER&lt;/tt&gt; to the result to get an integer, so that you can simply subtract one from the other and multiply by 1440.&lt;/p&gt;
&lt;p&gt;Except that rounds to the nearest day, so an additional step is to calculate the minutes since midnight for each of the two dates, which you can do by simply converting each date into an 'HH:MI AM' string, then back to a date, then back to an 'SSSSS' string, converting it to a number, dividing by 60 and adding it to the result of the first calculation. I think.&lt;/p&gt;

&lt;p&gt;Anyway, consider the following library of handy date functions our Oracle WTF Easter gift to you, the online development community.&lt;/p&gt;
&lt;pre&gt;CREATE PACKAGE dates_pkg
AS
    FUNCTION julian_date
        ( date_to_convert DATE )
        RETURN NUMBER;

    FUNCTION minutes_since_midnight
        ( timevalue DATE )
        RETURN NUMBER;

    FUNCTION minutes_elapsed
        ( lowdate DATE
        , highdate DATE )
        RETURN NUMBER;

END dates_pkg;
/

CREATE PACKAGE BODY dates_pkg
AS
    FUNCTION julian_date
        ( date_to_convert DATE)
        RETURN NUMBER
    IS
        varch_value VARCHAR (10);
        num_value NUMBER (20);
    BEGIN
        SELECT TO_CHAR
               ( TO_DATE(TO_CHAR(date_to_convert,'MM/DD/YYYY'),'MM/DD/YYYY')
               , 'J')
        INTO   varch_value
        FROM   dual;

        SELECT TO_NUMBER (varch_value)
        INTO   num_value
        FROM   dual;

        RETURN (num_value);
    END julian_date;


    FUNCTION minutes_since_midnight (
        timevalue DATE)
        RETURN NUMBER
    IS
        secs_elapsed NUMBER (20);
        mins_elapsed NUMBER (20);
    BEGIN
        SELECT TO_NUMBER
               ( TO_CHAR(TO_DATE(TO_CHAR(timevalue,'HH:MI AM'),'HH:MI AM')
               , 'SSSSS') )
        INTO   secs_elapsed
        FROM   dual;

        SELECT (secs_elapsed / 60)
        INTO   mins_elapsed
        FROM   dual;

        RETURN (mins_elapsed);
    END minutes_since_midnight;


    FUNCTION minutes_elapsed
        ( lowdate DATE
        , highdate DATE )
        RETURN NUMBER
    IS
        final_number NUMBER (20);
        low_julian NUMBER (20);
        high_julian NUMBER (20);
        num_days NUMBER (20);
        num_minutes NUMBER (20);
        temp_mins NUMBER (20);
        min_low NUMBER (20);
        min_high NUMBER (20);
    BEGIN
        SELECT julian_date (lowdate)
        INTO   low_julian
        FROM   dual;

        SELECT julian_date (highdate)
        INTO   high_julian
        FROM   dual;

        SELECT (high_julian - low_julian)
        INTO   num_days
        FROM   dual;

        SELECT (num_days * 1440)
        INTO   num_minutes
        FROM   dual;

        SELECT minutes_since_midnight (lowdate)
        INTO   min_low
        FROM   dual;

        SELECT minutes_since_midnight (highdate)
        INTO   min_high
        FROM   dual;

        SELECT (min_high - min_low)
        INTO   temp_mins
        FROM   dual;

        SELECT (num_minutes + temp_mins)
        INTO   final_number
        FROM   dual;

        RETURN (final_number);

    END minutes_elapsed;
END dates_pkg;
&lt;/pre&gt;
&lt;p&gt;Just for fun, let's test it:&lt;/p&gt;
&lt;pre&gt;CREATE TABLE wtf_test (start_date NOT NULL, end_date NOT NULL) AS
SELECT DATE '2006-12-25' + DBMS_RANDOM.VALUE(1,365)
     , DATE '2007-12-25' + DBMS_RANDOM.VALUE(1,365)
FROM   dual CONNECT BY LEVEL &lt;= 1000;

-- &lt;i&gt;...several runs here to allow for caching etc, last set of results shown...&lt;/i&gt;

SQL&gt; set timing on autotrace traceonly stat

SQL&gt; SELECT dates_pkg.minutes_elapsed(start_date,end_date) FROM wtf_test;

1000 rows selected.

Elapsed: 00:00:03.96

Statistics
----------------------------------------------------------
  &lt;b&gt;16000  recursive calls&lt;/b&gt;
      0  db block gets
     74  consistent gets
      0  physical reads
      0  redo size
   9330  bytes sent via SQL*Net to client
    809  bytes received via SQL*Net from client
     68  SQL*Net roundtrips to/from client
      0  sorts (memory)
      0  sorts (disk)
   1000  rows processed

SQL&gt; SELECT (end_date - start_date) * 1440 FROM wtf_test;

1000 rows selected.

Elapsed: 00:00:00.16

Statistics
----------------------------------------------------------
      &lt;b&gt;0  recursive calls&lt;/b&gt;
      0  db block gets
     74  consistent gets
      0  physical reads
      0  redo size
  25485  bytes sent via SQL*Net to client
    809  bytes received via SQL*Net from client
     68  SQL*Net roundtrips to/from client
      0  sorts (memory)
      0  sorts (disk)
   1000  rows processed&lt;/pre&gt;
&lt;p&gt;So the handy package version takes &lt;b&gt;25 times&lt;/b&gt; as long as the 1-line SQL version.&lt;/p&gt;
&lt;p&gt;And in the interests of fairness, in case you're thinking perhaps that is just the normal overhead of calling PL/SQL functions in SQL, let's try our own function:&lt;/p&gt;
&lt;pre&gt;CREATE FUNCTION minutes_elapsed
    ( lowdate DATE
    , highdate DATE )
    RETURN NUMBER
AS
BEGIN
    RETURN (highdate - lowdate) * 1440;
END minutes_elapsed;
/

SQL&gt; SELECT minutes_elapsed(start_date,end_date) FROM wtf_test;

1000 rows selected.

Elapsed: 00:00:00.26

Statistics
----------------------------------------------------------
     21  recursive calls
      0  db block gets
    107  consistent gets
      0  physical reads
      0  redo size
  25496  bytes sent via SQL*Net to client
    809  bytes received via SQL*Net from client
     68  SQL*Net roundtrips to/from client
      0  sorts (memory)
      0  sorts (disk)
   1000  rows processed&lt;/pre&gt;
&lt;p&gt;Still 15 times faster.&lt;/p&gt;
&lt;p&gt;Many thanks to Padders for sharing this one.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-8228621318724798864?l=oracle-wtf.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-wtf.blogspot.com/feeds/8228621318724798864/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=15861274&amp;postID=8228621318724798864' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/8228621318724798864'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/8228621318724798864'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2007/04/date-comparisons-scenic-route.html' title='DATE comparisons: the scenic route'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15419749305409395293'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-7269800696104288291</id><published>2007-03-23T07:51:00.000Z</published><updated>2007-03-23T08:11:55.425Z</updated><title type='text'>Quote For The Day</title><content type='html'>&lt;blockquote&gt;&lt;i&gt;"PL/SQL development can be a tedious and time-consuming job – often monopolizing the valuable time and efforts of Oracle developers."&lt;/i&gt; &lt;b&gt;- &lt;a href="http://www.quest.com/sql_navigator/" rel=nofollow&gt;SQL Navigator page, Quest Software&lt;/a&gt;&lt;/b&gt;&lt;/blockquote&gt;

&lt;p&gt;Spare a thought today for PL/SQL developers, having their precious time tediously monopolised by, umm, PL/SQL development.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-7269800696104288291?l=oracle-wtf.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-wtf.blogspot.com/feeds/7269800696104288291/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=15861274&amp;postID=7269800696104288291' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/7269800696104288291'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/7269800696104288291'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2007/03/quote-for-day.html' title='Quote For The Day'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15419749305409395293'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-2062963565245353794</id><published>2007-03-19T20:55:00.000Z</published><updated>2007-03-19T20:56:36.967Z</updated><title type='text'>423,551 Invalid Indexes</title><content type='html'>&lt;p&gt;A friend received an alarming email from a commendably proactive DBA who was concerned that he had discovered a potentially serious performance issue on the production system:&lt;/p&gt;
&lt;blockquote&gt;The following result shows there are many invalid  indexes. For example, in the first row we see that there are nearly 423551 invalid indexes for just one row of a table. So if we rebuilt the index it would improve the performance.&lt;/blockquote&gt;
&lt;p&gt;Wow, that sure is a lot of invalid indexes for just one row of a table. For the sake of anonymity, I've run his query against the SCOTT/TIGER schema, where fortunately there are only 14 invalid indexes (or perhaps 10, if that's how you count them). Perhaps you can see what the problem might be:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;SELECT DISTINCT
       t.table_name
     , i.index_name
     , t.num_rows table_rows
     , i.num_rows index_rows
FROM   dba_tables t
     , dba_indexes i
WHERE  t.table_name = 'DEPT'
AND    t.owner = 'SCOTT'
AND    i.owner = t.owner
AND    i.index_type = 'NORMAL';

TABLE_NAME                     INDEX_NAME                     TABLE_ROWS INDEX_ROWS
------------------------------ ------------------------------ ---------- ----------
DEPT                           PK_EMP                                  4         14
DEPT                           EMP_DEPT_IX                             4         14
DEPT                           PK_DEPT                                 4          4
DEPT                           PK_SALGRADE                             4          5

4 rows selected.&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;There is worse to come. It's not just DEPT that has invalid indexes. He goes on:&lt;/p&gt;
&lt;blockquote&gt;The following result shows there are many invalid indexes, so if we rebuild the index, it would improve the performance. At the same time from the first and last rows, indexes are not being used, so we need to look into it.&lt;/blockquote&gt;
&lt;blockquote&gt;&lt;pre&gt;TABLE_NAME                     INDEX_NAME                     TABLE_ROWS INDEX_ROWS
------------------------------ ------------------------------ ---------- ----------
SALGRADE                       PK_DEPT                                 5          4
SALGRADE                       PK_EMP                                  5         14
SALGRADE                       EMP_DEPT_IX                             5         14
SALGRADE                       PK_SALGRADE                             5          5

TABLE_NAME                     INDEX_NAME                     TABLE_ROWS INDEX_ROWS
------------------------------ ------------------------------ ---------- ----------
EMP                            PK_DEPT                                14          4
EMP                            PK_EMP                                 14         14
EMP                            EMP_DEPT_IX                            14         14
EMP                            PK_SALGRADE                            14          5&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;I just can't help wondering what he thinks an index is.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-2062963565245353794?l=oracle-wtf.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-wtf.blogspot.com/feeds/2062963565245353794/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=15861274&amp;postID=2062963565245353794' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/2062963565245353794'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/2062963565245353794'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2007/03/423551-invalid-indexes.html' title='423,551 Invalid Indexes'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15419749305409395293'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-116899419612369997</id><published>2007-01-17T00:33:00.000Z</published><updated>2007-01-17T16:28:42.046Z</updated><title type='text'>Performance Tuning and The Big O</title><content type='html'>&lt;p&gt;Oracle Performance Tuning is a big subject, as anyone will appreciate who has read any of a number of books that set out to help you to understand what problem you are trying to solve, what factors may affect the performance you are seeing, what strategies are available to the query optimizer, and so on.&lt;/p&gt;

&lt;p&gt;While Cary Millsap's &lt;i&gt;Optimizing Oracle Performance&lt;/i&gt; focusses on finding, tracing and prioritising specific problems in the face of vague reports that the system seems a bit slow this week, and Jonathan Lewis' &lt;i&gt;Cost-Based Oracle Fundamentals&lt;/i&gt; takes us on a tour of the CBO to help answer such questions as &lt;i&gt;Why isn't my &lt;tt&gt;EXISTS&lt;/tt&gt; query using an index? (and why isn't it faster than the &lt;tt&gt;IN&lt;/tt&gt; version?)&lt;/i&gt; a poster on &lt;a href=http://www.orafaq.com/forum/?t=rview&amp;goto=213972&gt;OraFAQ&lt;/a&gt; has an approach we've not seen before:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;The following is a problem I need help with and I am willing to pay for help if necessary. Any info would be greatly appreciated.&lt;/p&gt;

&lt;p&gt;Two tables in a database:&lt;/p&gt;

&lt;p&gt;Table1 contains a list of phone numbers&lt;br&gt;
Table2 contains a list of phone numbers as well&lt;/p&gt;

&lt;p&gt;I would like to create a Table3, in which Table3 contains all numbers
from Table1 that is not in Table2. I am looking for the shortest
runtime possible, keeping in mind that you can use whatever method(s)
you deem necessary.&lt;/p&gt;

&lt;p&gt;Table1 contains 30 Million rows,&lt;br&gt;
Table2 contains 2000 rows.&lt;/p&gt;

&lt;p&gt;given a regular SQL expression, it will yield Big O(m*n)&lt;/p&gt;

&lt;p&gt;Where m = rowcount of Table1&lt;br&gt;
and n = rowcount of Table2&lt;/p&gt;

&lt;p&gt;Generate for me, a method in which, runtime will yield Big O (m log2
n).&lt;/p&gt;

&lt;p&gt;I don't need code, I want to hear your logic. Table1 is customers, Table2 is a list of prepaid phone numbers. Table3 is list of people to bill.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;As usual no database version is given. The first suggestion, as you might expect, is the quite reasonable:&lt;/p&gt;
&lt;pre&gt;select phone_no from table1
minus
select phone_no from table2;&lt;/pre&gt;
&lt;p&gt;accompanied by a comment that it doesn't seem like a great piece of schema design to have two tables in the first place. However, the reply comes back:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;The guy who wrote this problem just told me that this answer is incorrect.&lt;/p&gt;
&lt;p&gt;His response to me was:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;it's not too simplistic, but it is incorrect. This will still yield a big O(m*n).&lt;/p&gt;

&lt;p&gt;Give it one more try, you are thinking too much in terms of DB.&lt;/p&gt;

&lt;p&gt;Ask yourself, what are the only structures that would yield
BigO(nlog2n)? Answer that, and you will get your answer.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Any ideas?&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Resident mathematician Ross Leishman tried to explain to me what &lt;i&gt;Big O (m log2n)&lt;/i&gt; means, and I can confirm that it is not after all a &lt;i&gt;When Harry Met Sally&lt;/i&gt; reference as most of us would probably assume. Apparently the version with an &lt;tt&gt;EXISTS&lt;/tt&gt; subquery was what was wanted, which seemed odd to me on a number of levels, not least that an &lt;tt&gt;IN&lt;/tt&gt; subquery would probably produce the same plan, especially in 10g where the new &lt;tt&gt;HASH JOIN RIGHT ANTI&lt;/tt&gt; allows the database to build its hash table from the 2,000-row table2 rather than the 30 million-row table1. But of course we don't know the database version, do we? Or whether the columns are nullable, unique or indexed, or how values are distributed, or really anything about the actual environment that would help in solving a real-world performance problem. I can see where I'm going wrong though. I am thinking too much in terms of DB.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-116899419612369997?l=oracle-wtf.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-wtf.blogspot.com/feeds/116899419612369997/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=15861274&amp;postID=116899419612369997' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/116899419612369997'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/116899419612369997'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2007/01/performance-tuning-and-big-o_17.html' title='Performance Tuning and The Big O'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15419749305409395293'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-116870200874889046</id><published>2007-01-13T15:13:00.000Z</published><updated>2007-01-15T15:28:43.563Z</updated><title type='text'>Short loop</title><content type='html'>&lt;p&gt;It's good to see a GOTO every now and then. However, the sender of this one (thanks!) was most impressed by the loop that goes from 1 to &lt;tt&gt;v_totalcntr&lt;/tt&gt;, and indeed the fact that there is a loop and a &lt;tt&gt;v_totalctr&lt;/tt&gt; variable at all, with the variable carefully set from the cursor's &lt;tt&gt;%ROWCOUNT&lt;/tt&gt;, when it can only ever have one value:&lt;/p&gt;
&lt;pre&gt;DECLARE
  CURSOR cur_pricing IS
      SELECT col1, col2
      FROM   sometable;

  var_pricing cur_pricing%ROWTYPE;

BEGIN
  OPEN cur_pricing;
  FETCH cur_pricing INTO var_pricing;

  IF cur_pricing%NOTFOUND THEN
      GOTO continue;
  END IF;

  v_totalcntr := cur_pricing%ROWCOUNT;

  FOR r IN 1..v_totalcntr
  LOOP
      -- loads of stuff here
      -- but no fetch from cur_pricing
      -- not even for the one time this loop will execute :-)
  END LOOP;

  &amp;lt;&amp;lt;continue&gt;&gt;
  NULL;
END;&lt;/pre&gt;
&lt;p&gt;Of course you could just fetch the value you want and process it, but where would be the fun in that?&lt;/p&gt;

&lt;p&gt;&lt;b&gt;PS&lt;/b&gt; The person who sent this in emailed me with a point I must admit hadn't occurred to me:&lt;/p&gt;

&lt;blockquote&gt;Saw you posted this one - thanks. But did you pick up on what they probably thought they were doing? I think whoever wrote it thought that &lt;tt&gt;%rowcount&lt;/tt&gt; would have the TOTAL number of rows that the cursor would return - so they thought they would be looping around ALL the records in the cursor. The fact that they also forgot to fetch again in the loop just adds to the problem of course.&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-116870200874889046?l=oracle-wtf.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-wtf.blogspot.com/feeds/116870200874889046/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=15861274&amp;postID=116870200874889046' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/116870200874889046'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/116870200874889046'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2007/01/short-loop_13.html' title='Short loop'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15419749305409395293'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-116603248419013315</id><published>2006-12-13T15:27:00.000Z</published><updated>2006-12-14T01:24:09.700Z</updated><title type='text'>Code Re-use</title><content type='html'>&lt;p&gt;This code was anonymised by the sender and some of the original logic may be a bit harder to make sense of as a result. Instead of EMP records, you should probably imagine it checking billion-dollar financial deals or nuclear reactor core temperature readings. Anyway, I think I've figured out what it's supposed to do.&lt;/p&gt;

&lt;p&gt;You pass in an EMP record containing &lt;i&gt;first name, last name, email address&lt;/i&gt; and so on, and it calls &lt;tt&gt;OTHER_PROC(email_address,&amp;nbsp;the_emp_record_as_passed_in)&lt;/tt&gt; - &lt;i&gt;but only if&lt;/i&gt; the email address is not null, &lt;i&gt;and&lt;/i&gt; it is unique for employees with that name. For some reason. But how to check? Simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use a cursor to load all the rows for that name into an array. (Apparently there were 130+ columns in the original table.)&lt;/li&gt;
&lt;li&gt;Check array.COUNT to see how many rows there are.&lt;/li&gt;
&lt;li&gt;If there is only one row, use it, taking care to use an NVL expression because we definitely don't want a NULL email address.&lt;/li&gt;
&lt;li&gt;If there is more than one row, open the same cursor again, and this time loop through it comparing each row's email address with the previous one. If it's the same, set &lt;tt&gt;lv_email_same&lt;/tt&gt; = 1, otherwise set it to 0. That way, at the end of the loop we'll know whether they were all the same or not, right?&lt;/li&gt;
&lt;/ol&gt;
&lt;br&gt;
&lt;pre&gt;
PROCEDURE unleash_havoc (p_emp_rec emp%rowtype)
IS
   lv_email_same  NUMBER(1) :=0; -- 0: no, 1: yes
   lv_email_null  NUMBER(1) :=0; -- 0: no, 1: yes
   lv_email       emp.email%TYPE := NULL;
   ln_row         NUMBER;

   TYPE emp_tab IS TABLE OF emp%ROWTYPE;
   lt_emp_data  emp_tab;

   CURSOR c_emp (p_last_name VARCHAR2, p_first_name VARCHAR2) IS
      SELECT *
      FROM   emp e
      WHERE  e.last_name = p_last_name
      AND    e.first_name = p_first_name;

BEGIN
   OPEN c_emp (p_emp_rec.last_name, p_emp_rec.first_name);
   FETCH c_emp BULK COLLECT INTO lt_emp_data;
   CLOSE c_emp;

   IF lt_emp_data.COUNT = 1 THEN
       ln_row := lt_emp_data.FIRST;
       lv_email  := NVL(lt_emp_data(ln_row).email,NULL);
       other_proc(lv_email,p_emp_rec);

   ELSIF lt_emp_data.COUNT &gt; 1 THEN

       FOR r IN c_emp (p_emp_rec.last_name, p_emp_rec.first_name) LOOP
           IF NVL(r.email,'X') = NVL(lv_email,'X') THEN
               lv_email := r.email;
               lv_email_same := 1;
           ELSE
               lv_email := r.email;
               lv_email_same := 0;
           END IF;

           IF r.email IS NULL THEN
               lv_email_null := 1;
           ELSE
               lv_email_null := 0;
           END IF;
       END LOOP;

       IF  lv_email_same = 1
       AND lv_email_null = 0
       THEN
           lv_email  := NVL(lt_emp_data(ln_row).email,NULL);
           other_proc(lv_email,p_emp_rec);
       ELSE
           ...
       END IF;
   END IF;
END;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-116603248419013315?l=oracle-wtf.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://oracle-wtf.blogspot.com/feeds/116603248419013315/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=15861274&amp;postID=116603248419013315' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/116603248419013315'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/116603248419013315'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/12/code-re-use.html' title='Code Re-use'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15419749305409395293'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-116124106163866933</id><published>2006-10-19T07:28:00.000+01:00</published><updated>2006-10-19T07:58:56.280+01:00</updated><title type='text'>Pause For Thought part 2</title><content type='html'>&lt;p&gt;In &lt;a href="http://asktom.oracle.com/pls/ask/f?p=4950:8:::::F4950_P8_DISPLAYID:4243161825986#74632859512796"&gt;an AskTom thread about native compilation&lt;/a&gt;, a poster mentions that he is seeing some big CPU waits on his system and wonders whether native compilation would help. After some discussion of tracing and profiling and his 32 Tuxedo connections, he reports back that from talking to the programmer (possibly &lt;a href="http://oracle-wtf.blogspot.com/2006/07/pause-for-thought.html"&gt;this guy&lt;/a&gt;), he might have narrowed the problem down to a procedure called DELAY():&lt;/p&gt;
&lt;blockquote&gt;I just happened to talk to the programmer and what i understand is that that 
specific function when called so many times , it is internally calling a 
procedure with passing a value n, where n is like 4,5,6 etv.
That procedure is called delay and its job is to create a delay in the logic 
flow. So the delay procedure accepsts values like 10 as seconds and then it
&lt;pre&gt;FOR di IN 1..sed LOOP
   NULL;
END LOOP;&lt;/pre&gt;
A random thought, could this when run so many times accumulate huge cpu?&lt;/blockquote&gt;
&lt;p&gt;Tom thinks maybe it might.&lt;/p&gt;
&lt;p&gt;Thanks Tom for sending this in.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-116124106163866933?l=oracle-wtf.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://asktom.oracle.com/pls/ask/f?p=4950:8:::::F4950_P8_DISPLAYID:4243161825986#74632859512796' title='Pause For Thought part 2'/><link rel='replies' type='application/atom+xml' href='http://oracle-wtf.blogspot.com/feeds/116124106163866933/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=15861274&amp;postID=116124106163866933' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/116124106163866933'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/116124106163866933'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/10/pause-for-thought-part-2.html' title='Pause For Thought part 2'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15419749305409395293'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-116069195206233672</id><published>2006-10-12T23:25:00.000+01:00</published><updated>2006-10-12T23:27:24.670+01:00</updated><title type='text'>Death By Furniture</title><content type='html'>&lt;p&gt;According to &lt;a href="http://www.identifiers.org" rel="nofollow"&gt;www.identifiers.org&lt;/a&gt;, there are two classes of relational database: &lt;i&gt;"Code Class"&lt;/i&gt; and &lt;i&gt;"Identifier Class"&lt;/i&gt;.&lt;/p&gt;&lt;p&gt;We hadn't heard of those either, but it's all made clear in &lt;a href="http://www.identifiers.org/downloads/05_99.pdf" rel="nofollow"&gt;this presentation&lt;/a&gt; (pdf, 1.2MB), in which the limitations of the conventional approach and a novel approach to schema design are explained without the aid of Powerpoint, in a series of pictures like this one:&lt;/p&gt;
&lt;div style="margin: 15pt 0pt; clear: left;"&gt;&lt;img src="http://photos1.blogger.com/blogger/7758/1483/1600/george-explains-airpii.jpg" /&gt;&lt;/div&gt;
&lt;p&gt;Still confused? Never mind, you can follow the debate on &lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=427362"&gt;this OTN thread&lt;/a&gt;, which George begins by asking for a simple clarification regarding the capabilities of the Oracle RDBMS. From the answers to this, he should be able to determine whether Oracle is old-hat &lt;i&gt;Code Class&lt;/i&gt; or funky new &lt;i&gt;Identifier Class&lt;/i&gt;:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;I have an interest in establishing how the Oracle System Catalogues cope with particular changes. I have never used Oracle, but I have carried out the same test on another RDBMS. If I had access to Oracle I would have carried out this test myself.&lt;/p&gt;
&lt;p&gt;The test goes as follows.&lt;/p&gt;
&lt;p&gt;Create a new database.&lt;/p&gt;
&lt;p&gt;Create a new simple table, with just a few columns.&lt;/p&gt;
&lt;p&gt;Create a form for the table, and add a few rows.&lt;/p&gt;
&lt;p&gt;Rename the table or a column – if you can’t, then the RDBMS is Code Class.&lt;/p&gt;
&lt;p&gt;If you can rename the table or a column, then do so, and invoke the form that you used before changing the table or column name. If it doesn’t work, the RDBMS is Code Class; if it does then the RDBMS is Identifier Class.&lt;/p&gt;
&lt;p&gt;In an Identifier Class RDBMS changes of column or relation/table name will not interfere with the operation of any form already in place based on that table.&lt;/p&gt;
&lt;p&gt;I'll be very grateful if anybody can give me a definitive answer on this, either through already having explored the issue or by running the test.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;It turns out that &lt;i&gt;"Code Class"&lt;/i&gt; covers all existing RDBMS products ever conceived, and &lt;i&gt;"Identifier Class"&lt;/i&gt; is an improved model invented by George himself, in which some theoretical 4GL development tool yet to be designed allows you to change table and column names without breaking existing code or having to define a view, and surrogate keys are, well, pretty much the same except that they are now called &lt;i&gt;attribute independent relative position independent identifiers&lt;/i&gt;. Perhaps one day Oracle will advance to this point, especially now that they've fixed DBMS_OUTPUT and must be wondering what to do next (perhaps after getting a product to work on Apple Mac and fixing the OTN "change password" facility). We can but dream.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-116069195206233672?l=oracle-wtf.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://forums.oracle.com/forums/thread.jspa?threadID=427362' title='Death By Furniture'/><link rel='replies' type='application/atom+xml' href='http://oracle-wtf.blogspot.com/feeds/116069195206233672/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=15861274&amp;postID=116069195206233672' title='18 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/116069195206233672'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/116069195206233672'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/10/death-by-furniture_12.html' title='Death By Furniture'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15419749305409395293'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>18</thr:total></entry></feed>