<?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' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-15861274</id><updated>2012-01-21T20:41:06.152Z</updated><title type='text'>Oracle WTF</title><subtitle type='html'>Analyze This</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?max-results=100'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>93</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-15861274.post-452067979669871331</id><published>2011-03-26T09:08:00.000Z</published><updated>2011-03-26T09:08:41.360Z</updated><title type='text'>Concatenation, Concatenation, Concatenation</title><content type='html'>&lt;p&gt;I'm still not sure what this one does, but you have to be impressed by 11 nested CONCATs.&lt;/p&gt;&lt;p&gt;(And by the way, you also have to be impressed by the inventor of the &lt;tt&gt;CONCAT&lt;/tt&gt; function who evidently considered two arguments sufficient, unlike, say &lt;tt&gt;LEAST&lt;/tt&gt;, &lt;tt&gt;GREATEST&lt;/tt&gt;, &lt;tt&gt;DECODE&lt;/tt&gt;, &lt;tt&gt;COALESCE&lt;/tt&gt; and &lt;tt&gt;BIN_TO_NUM&lt;/tt&gt;. But not &lt;tt&gt;NVL&lt;/tt&gt;. Who knows what goes through these people's heads.)&lt;/p&gt;
&lt;pre&gt;PROCEDURE ins_xyz
   ( p_xyz_id_out OUT NUMBER,
     p_input_array IN myarrayrectype )
IS
BEGIN
   p_xyz_id_out := NULL;

   BEGIN
      INSERT INTO xyztab
         (
            xyz_id,
            xyz_11,
            xyz_12,
            xyz_13,
            xyz_21,
            xyz_22,
            xyz_23,
            xyz_31,
            xyz_32,
            xyz_33,
            xyz_41,
            xyz_42,
            xyz_43,
            xyz_43_concatenated
         )
      VALUES
         (
            xyz_seq.NEXTVAL,
            p_input_array.xyz_11,
            p_input_array.xyz_12,
            p_input_array.xyz_13,
            p_input_array.xyz_21,
            p_input_array.xyz_22,
            p_input_array.xyz_23,
            p_input_array.xyz_31,
            p_input_array.xyz_32,
            p_input_array.xyz_33,
            p_input_array.xyz_41,
            p_input_array.xyz_42,
            p_input_array.xyz_43,
            SUBSTR(
              CONCAT(
                CONCAT(
                  CONCAT(
                    CONCAT(
                      CONCAT(
                        CONCAT(
                          CONCAT(
                            CONCAT(
                              CONCAT(
                                CONCAT(
                                  CONCAT(
                                    p_input_array.xyz_11 || ' ',
                                    p_input_array.xyz_12 || ' '),
                                  p_input_array.xyz_13 || ' ' ),
                                p_input_array.xyz_21 || ' ' ),
                              p_input_array.xyz_22 || ' ' ),
                            p_input_array.xyz_23 || ' ' ),
                          p_input_array.xyz_31 || ' ' ),
                        p_input_array.xyz_32 || ' ' ),
                      p_input_array.xyz_33 || ' ' ),
                    p_input_array.xyz_41 || ' ' ),
                  p_input_array.xyz_42 || ' ' ),
                p_input_array.xyz_43 ),
            1, 512 )
         )
      RETURNING xyz_id INTO p_xyz_id_out;
   EXCEPTION
      WHEN OTHERS THEN NULL;
   END;
END ins_xyz;
&lt;/pre&gt;
&lt;p&gt;Thanks BB for this one, which she or he (I can't say more for witness protection reasons) sent me a while ago and I almost forgot about.&lt;/p&gt;&lt;p&gt;I didn't post it at the time because I couldn't understand what it did. Looking at it again though, that's all part of the fun. Here's part of the conversation we had about it:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;b&gt;Me:&lt;/b&gt; Thanks BB - love it. I'm  slightly puzzled by p_input_array though. Is it an  array?&lt;/p&gt;
&lt;p&gt;&lt;b&gt;BB:&lt;/b&gt; An array of records.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Me:&lt;/b&gt; Yikes. So what does the target table look like? I suppose each &lt;i&gt;'xyz_nn_'&lt;/i&gt; column must be a nested table.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;BB:&lt;/b&gt; In the actual system they're parts of node tuples. &lt;i&gt;xyz_11, xyz_12, xyz_13&lt;/i&gt;, all indicate "scores" for pairings of the first node with 1, 2, 3, respectively. Hard to explain without giving away too much about the system. However, they're scalars.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Me:&lt;/b&gt; Glad we got that cleared up. Can I say &lt;i&gt;parts of node tuples&lt;/i&gt; without endangering your job at NASA?&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-452067979669871331?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/452067979669871331/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=452067979669871331' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/452067979669871331'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/452067979669871331'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2011/03/concatenation-concatenation.html' title='Concatenation, Concatenation, Concatenation'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-8932879139201997970</id><published>2011-03-12T15:04:00.000Z</published><updated>2011-03-12T15:04:44.315Z</updated><title type='text'>Explain this</title><content type='html'>&lt;p&gt;On the subject of &lt;a href="http://oracle-wtf.blogspot.com/2011/03/make-me-one-with-everything.html"&gt;cryptic OTN posts&lt;/a&gt;, &lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=1955511"&gt;this one&lt;/a&gt; has to get an honorary mention as well:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;h3&gt;explain this&lt;/h3&gt;&lt;br&gt;&lt;/p&gt;&lt;p&gt;hi,&lt;/p&gt;&lt;p&gt;write query to find out order detail of oder_date 2 year before (sorry i forget exact question)&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;No solutions so far.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-8932879139201997970?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/8932879139201997970/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=8932879139201997970' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/8932879139201997970'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/8932879139201997970'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2011/03/explain-this.html' title='Explain this'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-4925612722564686264</id><published>2011-03-12T14:52:00.000Z</published><updated>2011-03-12T14:52:28.708Z</updated><title type='text'>Make Me One With Everything</title><content type='html'>&lt;p&gt;Seen on &lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=2188330&amp;amp;tstart=0"&gt;OTN Forums&lt;/a&gt; recently (part of a question entitled &lt;i&gt;"HTML not working in PL/SQL block"&lt;/i&gt;, so I suppose we were warned):&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre&gt;l_col VARCHAR2(30) := to_number(to_char(to_date('01-feb-2011','dd-mon-yyyy'),'dd'));&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;So the string &lt;tt&gt;'01-feb-2011'&lt;/tt&gt; becomes first a date, then a string again, then a number, before being assigned to a string variable. Much more interesting than boring old&lt;p&gt;
&lt;blockquote&gt;
&lt;pre&gt;l_col VARCHAR2(30) := extract (day from date '2011-02-01');&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;Or even,&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre&gt;l_col VARCHAR2(30) := '1';&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-4925612722564686264?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/4925612722564686264/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=4925612722564686264' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/4925612722564686264'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/4925612722564686264'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2011/03/make-me-one-with-everything.html' title='Make Me One With Everything'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-4849165561594579990</id><published>2010-01-21T07:26:00.003Z</published><updated>2010-01-21T07:28:46.772Z</updated><title type='text'>Interview questions</title><content type='html'>&lt;p&gt;A friend recently had a telephone interview for an Oracle technical contract role. Here are the questions he was asked:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;What is the command to edit a crontab?&lt;/li&gt;
&lt;li&gt;What are the first and fourth parameters on the crontab?&lt;/li&gt;
&lt;li&gt;What is the command to email the list of files that are too big and need to be deleted to prevent a tablespace getting too big?&lt;/li&gt;
&lt;li&gt;Have you used the OLAP command? and who invented it?&lt;/li&gt;
&lt;li&gt;When do you set PCTFREE?&lt;/li&gt;
&lt;li&gt;When is the PGA in the SGA?&lt;/li&gt;
&lt;li&gt;Where is the Java pool?&lt;/li&gt;
&lt;li&gt;How do I stop a checkpoint when I commit?&lt;/li&gt;
&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-4849165561594579990?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/4849165561594579990/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=4849165561594579990' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/4849165561594579990'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/4849165561594579990'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2010/01/interview-questions.html' title='Interview questions'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>10</thr:total></entry><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='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=8582046489776760636' title='4 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:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>4</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='http://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:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>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='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=9046417030658760478' title='10 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:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>10</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='http://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:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>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='http://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:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>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='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=7945167208236007944' title='9 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:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>9</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='http://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:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>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='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=8844457069260996002' title='5 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:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>5</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='http://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:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>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='http://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:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>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='http://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:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>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='http://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:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>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='http://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:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>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='http://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:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>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='http://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:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>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='http://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:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>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='http://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:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>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='http://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:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>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='http://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:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>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='http://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:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>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='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=116899419612369997' title='5 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:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>5</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='http://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:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>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='http://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:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>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='http://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:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>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='http://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:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>18</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-115840843719502848</id><published>2006-09-16T23:01:00.000+01:00</published><updated>2006-09-16T23:27:19.900+01:00</updated><title type='text'>Useful books</title><content type='html'>&lt;div style="margin: 15pt 0pt; clear: left;"&gt;&lt;img src="http://photos1.blogger.com/blogger/7758/1483/400/spider-safari-1.jpg" border="0" /&gt;
&lt;p&gt;An enormous spider appears. It's clearly coming for you. Or not. What do you do?&lt;/p&gt;&lt;/div&gt;

&lt;div style="margin: 15pt 0pt; clear: left;"&gt;&lt;img src="http://photos1.blogger.com/blogger/7758/1483/400/spider-safari-2.jpg" border="0" /&gt;
&lt;p&gt;Staying calm, place a glass or similar containment device over the creature.&lt;/p&gt;&lt;/div&gt;

&lt;div style="margin: 15pt 0pt; clear: left;"&gt;&lt;img src="http://photos1.blogger.com/blogger/7758/1483/400/spider-safari-3.jpg" alt="" border="0" /&gt;
&lt;p&gt;Now gently slide a card under the glass, taking care not to trap any legs. There should be eight after you have completed this manoeuvre.&lt;/p&gt;&lt;/div&gt;

&lt;div style="margin: 15pt 0pt; clear: left;"&gt;&lt;img src="http://photos1.blogger.com/blogger/7758/1483/400/spider-safari-4.jpg" border="0" /&gt;
&lt;p&gt;Transfer to a suitable platform such as a book, and carry to a window or other suitable release location.&lt;/p&gt;&lt;/div&gt;

&lt;div style="margin: 15pt 0pt; clear: left;"&gt;&lt;img src="http://photos1.blogger.com/blogger/7758/1483/400/spider-safari-5.jpg" border="0" /&gt;
&lt;p&gt;No Oracle experts were harmed in the making of this blog.&lt;/p&gt;&lt;/div&gt;

&lt;div style="margin: 15pt 0pt; clear: left;"&gt;&lt;img src="http://photos1.blogger.com/blogger/7758/1483/400/spider-safari-6.jpg" border="0" /&gt;
&lt;p&gt;Reintroduce the creature into the wild, where it can begin a new life free to roam among its own kind. Or just wander back in of course, but spiders are not known for their homing instinct. Or are they? To be honest we haven't checked. This one said something about "Scotland" and "revenge".&lt;/p&gt;
&lt;/div&gt;

&lt;div style="margin: 15pt 0pt; clear: left;"&gt;&lt;img style="" src="http://photos1.blogger.com/blogger/7758/1483/400/spider-safari-7.jpg" border="0" /&gt;
&lt;p&gt;Finally, always sterilise your equipment.&lt;/p&gt;&lt;/div&gt;

&lt;div style="margin: 15pt 0pt; clear: left;"&gt;&lt;a href="http://oracledoug.com/serendipity/index.php?/archives/1074-Useful-Books.html" rel="nofollow"&gt;&lt;img src="http://photos1.blogger.com/blogger/7758/1483/320/crimescene.jpg" border="0" /&gt;&lt;/a&gt;
&lt;p&gt;Meanwhile in Edinburgh, police were called to a flat in the Stockbridge area following reports of a violent assault...&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-115840843719502848?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/115840843719502848/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=115840843719502848' title='16 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/115840843719502848'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/115840843719502848'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/09/useful-books.html' title='Useful books'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>16</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-115814784058633218</id><published>2006-09-13T12:34:00.000+01:00</published><updated>2006-09-13T12:44:00.600+01:00</updated><title type='text'>Just, Why?</title><content type='html'>I'm currently debugging a procedure of the form illustrated below, lovingly recreated using the ubiquitous scott.emp table.

I'm also taking suggestions on what might've been going through the head of the person who wrote it.

&lt;pre&gt;

RENAME emp TO emp_table
/
CREATE OR REPLACE VIEW emp
AS
   SELECT *
     FROM emp_table
/
CREATE OR REPLACE TRIGGER mod_emp
   INSTEAD OF UPDATE
   ON emp
   FOR EACH ROW
DECLARE
   new_emp                       emp_table%ROWTYPE;
   old_emp                       emp_table%ROWTYPE;
BEGIN
   new_emp.empno       := :NEW.empno;
   new_emp.ename       := :NEW.ename;
   new_emp.job         := :NEW.job;
   new_emp.mgr         := :NEW.mgr;
   new_emp.hiredate    := :NEW.hiredate;
   new_emp.sal         := :NEW.sal;
   new_emp.comm        := :NEW.comm;
   new_emp.deptno      := :NEW.deptno;
   old_emp.empno       := :OLD.empno;
   old_emp.ename       := :OLD.ename;
   old_emp.job         := :OLD.job;
   old_emp.mgr         := :OLD.mgr;
   old_emp.hiredate    := :OLD.hiredate;
   old_emp.sal         := :OLD.sal;
   old_emp.comm        := :OLD.comm;
   old_emp.deptno      := :OLD.deptno;
   update_emp (old_emp, new_emp);
END;
/

CREATE OR REPLACE PROCEDURE update_emp (
   old_emp                             emp_table%ROWTYPE
  ,new_emp                             emp_table%ROWTYPE
)
IS
BEGIN
   IF old_emp.empno != new_emp.empno
   THEN
      RETURN;   --can't update primary key attribute
   END IF;

   IF     old_emp.empno IS NOT NULL
      AND new_emp.empno IS NULL
   THEN
      DELETE FROM emp_table
            WHERE empno = old_emp.empno;

      RETURN;
   END IF;

   IF    (    old_emp.ename IS NULL
          AND new_emp.ename IS NOT NULL)
      OR (    old_emp.ename IS NOT NULL
          AND new_emp.ename != old_emp.ename)
   THEN
      UPDATE emp_table
         SET ename = new_emp.ename
       WHERE empno = old_emp.empno;
   END IF;
   -- ..
   -- ..
   -- ..
   IF    (    old_emp.deptno IS NULL
          AND new_emp.deptno IS NOT NULL)
      OR (    old_emp.deptno IS NOT NULL
          AND new_emp.deptno != old_emp.deptno)
   THEN
      UPDATE emp_table
         SET deptno = new_emp.deptno
       WHERE empno = old_emp.empno;
   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-115814784058633218?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/115814784058633218/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=115814784058633218' title='14 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/115814784058633218'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/115814784058633218'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/09/just-why.html' title='Just, Why?'/><author><name>Adrian</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>14</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-115780635282442626</id><published>2006-09-09T13:52:00.000+01:00</published><updated>2006-09-09T16:22:43.546+01:00</updated><title type='text'>A Year of WTFs</title><content type='html'>&lt;p&gt;Each year, the Oracle WTF organisation celebrates its anniversary by inviting a fellow Oracle professional to share an evening of fine Eastern European lager and disappointing bar snacks in a   pub where you can't hear each other properly, and this year it was the turn of former newbie (but now of course senior expert) DBA &lt;a href="http://newbiedba.blogspot.com"&gt;Lisa Dobson&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Actually that's not quite true - I realised today it was just over a year ago that we started the blog, and the other evening some of us met up with Lisa who happened to be in town, and if I'd thought of this a bit earlier I could probably have pretended it was all planned. Anyway it was nice meeting Lisa, and we enjoyed the story about the colleague who accidentally deleted &lt;i&gt;the entire production server&lt;/i&gt;, as luck would have it a week after the server room air conditioning took out the only other server by dripping a surprisingly large amount of water into it. That rather outdid my story about the day we turned up for work at a client's site and found nobody could log in, because as it happened someone had stolen the servers during the night. Or the other one, if I'd remembered to tell it, about the high street retail chain whose backup system involved a PC and a timer plug. (I shouldn't laugh - it actually worked quite well.) It was also reassuring to hear we are not the only ones who don't understand a single bloody word of those "Oracle" blogs about installing a Java framework in JDeveloper to implement service-oriented BPEL with a right-click and some XML. Umm, neat.&lt;/p&gt;&lt;p&gt;It seems we're also not the only ones to have been shocked and saddened by &lt;a href="http://oracledoug.com/serendipity/index.php?/archives/1074-Useful-Books.html"&gt;Doug Burns' recent senseless killing spree&lt;/a&gt;. This monster must be stopped. (...is probably what Doug said as he reached for his copy of "Expert One-On-One Oracle").&lt;/p&gt;
&lt;p&gt;Anyway, one year, 63 posts, and some lessons learned:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;Post one of Tom Kyte's pet hates like &lt;tt&gt;WHEN OTHERS THEN NULL&lt;/tt&gt; (or &lt;a href="http://www.datawebtect.com/wordpress/2006/08/22/when-others/"&gt;&lt;tt&gt;WHEN OTHERS THEN DBMS_OUTPUT&lt;/tt&gt;&lt;/a&gt;, which isn't much better quite frankly) for a mention on &lt;a href="http://tkyte.blogspot.com/2006/08/ouch-that-hurts.html"&gt;his blog&lt;/a&gt; and a surefire thousand hits. We need one about &lt;a href="http://tkyte.blogspot.com/2006/01/im-speak.html"&gt;IM Speak&lt;/a&gt; now b/c im sure u will C loadsa hits ;-)&lt;/li&gt;
&lt;li&gt;Post something involving security for a mention on &lt;a href="http://www.petefinnigan.com/weblog/archives/00000765.htm"&gt;Pete Finnigan's site&lt;/a&gt;. We also get a steady stream of visitors googling for &lt;i&gt;"forgot system password +oracle"&lt;/i&gt;, &lt;i&gt;"how to get password of a user in oracle"&lt;/i&gt; and so on, and being directed to &lt;a href="http://oracle-wtf.blogspot.com/2006/03/umm-i-forgot-my-password-part-2.html"&gt;Umm, I Forgot My Password, part 2&lt;/a&gt;. (In future just &lt;a href="http://thedailywtf.com/forums/thread/85316.aspx"&gt;put it on a Post-It under your keyboard&lt;/a&gt; like everyone else.)&lt;/li&gt;
&lt;li&gt;Titles involving common Oracle error codes seem to do well. A lot of visitors come here from  a Google search for &lt;a href="http://www.google.com/search?q=sp2-0552" hl="en&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;q=SP2-0552&amp;btnG=Google%20Search&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;"&gt;SP2-0552&lt;/a&gt; (guys, you have a variable with a colon in front of it somewhere). We need some posts about ORA-0600 or TNSNAMES.&lt;/li&gt;
&lt;li&gt;A lot of people seem to be searching for an explanation of joins and end up at our &lt;a href="http://oracle-wtf.blogspot.com/2005/09/joins-explained.html"&gt;Joins Explained&lt;/a&gt;, heaven help them, where a Mr Sanders Kaufman explains things like &lt;i&gt;"Left Joins are joined on the left columns of two tables. Right Joins are joined on the right columns of two tables."&lt;/i&gt; I'm glad we got that cleared up.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.google.com/analytics/"&gt;Google Analytics&lt;/a&gt; Rock. So (while we're at it) do &lt;a href="http://www.statcounter.com/"&gt;Statcounter&lt;/a&gt;, &lt;a href="http://www.feedburner.com"&gt;Feedburner&lt;/a&gt; and &lt;a href="http://www.cocomment.com/"&gt;CoComment&lt;/a&gt;.
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We were recently offered some sponsorship by price comparison website &lt;a href="http://www.shopzilla.co.uk"&gt;Shopzilla&lt;/a&gt; (or rather, they emailed me a week ago and I remembered it in the pub). The consensus among those present was that we should not accept it, although personally I think all that would change if we could get &lt;a href="http://thedailywtf.com/forums/thread/87772.aspx"&gt;The Daily WTF's Beanbag Girl&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We were also kindly offered a spot on &lt;a href="http://www.pythian.com/blogs/about-log-buffer/"&gt;Pythian Group's Logfile Of The Vanities&lt;/a&gt; or whatever it's called (or rather, they emailed me a month ago and I seem to have deleted the message, sorry guys, meant to get back to you) but  I didn't take them up on it, partly because there didn't seem much point in writing a piece telling people about Oracle blogs they already read (surely?) via &lt;a href="http://blogs.oracle.com/"&gt;blogs.oracle.com&lt;/a&gt;, and also because it's explicitly for DBAs, and with the possible exception of Padders we are all developers (even though these days "developer" is often assumed to mean someone who is into aspect-oriented JDeveloper BPEL plug-ins). Our main thing is SQL, PL/SQL and &lt;a href="http://oracle-wtf.blogspot.com/2006/02/eav-returns-concrete-elephant-approach.html"&gt;data modelling&lt;/a&gt;, and AFAIK none of those have much to do with the DBA role. In fact, thinking about it I'm not sure why they asked. And is that &lt;tt&gt;Pie-thian&lt;/tt&gt; as in Pythagoras and Python, or &lt;tt&gt;Pith-ian&lt;/tt&gt; as in &lt;a href="http://www.hp-lexicon.org/hogwarts/houses/gryffindor.html"&gt;Gryffindor&lt;/a&gt; and &lt;a href="http://www.hp-lexicon.org/hogwarts/houses/slytherin.html"&gt;Slytherin&lt;/a&gt;, anyway?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-115780635282442626?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/115780635282442626/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=115780635282442626' title='32 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/115780635282442626'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/115780635282442626'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/09/year-of-wtfs_09.html' title='A Year of WTFs'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>32</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-115682099217988449</id><published>2006-08-29T04:08:00.000+01:00</published><updated>2006-08-29T04:10:36.450+01:00</updated><title type='text'>Production-ready code</title><content type='html'>I'm not sure that there's much more to add to this forums.oracle.com &lt;a href="http://forums.oracle.com/forums/thread.jspa?messageID=1433907"&gt;thread&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-115682099217988449?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/115682099217988449/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=115682099217988449' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/115682099217988449'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/115682099217988449'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/08/production-ready-code.html' title='Production-ready code'/><author><name>Scott Swank</name><uri>http://www.blogger.com/profile/01922902566871746635</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-115600495671627037</id><published>2006-08-19T17:00:00.000+01:00</published><updated>2006-08-19T17:45:14.016+01:00</updated><title type='text'>Competition</title><content type='html'>&lt;p&gt;Well, not really a competition because we haven't got any prizes to give away, but the code below (thanks Padders) has a real &lt;i&gt;"How Many WTFs Can You Spot?"&lt;/i&gt; feel about it. I make it four.&lt;/p&gt;
&lt;pre&gt;PROCEDURE log_error
    ( p_source  IN  VARCHAR2
    , p_result  IN  VARCHAR2)
IS
    PRAGMA AUTONOMOUS_TRANSACTION;
    p_primarykey errorlogging.primarykey%TYPE;
BEGIN
    SELECT errorlogging_seq.NEXTVAL
    INTO   p_primarykey
    FROM   dual;

    INSERT /*+ APPEND */ INTO errorlogging NOLOGGING
    ( primarykey
    , source
    , result
    , timestamp
    , wherewasi
    , processed_count
    , process_id )
    VALUES
    ( p_primarykey
    , p_source
    , SUBSTR(p_result, 1, 1000)
    , SYSDATE
    , NULL
    , NULL
    , 1 );

    COMMIT;
EXCEPTION
    WHEN OTHERS THEN NULL;
END;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-115600495671627037?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/115600495671627037/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=115600495671627037' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/115600495671627037'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/115600495671627037'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/08/competition.html' title='Competition'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-115502039406999825</id><published>2006-08-08T06:47:00.000+01:00</published><updated>2006-08-08T08:02:08.616+01:00</updated><title type='text'>Show Me The Money</title><content type='html'>&lt;p&gt;Money, money, money. It's a rich man's world. It can't buy you love, but as we are constantly reminded it can buy you cheap Levitra and pre-approved loans, and those are just as good and will probably boost this site's stats. It makes the world go round. It's great - but how to format it?&lt;/p&gt;

&lt;p&gt;Well, here is one way. The editing history tells the whole story.&lt;/p&gt;
&lt;br&gt;

&lt;pre&gt;
/*=============================================================================
Procedure:    FN_FORMAT_DOLLARS
Description:  Formats a number as dollars (2 decimals)

MODIFICATION HISTORY:
Person        Date        Comments
---------     ------      -------------------------------------------
XX            01/24/03    Created
SF            08/05/03    Rewrote the function as a TO_CHAR statement
==============================================================================*/

FUNCTION fn_format_dollars (p_dollars IN NUMBER)
    RETURN VARCHAR2
IS
    &lt;i&gt;-- v_dollars   VARCHAR2 (50);&lt;/i&gt;
BEGIN

    &lt;i&gt;/*
    v_dollars := TO_CHAR (p_dollars);
    IF INSTR (v_dollars, '.') = 0
    THEN
        v_dollars :=  v_dollars  || '.';
    END IF;

    -- too many decimal places...
    WHILE   LENGTH (v_dollars) - INSTR (v_dollars, '.') &gt; 2
    LOOP
        v_dollars := SUBSTR (v_dollars, 1, LENGTH (v_dollars) - 1);
    END LOOP;

    -- not enough decimal places...
    WHILE   LENGTH (v_dollars) - INSTR (v_dollars, '.') &lt; 2
    LOOP
        v_dollars := v_dollars || '0';
     END LOOP;
    */&lt;/i&gt;

    RETURN TO_CHAR(p_dollars, 'FM999999999990.00');

END fn_format_dollars;
&lt;/pre&gt;
&lt;br&gt;
&lt;p&gt;Many thanks to rd 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-115502039406999825?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/115502039406999825/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=115502039406999825' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/115502039406999825'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/115502039406999825'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/08/show-me-money.html' title='Show Me The Money'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-115317229151164642</id><published>2006-07-17T22:18:00.000+01:00</published><updated>2006-07-17T23:40:00.296+01:00</updated><title type='text'>The fine line between clever and stupid</title><content type='html'>&lt;p&gt;Stojka Mongo began to be concerrned when he came across table AT_ILOAD_DAYS that looked like this:&lt;/p&gt;
&lt;pre&gt;CREATE TABLE at_iload_days
( daystring      VARCHAR2(8)
, batch_created  VARCHAR2(1)  DEFAULT 'N' );&lt;/pre&gt;&lt;p&gt;where "daystring" contained values like "20030901".&lt;/p&gt;

&lt;p style="margin-top: 24px;"&gt;Then he found this convenient procedure to "fill" it:&lt;/p&gt;&lt;pre&gt;CREATE OR REPLACE PROCEDURE pr_generate_iload_days
AS
    -- Procedure to fill days from most recent entry in at_iload_days up to current sysdate */
    d_date_string    VARCHAR2(8) DEFAULT NULL;
    d_maxdate_string VARCHAR2(8) DEFAULT NULL;
BEGIN
    -- sysdate will be max date to generate:
    d_maxdate_string := TO_CHAR(SYSDATE, 'yyyymmdd');

    -- Fetch most recent datestring from at_iload_days + 1 day into d_date_string
    -- (default to commercial launch date)
    EXECUTE IMMEDIATE
    'select to_char((to_date(nvl(max(daystring),''20030505''),''yyyymmdd'')+1),''yyyymmdd'') from at_iload_days'
    INTO d_date_string;

    -- We shouldn't load data that will exist in the future, should we?
    IF d_date_string &lt;= d_maxdate_string THEN
        EXECUTE IMMEDIATE
        'insert into at_iload_days (daystring,batch_created) values (' ||
        '''' ||d_date_string || '''' || ',''N'')';

        EXECUTE IMMEDIATE 'COMMIT';
    END IF;
END pr_generate_iload_days;&lt;/pre&gt;
&lt;p style="margin-top: 24px;"&gt;Our favourite line:&lt;p&gt;&lt;pre&gt;EXECUTE IMMEDIATE 'COMMIT';&lt;/pre&gt;
&lt;p style="margin-top: 24px;"&gt;It's hard to tell but I think that procedure can be rewritten as:&lt;/p&gt;&lt;pre&gt;CREATE OR REPLACE PROCEDURE pr_generate_iload_days
AS
BEGIN
    INSERT INTO at_iload_days (daystring)
    SELECT TO_CHAR
           ( TO_DATE(NVL(MAX(daystring),'20030505'),'yyyymmdd')+1
           , 'yyyymmdd' )
    FROM   at_iload_days
    HAVING NVL(MAX(daystring),'20030505') &lt;= TO_CHAR(SYSDATE, 'yyyymmdd')
END pr_generate_iload_days;&lt;/pre&gt;
&lt;p style="margin-top: 24px;"&gt;although if DAYSTRING had actually been a date, it would have just been:&lt;/p&gt;
&lt;pre&gt;CREATE OR REPLACE PROCEDURE pr_generate_iload_days
AS
BEGIN
    INSERT INTO at_iload_days(day)
    SELECT NVL(MAX(day), DATE '2003-05-05') +1
    FROM   at_iload_days
    HAVING NVL(MAX(day), DATE '2003-05-05') &lt;= SYSDATE;
END pr_generate_iload_days;&lt;/pre&gt;
&lt;p style="margin-top: 24px;"&gt;Thanks 3360 for the title for this post.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-115317229151164642?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/115317229151164642/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=115317229151164642' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/115317229151164642'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/115317229151164642'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/07/fine-line-between-clever-and-stupid.html' title='The fine line between clever and stupid'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-115292268995354070</id><published>2006-07-15T00:14:00.000+01:00</published><updated>2006-08-21T08:41:35.623+01:00</updated><title type='text'>Pause for thought</title><content type='html'>&lt;p&gt;Requirement:&lt;/p&gt;
&lt;blockquote&gt;Can I let a procedure wait for a specific time (10 seconds) before inserting values into a table?&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=402345"&gt;One solution&lt;/a&gt; (according to a poster on OTN - don't try this at home):&lt;/p&gt;
&lt;pre&gt;declare
  dStart DATE := SYSDATE;
  nDiff  NUMBER;
begin
  dbms_output.put_line('dStart: '||TO_CHAR(dStart, 'dd.mm.yyyy hh24:mi:ss'));
  LOOP
    nDiff := (SYSDATE - dStart)*86400;
    EXIT WHEN nDiff &gt;= 10;
  END LOOP;
  dbms_output.put_line('nDiff: '||nDiff);
  dbms_output.put_line('END: '||TO_CHAR(SYSDATE, 'dd.mm.yyyy hh24:mi:ss'));
end;
/&lt;/pre&gt;
&lt;p&gt;Or &lt;a href="http://forums.oracle.com/forums/thread.jspa?messageID=1360604#1360604"&gt;if you prefer&lt;/a&gt;,&lt;/p&gt;
&lt;pre&gt;create or replace function timeout
    return number
is
begin
    return to_number(to_char(sysdate,'SSSSS'));
end timeout;
/

Function created.

create or replace procedure tcal( t in number ) as
    a  number:=1;
    st number:=to_number(to_char(sysdate,'SSSSS'));
    x varchar2(12);
    y varchar2(12);
begin
    while(a&lt;99999999) loop
        dbms_output.enable(100000); ---&gt; Just to make loop busy...
        a := a + 1;
        exit when (timeout - st)&gt;=t;
    end loop;

    x:=to_char(trunc(sysdate)+st/(24*60*60),'HH:MI:SS AM');

    dbms_output.put_line('       Started: '||x);

    y:=to_char(trunc(sysdate)+timeout/(24*60*60),'HH:MI:SS AM');

    dbms_output.put_line('       Ended:   '||y);
    dbms_output.put_line(timeout-st||' seconds reached...');
end ;
/

Procedure created.&lt;/pre&gt;
&lt;p&gt;Now that is all well and good, you may say, after all the cpu isn't doing anything else at the moment and these days they rarely catch fire, but couldn't we just use the supplied procedure &lt;a href="http://download-uk.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_lock.htm#sthref3947"&gt;DBMS_LOCK.SLEEP&lt;/a&gt;? Well apparently it is impractical. Those with a quiet afternoon to spare might like to follow the reasons why, at &lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=402345"&gt;forums.oracle.com/forums/thread.jspa?threadID=402345&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-115292268995354070?l=oracle-wtf.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://forums.oracle.com/forums/thread.jspa?threadID=402345&amp;start=25&amp;tstart=0' title='Pause for thought'/><link rel='replies' type='application/atom+xml' href='http://oracle-wtf.blogspot.com/feeds/115292268995354070/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=115292268995354070' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/115292268995354070'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/115292268995354070'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/07/pause-for-thought.html' title='Pause for thought'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-115107978478306186</id><published>2006-06-23T16:59:00.000+01:00</published><updated>2006-06-23T17:34:15.490+01:00</updated><title type='text'>That Reminds Me...</title><content type='html'>&lt;p&gt;Sometimes the solutions people come up with to a given problem are breathtaking in their combination of ingenuity and insanity.  Take this view, which exists purely to transform a boring "reminder number" like 3, 4, 5, ... into the English text "Third Reminder", "Fourth Reminder", "Fifth Reminder", ...&lt;/p&gt;

&lt;pre&gt;CREATE OR REPLACE VIEW reminders_view AS
SELECT reminder_id
, reminder_seq
, ( SELECT 
      DECODE (reminder_seq, 
       1, 'No reminder', 
       2, 'Reminded', 
       3, INITCAP(TO_CHAR(TO_DATE(TO_CHAR(reminder_seq)||'-MAY-2004','DD-MON-YYYY'),'ddspth'))||' Reminder', 
       4, INITCAP(TO_CHAR(TO_DATE(TO_CHAR(reminder_seq)||'-MAY-2004','DD-MON-YYYY'),'ddspth'))||' Reminder', 
       5, INITCAP(TO_CHAR(TO_DATE(TO_CHAR(reminder_seq)||'-MAY-2004','DD-MON-YYYY'),'ddspth'))||' Reminder', 
    6, INITCAP(TO_CHAR(TO_DATE(TO_CHAR(reminder_seq)||'-MAY-2004','DD-MON-YYYY'),'ddspth'))||' Reminder', 
    7, INITCAP(TO_CHAR(TO_DATE(TO_CHAR(reminder_seq)||'-MAY-2004','DD-MON-YYYY'),'ddspth'))||' Reminder', 
    8, INITCAP(TO_CHAR(TO_DATE(TO_CHAR(reminder_seq)||'-MAY-2004','DD-MON-YYYY'),'ddspth'))||' Reminder', 
    9, INITCAP(TO_CHAR(TO_DATE(TO_CHAR(reminder_seq)||'-MAY-2004','DD-MON-YYYY'),'ddspth'))||' Reminder', 
    10, INITCAP(TO_CHAR(TO_DATE(TO_CHAR(reminder_seq)||'-MAY-2004','DD-MON-YYYY'),'ddspth'))||' Reminder', 
    11, INITCAP(TO_CHAR(TO_DATE(TO_CHAR(reminder_seq)||'-MAY-2004','DD-MON-YYYY'),'ddspth'))||' Reminder', 
    12, INITCAP(TO_CHAR(TO_DATE(TO_CHAR(reminder_seq)||'-MAY-2004','DD-MON-YYYY'),'ddspth'))||' Reminder', 
    13, INITCAP(TO_CHAR(TO_DATE(TO_CHAR(reminder_seq)||'-MAY-2004','DD-MON-YYYY'),'ddspth'))||' Reminder', 
    14, INITCAP(TO_CHAR(TO_DATE(TO_CHAR(reminder_seq)||'-MAY-2004','DD-MON-YYYY'),'ddspth'))||' Reminder', 
    15, INITCAP(TO_CHAR(TO_DATE(TO_CHAR(reminder_seq)||'-MAY-2004','DD-MON-YYYY'),'ddspth'))||' Reminder', 
    16, INITCAP(TO_CHAR(TO_DATE(TO_CHAR(reminder_seq)||'-MAY-2004','DD-MON-YYYY'),'ddspth'))||' Reminder', 
    17, INITCAP(TO_CHAR(TO_DATE(TO_CHAR(reminder_seq)||'-MAY-2004','DD-MON-YYYY'),'ddspth'))||' Reminder', 
    18, INITCAP(TO_CHAR(TO_DATE(TO_CHAR(reminder_seq)||'-MAY-2004','DD-MON-YYYY'),'ddspth'))||' Reminder', 
    19, INITCAP(TO_CHAR(TO_DATE(TO_CHAR(reminder_seq)||'-MAY-2004','DD-MON-YYYY'),'ddspth'))||' Reminder', 
    20, INITCAP(TO_CHAR(TO_DATE(TO_CHAR(reminder_seq)||'-MAY-2004','DD-MON-YYYY'),'ddspth'))||' Reminder', 
    21, INITCAP(TO_CHAR(TO_DATE(TO_CHAR(reminder_seq)||'-MAY-2004','DD-MON-YYYY'),'ddspth'))||' Reminder', 
    22, INITCAP(TO_CHAR(TO_DATE(TO_CHAR(reminder_seq)||'-MAY-2004','DD-MON-YYYY'),'ddspth'))||' Reminder', 
    23, INITCAP(TO_CHAR(TO_DATE(TO_CHAR(reminder_seq)||'-MAY-2004','DD-MON-YYYY'),'ddspth'))||' Reminder', 
    24, INITCAP(TO_CHAR(TO_DATE(TO_CHAR(reminder_seq)||'-MAY-2004','DD-MON-YYYY'),'ddspth'))||' Reminder', 
    25, INITCAP(TO_CHAR(TO_DATE(TO_CHAR(reminder_seq)||'-MAY-2004','DD-MON-YYYY'),'ddspth'))||' Reminder', 
    26, INITCAP(TO_CHAR(TO_DATE(TO_CHAR(reminder_seq)||'-MAY-2004','DD-MON-YYYY'),'ddspth'))||' Reminder', 
    27, INITCAP(TO_CHAR(TO_DATE(TO_CHAR(reminder_seq)||'-MAY-2004','DD-MON-YYYY'),'ddspth'))||' Reminder', 
    28, INITCAP(TO_CHAR(TO_DATE(TO_CHAR(reminder_seq)||'-MAY-2004','DD-MON-YYYY'),'ddspth'))||' Reminder', 
    29, INITCAP(TO_CHAR(TO_DATE(TO_CHAR(reminder_seq)||'-MAY-2004','DD-MON-YYYY'),'ddspth'))||' Reminder', 
    30, INITCAP(TO_CHAR(TO_DATE(TO_CHAR(reminder_seq)||'-MAY-2004','DD-MON-YYYY'),'ddspth'))||' Reminder', 
       'Reminded') FROM DUAL) reminder_type 
FROM reminders;&lt;/pre&gt;

&lt;p&gt;What a beauty!  It works as follows:&lt;/p&gt;
&lt;p&gt;1) Use a DECODE to determine what the number is.  Note that 2 is treated as a special case, even though it ends up the same as all the "other" numbers above 30.&lt;/p&gt;
&lt;p&gt;2) For numbers between 3 and 30:&lt;/p&gt;
&lt;p&gt;2.1) Convert to a string&lt;/p&gt;
&lt;p&gt;2.2) Concatenate with '-MAY-2004'&lt;/p&gt;
&lt;p&gt;2.3) Convert to a date&lt;/p&gt;
&lt;p&gt;2.4) Convert back to a string using the 'ddspth' format mask&lt;/p&gt;
&lt;p&gt;2.5) Convert to Init Caps&lt;/p&gt;
&lt;p&gt;2.6) Append the word ' Reminder'&lt;/p&gt;
&lt;p&gt;3) Enclose the whole lot in a redundant "(SELECT ... FROM DUAL)" scalar subquery.&lt;/p&gt;

&lt;p&gt;Obviously, this saved the developer from the tiresome task of typing 'Third', 'Fourth', 'Fifth' etc.  And presumably he/she isn't aware of the CASE expression that could have reduced it to:&lt;/p&gt;

&lt;pre&gt;CREATE OR REPLACE VIEW reminders_view AS
SELECT reminder_id
, reminder_seq
, CASE WHEN reminder_seq = 1
           THEN 'No reminder'
       WHEN reminder_seq BETWEEN 3 AND 30
           THEN INITCAP(TO_CHAR(TO_DATE(TO_CHAR(reminder_seq)||'-MAY-2004','DD-MON-YYYY'),'ddspth'))||' Reminder'
       ELSE 'Reminded'
       END reminder_type 
FROM reminders;&lt;/pre&gt;

&lt;p&gt;(And why stop at 30 when May has 31 days?!)&lt;/p&gt;

&lt;p&gt;Well, it gave me a much needed laugh on a Friday afternoon, anyway.&lt;/p&gt;

&lt;p&gt;All names have been changed to protect the guilty.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-115107978478306186?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/115107978478306186/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=115107978478306186' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/115107978478306186'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/115107978478306186'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/06/that-reminds-me.html' title='That Reminds Me...'/><author><name>Tony Andrews</name><uri>http://www.blogger.com/profile/16750945985361011515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-114963520871593438</id><published>2006-06-06T23:20:00.000+01:00</published><updated>2006-11-15T20:55:15.146Z</updated><title type='text'>Why Machines Will Never Take Over The World</title><content type='html'>&lt;p&gt;It is a recurring theme in science fiction that as computers increase in power and sophistication, they may one day reach a point where they decide they can do better without us, and condemn us to lives suspended in racked pods with our brains plugged into a vast virtual world, or alternatively send increasingly resourceful and indestructable robots to hunt us down in our bunkers, while above ground survivors fight a desperate war for survival amidst the wreckage of civilisation.&lt;/p&gt;&lt;p&gt;If you find this vision of the future alarming, take heart in &lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=392707"&gt;this SQL query&lt;/a&gt;, which was generated by a machine. Not, perhaps, a Cyberdyne Systems T-800 or the Matrix Mainframe, but something called OLAP API. We don't know what that is either, but we can tell you that if any robot descended from it ever attempts to enslave humanity using a virtual world and an unfeasible pod system, rest assured that you will have time to get out of its way.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-114963520871593438?l=oracle-wtf.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://forums.oracle.com/forums/thread.jspa?threadID=392707' title='Why Machines Will Never Take Over The World'/><link rel='replies' type='application/atom+xml' href='http://oracle-wtf.blogspot.com/feeds/114963520871593438/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=114963520871593438' title='14 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114963520871593438'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114963520871593438'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/06/why-machines-will-never-take-over.html' title='Why Machines Will Never Take Over The World'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>14</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-114859070074625148</id><published>2006-05-25T21:51:00.000+01:00</published><updated>2006-05-25T23:21:52.786+01:00</updated><title type='text'>Dynstatic SQL...</title><content type='html'>&lt;p&gt;Here's &lt;a href="http://www.oracledba.co.uk"&gt;Connor&lt;/a&gt; again...&lt;/p&gt;

&lt;p&gt;Note that the following code has been "anonymised" to protect the guilty.&lt;/p&gt;

&lt;hr&gt;

&lt;pre&gt;procedure P is
begin
   ...
   ...
   execute immediate 'drop  table T';
   execute immediate 'create table T as select * from ......';
   ...
   ...
   ...
   for i in ( select * from T ) loop
        ...
        ...
   end loop;
end;
&lt;/pre&gt;

&lt;p&gt;Ah, a mix of dynamic and static references... Now how precisely did that compile? Nope, I'm not sure either.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-114859070074625148?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/114859070074625148/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=114859070074625148' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114859070074625148'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114859070074625148'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/05/dynstatic-sql.html' title='Dynstatic SQL...'/><author><name>OraWTFGuy</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-114858981528769442</id><published>2006-05-25T21:40:00.000+01:00</published><updated>2006-05-25T23:16:12.276+01:00</updated><title type='text'>If in doubt, test, test and test again</title><content type='html'>&lt;p&gt;Thanks to Rob Baillie for the following example...&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;I was glancing through some legacy code today, and came across this.&lt;/p&gt;

&lt;p&gt;It's funny how barnacles can accumulate when code changes over time.&lt;/p&gt;
&lt;pre&gt;            if r2.status_id = 3 then
                 v_gp := r2.rate;
            elsif r2.status_id in (11, 12) then
                if r2.type_id = 3 then
                    v_gp := r2.rate;
                else
                    v_gp := r2.rate;
                end if;
            else
                v_gp := r2.rate;
            end if;&lt;/pre&gt;

&lt;p&gt;Skip over the record being called r2 and work out what it actually does...&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-114858981528769442?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/114858981528769442/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=114858981528769442' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114858981528769442'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114858981528769442'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/05/if-in-doubt-test-test-and-test-again.html' title='If in doubt, test, test and test again'/><author><name>OraWTFGuy</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-114841454509636210</id><published>2006-05-23T21:02:00.000+01:00</published><updated>2006-05-25T23:12:10.066+01:00</updated><title type='text'>Code generation nonpareil</title><content type='html'>&lt;p&gt;We've all engaged in code generation of one sort or another.  For certain problems it's just the right, or perhaps the only tool.  But then your content management vendor starts to throw this sort of thing at your database...&lt;/p&gt;

&lt;pre&gt;OPEN p_cursor FOR
 'SELECT content_id, content_status
    FROM content
   WHERE content_type_id = 319
     AND content_id IN (
      51055 , 45531 , 42208 , 42911 , 46494 , 52898 , 44262 , 44312 , 47474 , 42792 ,
      45956 , 45109 , 53432 , 14936 , 29040 , 28779 , 53015 , 48366 , 53739 , 48565 ,
      47188 , 46573 , 43038 , 53534 , 51999 , 49731 , 52847 , 43883 , 41522 , 50804 ,
      49975 , 45729 , 53260 , 47658 , 41325 , 49454 , 41374 , 45328 , 51612 , 54347 ,
      50092 , 48147 , 42416 , 42570 , 49533 , 41948 , 51740 , 52973 , 42648 , 44867 ,
      48289 , 45943 , 49556 , 54550 , 46801 , 43628 , 40569 , 41576 , 46752 , 44982 ,
      42309 , 45146 , 47198 , 44993 , 47768 , 47060 , 46889 , 45651 , 47045 , 45830 ,
      41248 , 54370 , 43741 , 44183 , 28451 , 45094 , 54332 , 47030 , 42060 , 41293 ,
      48287 , 48012 , 47740 , 45688 , 43639 , 48484 , 47583 , 45304 , 51478 , 42633 ,
      40558 , 43793 , 41587 , 49407 , 28803 , 43272 , 46464 , 45602 , 43866 , 44521 ,
      41200 , 48044 , 46927 , 29186 , 45774 , 43722 , 45128 , 43398 , 47397 , 41670 ,
      51888 , 47534 , 29237 , 42486 , 53811 , 44704 , 46618 , 48994 , 44848 , 44573 ,
      52956 , 44487 , 42435 , 48164 , 43451 , 52031 , 51300 , 52595 , 53141 , 44032 ,
      50904 , 41477 , 42161 , 44622 , 52695 , 43838 , 44562 , 45373 , 44882 , 47247 ,
      42367 , 50921 , 46265 , 41933 , 48960 , 43143 , 43345 , 28412 , 48868 , 49005 ,
      43533 , 46953 , 52420 , 44017 , 49817 , 41490 , 41395 , 43027 , 47703 , 29064 ,
      41689 , 50564 , 44112 , 28957 , 29544 , 45223 , 43252 , 49699 , 47356 , 43565 ,
      53604 , 45478 , 29422 , 53041 , 45697 , 44054 , 42469 , 44035 , 48750 , 46667 ,
      50060 , 46698 , 48306 , 45849 , 45563 , 42452 , 45143 , 46110 , 47800 , 43076 ,
      41280 , 45862 , 41657 , 42114 , 47523 , 51841 , 45988 , 48023 , 47307 , 43203 ,
      53464 , 44202 , 47984 , 46218 , 45255 , 51412 , 52409 , 47442 , 45932 , 28269 ,
      43823 , 46835 , 47785 , 50968 , 46050 , 41916 , 47219 , 51772 , 41980 , 43377 ,
      43681 , 50007 , 43072 , 47150 , 45900 , 53376 , 54338 , 45360 , 49086 , 46520 ,
      47626 , 29529 , 50321 , 51982 , 53660 , 51644 , 42028 , 41901 , 53269 , 47995 ,
      43754 , 49163 , 46069 , 51213 , 53566 , 52304 , 49588 , 51134 , 45167 , 46447 ,
      42108 , 45570 , 29439 , 46091 , 44160 , 52227 , 47324 , 42256 , 51262 , 28854 ,
      43220 , 41363 , 45272 , 42097 , 46790 , 51102 , 50338 , 44149 , 49849 , 49375 ,
      41814 , 44738 , 54211 , 52712 , 54364 , 50283 , 54442 , 46863 , 48687 , 45178 ,
      28464 , 44084 , 47615 , 44504 , 50895 , 46231 , 45723 , 47753 , 47230 , 29600 ,
      43430 , 28764 , 41619 , 44217 , 43649 , 47502 , 41509 , 47425 , 42873 , 51814 ,
      41438 , 44925 , 15364 , 41539 , 50336 , 42777 , 42127 , 44967 , 46942 , 43578 ,
      46644 , 48887 , 52748 , 46904 , 42290 , 44000 , 45446 , 45967 , 46539 , 44361 ,
      52990 , 45341 , 42326 , 47952 , 49746 , 29512 , 45806 , 50252 , 48121 , 46981 ,
      29162 , 41702 , 48700 , 50692 , 49039 , 44689 , 51181 , 42988 , 41737 , 41782 ,
      54283 , 44796 , 42667 , 48793 , 42597 , 49195 , 46018 , 48070 , 42975 , 49264 ,
      43675 , 29478 , 51000 , 43287 , 49052 , 51589 , 42506 , 44301 , 44649 , 44908 ,
      48072 , 50857 , 46020 , 44067 , 42013 , 42091 , 43464 , 48578 , 54015 , 41412 ,
      51361 , 52509 , 47124 , 51316 , 44143 , 29724 , 52714 , 44638 , 46142 , 41459 ,
      42586 , 43919 , 48945 , 44346 , 49390 , 44822 , 46631 , 43107 , 43591 , 42144 ,
      29755 , 43662 , 47540 , 43808 , 45390 , 42223 , 42371 , 42551 , 47918 , 47337 ,
&lt;/pre&gt;

&lt;p&gt;For brevity's sake I'll skip the next 11,000 elements of the IN list.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-114841454509636210?l=oracle-wtf.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://oracle-wtf.blogspot.com/' title='Code generation nonpareil'/><link rel='replies' type='application/atom+xml' href='http://oracle-wtf.blogspot.com/feeds/114841454509636210/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=114841454509636210' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114841454509636210'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114841454509636210'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/05/code-generation-nonpareil.html' title='Code generation nonpareil'/><author><name>Scott Swank</name><uri>http://www.blogger.com/profile/01922902566871746635</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-114717397000745242</id><published>2006-05-09T11:14:00.000+01:00</published><updated>2006-05-09T12:38:53.156+01:00</updated><title type='text'>Oracle World Goes Sensible shock</title><content type='html'>&lt;p&gt;You may be wondering WTF happened to all the WTFs, and so are we. It seems the Oracle world has been going through a rather depressing sensible season recently, in which nobody &lt;a href="http://oracle-wtf.blogspot.com/2006/04/sp2-0552-bind-variable-not-declared.html"&gt;posts Pro*Ada code&lt;/a&gt; and wonders why it won't run at the SQL*Plus prompt, or suggests adding "&lt;tt&gt;&lt;a href="http://oracle-wtf.blogspot.com/2006/01/universal-sql-performance-improver.html"&gt;AND 1=1&lt;/a&gt;&lt;/tt&gt;" to any query to make it go faster. Even &lt;a href="http://oracle-wtf.blogspot.com/2006/01/integer-type-is-platform-independent.html"&gt;Mr Feuerstein&lt;/a&gt; seems to have deserted us.&lt;/p&gt;&lt;p&gt;Perhaps &lt;a href="http://mikerault.blogspot.com/2006/04/time-for-change.html" rel=nofollow&gt;Mike Ault's foray into international economics&lt;/a&gt; cheered some of us up. He proposed an ingenious regulatory system requiring (I think) US grain, medicine and other key exporters to adjust their prices in response to international oil market fluctuations, on the grounds that certain oil producers are not taking America seriously enough. Now that'll teach Johnny Foreigner a lesson. "It is time for America to get tough", he adds. Oh dear.&lt;/p&gt;&lt;p&gt;On a more conventional note, a Mr Sahil Malik &lt;a href="http://groups.google.com/group/comp.databases.oracle.server/browse_frm/thread/5eed0a5f4d6a59b4/84a71f19dc53e69a?q=shit&amp;rnum=1#84a71f19dc53e69a" rel=nofollow&gt;complained at great length on cdos&lt;/a&gt; about how hard it was to install 9i Personal Edition on his PC. At one point he fumed:&lt;/p&gt;&lt;blockquote&gt;Larry Ellison IMHO has only one business idea - "Defeat bill gates
and trap every programmer in matrix like pods powering oracle
databases". WHAT THE HECK !! Time he matured up a bit.&lt;/blockquote&gt;&lt;p&gt;I agree. Larry Ellison, if you're listening, you need to mature up a bit and forget the whole Matrix pod idea. We all know that ends badly.&lt;/p&gt;&lt;p&gt;Over on the &lt;a href="http://forums.oracle.com/forums/thread.jspa?messageID=1272886"&gt;OTN SQL Developer Forum&lt;/a&gt;, we were intrigued when one frustrated poster asked:&lt;/p&gt;&lt;blockquote&gt;I cannot find clustered option for the indexes or PKs that I create in SQL Developer.&lt;br&gt;&lt;br&gt;Where is the CLUSTERED check box in user interface?&lt;/blockquote&gt;&lt;p&gt;Where indeed? Helpfully, Sharon from the SQL Developer team promised to get one added ASAP:&lt;/p&gt;&lt;blockquote&gt;I have added an enhancement request to get this added to the interface in a future release.&lt;/blockquote&gt;&lt;p&gt;We look forward to seeing what that does.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-114717397000745242?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/114717397000745242/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=114717397000745242' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114717397000745242'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114717397000745242'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/05/oracle-world-goes-sensible-shock.html' title='Oracle World Goes Sensible shock'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-114433440607650382</id><published>2006-04-06T14:44:00.000+01:00</published><updated>2006-08-10T22:38:13.550+01:00</updated><title type='text'>SP2-0552: Bind variable not declared</title><content type='html'>&lt;p&gt;Please help. Why does SQL*Plus keep giving me the error&lt;/p&gt;&lt;blockquote style="font-weight: bold;"&gt;SP2-0552: Bind variable "INTARRAY" not declared.&lt;/blockquote&gt;&lt;p&gt;Thanks in advance.&lt;/p&gt;&lt;pre&gt;DECLARE
    BatchSize : constant := 50;

    subtype IndexRanges is INTEGER range 1 .. BatchSize;
    type IntArrays is array( IndexRanges) of INTEGER;
    IntArray : IntArrays;

    EXEC SQL DECLARE network_cursor CURSOR FOR
        select pal.provider_id from hold_provider_address_link pal;

    EXEC SQL OPEN network_cursor;

-- establish a local block, with an exception to
-- handle the "no data found" condition
begin
    EXEC SQL WHENEVER NOT FOUND raise NO_MORE_DATA;
    FETCH_LOOP:
    loop -- fetch the data, 20 rows at a time
        EXEC SQL FETCH network_cursor
        INTO :IntArray;

        for I in 1..20 loop
            -- process batches of 20 rows
            ...
        end loop;

        commit;
    end loop FETCH_LOOP;

exception
    -- the exception NO_MORE_DATA is raised when there is
    -- no more data to FETCH
    when NO_MORE_DATA =&gt;
        PUT("No more data to fetch. N of rows fetched was ");
        PUT(ORACLE.SQLROWS);
        NEW_LINE;

        -- turn off the error handling
        EXEC SQL WHENEVER NOT FOUND CONTINUE;
end;
/&lt;/pre&gt;&lt;p&gt;I mentioned this in a comment the other day so apologies if you've seen it before, but I felt it really deserved its own post.&lt;/p&gt;&lt;p&gt;(Hint: SP errors are from SQL*Plus, and INTARRAY is  a bind variable from SQL*Plus's point of view because it begins with ":")&lt;/p&gt;&lt;p&gt;By the way I don't mean to laugh too much at the poor guy who posted this problem on a forum, as from his other posts he seems to have had a crappy application dumped on him without much support from anyone at his company. I did ask him what language it was written in but he hasn't replied. Suggestions, anyone? (My guess is Pro*Ada, which in my opinion we don't see enough of these days.)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-114433440607650382?l=oracle-wtf.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://forums.oracle.com/forums/thread.jspa?threadID=374064' title='SP2-0552: Bind variable not declared'/><link rel='replies' type='application/atom+xml' href='http://oracle-wtf.blogspot.com/feeds/114433440607650382/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=114433440607650382' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114433440607650382'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114433440607650382'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/04/sp2-0552-bind-variable-not-declared.html' title='SP2-0552: Bind variable not declared'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-114356089802192108</id><published>2006-03-28T16:32:00.000+01:00</published><updated>2006-03-28T18:16:01.583+01:00</updated><title type='text'>A Thneed's a Fine-Something-That-All-People-Need!</title><content type='html'>&lt;p&gt;Now maybe I'm misusing this whole forum with this posting, and if so I apologise profusely,  but...&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.janus-software.com/fb_fyracle.html" rel=nofollow&gt;www.janus-software.com/fb_fyracle.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Are you worried about "under-licencing" too...?&lt;/p&gt;

&lt;p&gt;Not only does open source Firebird-Fyracle have a catchy name and almost match Oracle on the 6 well known "gold standard key database evaluation mapping criteria",  but it is "just as idiosyncratic",  AND you can run "Compiere v2.5.3c" ( almost )!&lt;/p&gt;

&lt;p&gt;Who could possibly argue with the rigorously documented "proof of the pudding" that this product is "faster than Oracle on the same hardware"&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-114356089802192108?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/114356089802192108/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=114356089802192108' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114356089802192108'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114356089802192108'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/03/thneeds-fine-something-that-all-people.html' title='A Thneed&apos;s a Fine-Something-That-All-People-Need!'/><author><name>Adrian</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-114345301901214494</id><published>2006-03-27T10:43:00.000+01:00</published><updated>2006-03-27T10:50:19.026+01:00</updated><title type='text'>The Clue Was In The Name</title><content type='html'>&lt;pre&gt;email from tester: &lt;/pre&gt;
This bug is blocking test:  bg9876-a, I have elevated it to priority 1.

&lt;pre&gt;reply: &lt;/pre&gt;
The bug you've raised says "please provide a version of write_transaction() stored procedure, that doesn't write anything to the database",  can you explain where you're going with this?

&lt;pre&gt;email from tester: &lt;/pre&gt; 
It is a question of practicality for us, we have used this method in every release, we need to test high throughput rates without a Performance Oracle server.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-114345301901214494?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/114345301901214494/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=114345301901214494' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114345301901214494'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114345301901214494'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/03/clue-was-in-name.html' title='The Clue Was In The Name'/><author><name>Adrian</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-114332264325895814</id><published>2006-03-25T21:35:00.000Z</published><updated>2006-03-25T21:40:25.443Z</updated><title type='text'>ORA-06553: PLS-906: Compilation is not possible</title><content type='html'>&lt;p&gt;Or in &lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=374023"&gt;this case&lt;/a&gt; posted on the OTN Forums, is it even desirable. It's nice to see there is the ability for the database to simply say, "I'm sorry but this code is too stupid to run".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-114332264325895814?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/114332264325895814/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=114332264325895814' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114332264325895814'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114332264325895814'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/03/ora-06553-pls-906-compilation-is-not.html' title='ORA-06553: PLS-906: Compilation is not possible'/><author><name>3360</name><uri>http://www.blogger.com/profile/15154122363413824960</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-114287155052034906</id><published>2006-03-20T15:49:00.000Z</published><updated>2006-03-20T16:24:15.513Z</updated><title type='text'>The Decibel Method</title><content type='html'>&lt;p&gt;A poster on the hardcore &lt;a href="http://groups.google.com/group/comp.databases.oracle.server/browse_frm/thread/95ff418b73175c40/1449a9dc6ad09365?lnk=raot&amp;hl=en#1449a9dc6ad09365"&gt;comp.databases.oracle.server&lt;/a&gt; newsgroup had some tables in the production database that he felt were redundant, and asked, not unreasonably I felt, whether there was a way to tell from his Developer 6i application whether they were in fact in use:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;hello&lt;/p&gt;
&lt;p&gt;we are using oracle 9i production database and d2k 6i applications.
is there any way by which i can find the tables/ columns that are not
in used by applications. So that i can move them out from our
production database.&lt;/p&gt;
&lt;p&gt;can anyone throw some light how to do it.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;After the obligatory initial responses along the lines of &lt;i&gt;"it can't be done"&lt;/i&gt; and &lt;i&gt;"you are an idiot for even thinking about it"&lt;/i&gt; (you take your life in your hands when you post on cdos), one respondent begins,&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;For tables, the solution is called "auditing". You can audit desired
objects.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Reasonable enough. Give it a year, then if nobody has used the tables, they are probably not so important. Then he continues:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;For columns, you should be using so called decibel method:
if you suspect that column C1 in table TAB is not used, you can always
execute the following commands:&lt;p&gt;
&lt;pre&gt;update TAB set C1=NULL;
commit;&lt;/pre&gt;
&lt;p&gt;If the reaction to that is a loud scream, accompanied by swearwords and
a genuine cornucopia of various expletives, you've made a mistake, the
column was used. It's time for the "I'm sorry, I didn't know that this
column was still being used" routine. You can rest assured that this
swearing sucker is gonna be busy for a while.&lt;/p&gt;
&lt;p&gt;If not, you can proceed and drop the column. The previous update has an
added benefit of making "drop column" operation faster. It will also
expose weak points in all those lousy applications that use "select *" and
expect the table to populate all of their variables.&lt;/p&gt;
&lt;p&gt;An alternative to the decibel method is fine-grain auditing, described in
the books by D. Knox. It's much more tedious and requires much larger
knowledge then the decibel method, which is also a lot of fun.&lt;/blockquote&gt;&lt;/p&gt;
&lt;p&gt;Problem solved I think.&lt;/p&gt;
&lt;p&gt;Our thanks to &lt;a href="http://www.blogger.com/profile/20151959"&gt;Herod T&lt;/a&gt; for the plug.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-114287155052034906?l=oracle-wtf.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://groups.google.com/group/comp.databases.oracle.server/browse_frm/thread/95ff418b73175c40/1449a9dc6ad09365?lnk=raot&amp;hl=en#1449a9dc6ad09365' title='The Decibel Method'/><link rel='replies' type='application/atom+xml' href='http://oracle-wtf.blogspot.com/feeds/114287155052034906/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=114287155052034906' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114287155052034906'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114287155052034906'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/03/decibel-method.html' title='The Decibel Method'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-114260581603484579</id><published>2006-03-17T14:29:00.000Z</published><updated>2006-03-17T14:37:31.526Z</updated><title type='text'>If only there was a SUM function</title><content type='html'>&lt;p&gt;...then we wouldn't have to write code like this, which, as &lt;b&gt;Graham Oakes&lt;/b&gt; can confirm, takes ages:&lt;/p&gt;
&lt;pre&gt;FOR r IN ( SELECT tid FROM t_brel WHERE bqid = iqid )
LOOP
    SELECT q.lamount, q.famount
    INTO   v_lamount, v_famt
    FROM   t_aq   atq
         , t_q    q
    WHERE  atq.tid = r.tid
    AND    q.qid = atq.qid
    AND    qtype = 10;

    v_ltotal := v_ltotal + v_lamount;
    v_ftotal := v_ftotal + v_famt;
END LOOP;

UPDATE t_q
SET    lamount = v_ltotal
     , famount = v_ftotal
WHERE  qid = iqid; &lt;/pre&gt;
&lt;p&gt;We can but dream.&lt;/p&gt;
&lt;p&gt;While we're on the subject, we received this from a correspondent who wishes to remain anonymous:&lt;/p&gt;
&lt;pre&gt;FOR r IN
(
    SELECT /*+ FIRST_ROWS */
           *
    FROM   pay_details
    WHERE  acct_fk = p_accountpk
)
LOOP
    DELETE pay_details
    WHERE  primarykey = r.primarykey;

    COMMIT;
END LOOP;&lt;/pre&gt;
&lt;p&gt;I particularly like the FIRST_ROWS hint. &lt;i&gt;"What, it's slow? Better make sure it uses that index..."&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-114260581603484579?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/114260581603484579/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=114260581603484579' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114260581603484579'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114260581603484579'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/03/if-only-there-was-sum-function_17.html' title='If only there was a SUM function'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-114204126519249103</id><published>2006-03-11T01:31:00.000Z</published><updated>2006-03-11T01:54:07.250Z</updated><title type='text'>Simplest row generator meets maximum inefficiency</title><content type='html'>&lt;p&gt;
Generating a set of values that are not stored in a table is a reasonably common problem. I recently came across this solution for a set of irregular interval values.

&lt;pre&gt;
 OPEN cur_rows FOR
   'SELECT 3  FROM dual UNION '||
   'SELECT 6  FROM dual UNION '||
   'SELECT 9  FROM dual UNION '||
   'SELECT 12  FROM dual UNION '||
   'SELECT 24  FROM dual UNION '||
   'SELECT 36  FROM dual';
 LOOP
    FETCH cur_rows INTO v_num_value;
    EXIT WHEN cur_rows%NOTFOUND;&lt;/pre&gt;

I didn't know which to admire the most. The clever use of dynamic SQL or the sort distinct to get rid of any duplicate literals that may occur from accidentally typing the same line twice. I think the latter wins for being also &lt;a href="http://oracle-wtf.blogspot.com/2006/02/tip-add-distinct-to-every-query.html"&gt;relationally pure&lt;/a&gt; apparently.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-114204126519249103?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/114204126519249103/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=114204126519249103' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114204126519249103'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114204126519249103'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/03/simplest-row-generator-meets-maximum.html' title='Simplest row generator meets maximum inefficiency'/><author><name>3360</name><uri>http://www.blogger.com/profile/15154122363413824960</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-114199198683276791</id><published>2006-03-10T11:45:00.000Z</published><updated>2006-03-10T23:15:26.000Z</updated><title type='text'>Umm, I forgot my password, Part 2</title><content type='html'>&lt;p&gt;In &lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=368215"&gt;a thread on OTN forums&lt;/a&gt;, a poster asked how he could recover a user's password. Naturally he was told that it can't be done because the password itself is not stored, only a hash based on the username and password combination.&lt;/p&gt;&lt;p&gt;After some interesting discussion of password hashing, brute force and rainbow table attacks and the like, a poster makes the following rather novel suggestion:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;if you apply the password verify function, yes it is possible to get the password of a user.&lt;/p&gt;

&lt;p&gt;Etape 1: edit the utlpwdmg.sql script and add the line which is in bold (insert into...)&lt;/p&gt;

&lt;p&gt;-- Check if the password is same as the username&lt;/p&gt;
&lt;p&gt;&lt;tt&gt;IF NLS_LOWER(password) = NLS_LOWER(username) THEN&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;raise_application_error(-20001, 'Password same as or similar to user');&lt;br&gt;
END IF;&lt;/tt&gt;&lt;/p&gt;

&lt;p&gt;&lt;tt&gt;&lt;b&gt;insert into mytable values ('username','password');&lt;/b&gt;&lt;/tt&gt;&lt;/p&gt;

-- Check for the minimum length of the password

&lt;p&gt;Etape 2: run this script as sys&lt;/p&gt;

&lt;p&gt;Etape 3: grant the profile to user whom u want to get the password.&lt;/p&gt;

&lt;p&gt;u will be able to get the new password by consulting the table mytable (u must create this table)&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;This had me puzzled at first, and I had to check what &lt;a href="http://download-uk.oracle.com/docs/cd/B10501_01/server.920/a96536/ch53.htm#1005955"&gt;$ORACLE_HOME/rdbms/admin/utlpwdmg.sql&lt;/a&gt; did. In fact it creates a default password verification function called "verify_function" ("verify_password" might have made a better name, but that's obfuscation for you), and then assigns it to the default profile using &lt;tt&gt;ALTER PROFILE DEFAULT ... PASSWORD_VERIFY_FUNCTION verify_function;&lt;/tt&gt;
&lt;p&gt;This means that any attempt to change the password for a user with the default profile (see &lt;a href="http://download-uk.oracle.com/docs/cd/B10501_01/server.920/a96540/statements_44a.htm#2058358"&gt;ALTER USER&lt;/a&gt; examples in the documentation), will automatically execute &lt;tt&gt;verify_function(username, password, old_password)&lt;/tt&gt;. The idea is to apply some rules to prevent easily guessed passwords such as &lt;a href="http://oracle-wtf.blogspot.com/2006/03/umm-i-forgot-my-password.html"&gt;your username&lt;/a&gt;, but Mouhamadou's ingenious addition is his extra line,&lt;/p&gt;&lt;pre&gt;insert into mytable values (username,password);&lt;/pre&gt;&lt;p&gt;Now any attempt to change the password for a user with the default profile that successfully passes this extra security step &lt;i&gt;&lt;b&gt;will result in the new password being logged in &lt;tt&gt;mytable&lt;/tt&gt; in clear text.&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;As we like to say on Oracle WTF, problem solved.&lt;/p&gt;
&lt;p&gt;Many thanks to Andrew P. Clarke for submitting this.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-114199198683276791?l=oracle-wtf.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://forums.oracle.com/forums/thread.jspa?threadID=368215' title='Umm, I forgot my password, Part 2'/><link rel='replies' type='application/atom+xml' href='http://oracle-wtf.blogspot.com/feeds/114199198683276791/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=114199198683276791' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114199198683276791'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114199198683276791'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/03/umm-i-forgot-my-password-part-2.html' title='Umm, I forgot my password, Part 2'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-114200121756541536</id><published>2006-03-09T21:30:00.000Z</published><updated>2006-03-10T15:15:39.303Z</updated><title type='text'>What is it with dates?</title><content type='html'>&lt;p&gt;What exactly is it with dates that so many Oracle developers struggle with? Why do they go to such lengths to avoid using the DATE type? Why, if DATE validation or arithmetic is required, would they use CHARs or NUMBERs? Abuses of DATEs seems to be a recurring theme on Oracle WTF. Indeed, here's another good example kindly provided by Graham Oakes.&lt;/p&gt;

&lt;p&gt;Over to Graham...&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;This is a cracker, the easy way to check the supplied date in a string (after all who actually wants to use date types) is a valid date.&lt;/p&gt;

&lt;pre&gt;IF to_number(substr(v_valuedate,3,2)) NOT BETWEEN 1 AND 12
THEN
    v_rowstatustype := -190;
ELSE
    -- check 31 day months
    IF substr(v_valuedate,3,2) IN ('01','03','05','07','08','10','12')
    THEN
        IF to_number(substr(v_valuedate,1,2)) &gt; 31
        THEN
            v_rowstatustype := -200;
        END IF;

    -- check 30 day months
    ELSIF substr(v_valuedate,3,2) IN ('04','06','09','11')
    THEN
        IF to_number(substr(v_valuedate,1,2)) &gt; 30
        THEN
            v_rowstatustype := -200;
        END IF;

    -- check leap year feb
    ELSIF substr(v_valuedate,3,2) = '02'
          AND MOD(to_number(substr(v_valuedate,5,4)),4) = 0
    THEN
        IF to_number(substr(v_valuedate,1,2)) &gt; 29
        THEN
            v_rowstatustype := -200;
        END IF;

    -- check non-leap year feb
    ELSIF substr(v_valuedate,3,2) = '02'
          AND MOD(to_number(substr(v_valuedate,5,4)),4) != 0
    THEN
        IF to_number(substr(v_valuedate,1,2)) &gt; 28
        THEN
            v_rowstatustype := -200;
        END IF;
    END IF;
END IF;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-114200121756541536?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/114200121756541536/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=114200121756541536' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114200121756541536'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114200121756541536'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/03/what-is-it-with-dates_09.html' title='What is it with dates?'/><author><name>OraWTFGuy</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-114175479415999354</id><published>2006-03-07T16:59:00.000Z</published><updated>2006-09-11T23:38:58.076+01:00</updated><title type='text'>Create Your Own DUAL Table</title><content type='html'>&lt;p&gt;If you want to retrieve a sequence value into a PL/SQL variable, you have to SELECT FROM DUAL. (Or use RETURNING INTO of course, but never mind that now.)&lt;/p&gt;&lt;p&gt;According to some, this is not only an inconvenient restriction, but also prone to failure if SYS.DUAL contains more than one row.&lt;/p&gt;&lt;p&gt;Help is at hand in the form of the utility below, which solves both problems at once by installing a table, a public synonym, a trigger and a function. Now your application will never again be unable to retrieve sequence values directly into PL/SQL variables on days when DUAL contains more than one row. So that's one less thing to worry about.&lt;/p&gt;&lt;pre&gt;CREATE OR REPLACE PROCEDURE replace_onerow (
 table_name_in IN VARCHAR2
)
IS
BEGIN
 BEGIN
    EXECUTE IMMEDIATE 'DROP TABLE ' || table_name_in;
 EXCEPTION
    WHEN OTHERS THEN NULL;
 END;

 EXECUTE IMMEDIATE 'CREATE TABLE '
                   || table_name_in
                   || ' (dummy VARCHAR2(1))';

 EXECUTE IMMEDIATE
    'CREATE OR REPLACE TRIGGER onerow_' || table_name_in ||
    '  BEFORE INSERT
       ON ' || table_name_in || '
    DECLARE
       PRAGMA AUTONOMOUS_TRANSACTION;
       l_count PLS_INTEGER;
    BEGIN
       SELECT COUNT (*)
       INTO   l_count
       FROM   ' || table_name_in || ';

       IF l_count = 1
       THEN
          raise_application_error
          ( -20000
          , ''The ' || table_name_in || ' table can only have one row.'' );
       END IF;
    END;';

 EXECUTE IMMEDIATE 'BEGIN INSERT INTO '
                   || table_name_in
                   || ' VALUES (''X''); COMMIT; END;';

 EXECUTE IMMEDIATE 'GRANT SELECT ON '
                   || table_name_in
                   || ' TO PUBLIC';

 EXECUTE IMMEDIATE 'CREATE PUBLIC SYNONYM '
                   || table_name_in
                   || ' FOR '
                   || table_name_in;

 EXECUTE IMMEDIATE
    'CREATE OR REPLACE FUNCTION next_pky (seq_in IN VARCHAR2)
        RETURN PLS_INTEGER AUTHID CURRENT_USER
     IS
        retval PLS_INTEGER;
     BEGIN
        EXECUTE IMMEDIATE ''SELECT '' || seq_in
                      || ''.NEXTVAL FROM ' || table_name_in ||
                      '|| ''INTO retval;
        RETURN retval;
     END next_pky;';

END replace_onerow;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-114175479415999354?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/114175479415999354/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=114175479415999354' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114175479415999354'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114175479415999354'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/03/create-your-own-dual-table.html' title='Create Your Own DUAL Table'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-114173944597172749</id><published>2006-03-07T13:42:00.000Z</published><updated>2006-03-07T13:50:45.986Z</updated><title type='text'>Error-Prone Error Handling</title><content type='html'>A colleague found this handy utility on the internet.  The idea is that whenever you get an Oracle error, the errant SQL statement will be written away to a table along with the message for you to read and enjoy at your leisure.  Which would be fine I suppose, if it didn't introduce a whole lot of errors of its own.
&lt;pre&gt;create table caught_errors (
  dt        date,               
  username  varchar2( 30), -- value from ora_login_user
  msg       varchar2(512),
  stmt      varchar2(512)
);

create or replace trigger catch_errors
   after servererror on database
declare
   sql_text ora_name_list_t;
   msg_     varchar2(2000) := null;
   stmt_    varchar2(2000) := null;
begin

  for depth in 1 .. ora_server_error_depth loop
    msg_ := msg_ || ora_server_error_msg(depth);
  end loop;

  for i in 1 .. ora_sql_txt(sql_text) loop
     stmt_ := stmt_ || sql_text(i);
  end loop;

  insert into 
    caught_errors (dt     , username      ,msg ,stmt )
           values (sysdate, ora_login_user,msg_,stmt_);
end;
/&lt;/pre&gt;
&lt;p&gt;Note that whenever a SQL error occurs on the database this trigger will fire and:&lt;/p&gt;
&lt;p&gt;1) try to stuff the entire SQL statement that failed into a varchar2(2000),
regardless of how big it actually is&lt;/p&gt;
&lt;p&gt;2) if that doesn't blow up, then tries to insert the same value into a varchar2(255) column&lt;/p&gt;

&lt;p&gt;In SQL Plus, this leads to errors like this (using an invalid table name in a
large SELECT statement):&lt;/p&gt;

&lt;pre&gt;ERROR at line 30:
ORA-00604: error occurred at recursive SQL level 1
ORA-01401: inserted value too large for column
ORA-06512: at line 12
ORA-00942: table or view does not exist&lt;/pre&gt;

&lt;p&gt;... which is clearly more informative than:&lt;/p&gt;

&lt;pre&gt;ERROR at line 30:
ORA-00942: table or view does not exist&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-114173944597172749?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/114173944597172749/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=114173944597172749' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114173944597172749'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114173944597172749'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/03/error-prone-error-handling.html' title='Error-Prone Error Handling'/><author><name>Tony Andrews</name><uri>http://www.blogger.com/profile/16750945985361011515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-114122305422730662</id><published>2006-03-01T13:47:00.000Z</published><updated>2006-03-01T14:24:17.686Z</updated><title type='text'>Umm, I forgot my password</title><content type='html'>&lt;p&gt;Probem solved, with the following convenient password reset procedure found in a large production database, with &lt;tt&gt;EXECUTE&lt;/tt&gt; granted to &lt;tt&gt;PUBLIC&lt;/tt&gt; and a handy public synonym:
&lt;/p&gt;&lt;pre&gt;CREATE OR REPLACE PROCEDURE reset_user_password(p_username IN VARCHAR2)
AS
BEGIN
   execute immediate 'ALTER USER '||upper(p_username)||' IDENTIFIED BY '||upper(p_username);
END;
/&lt;/pre&gt;Many thanks to Robert De Laat for this submission.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-114122305422730662?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/114122305422730662/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=114122305422730662' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114122305422730662'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114122305422730662'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/03/umm-i-forgot-my-password.html' title='Umm, I forgot my password'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-114111461601957950</id><published>2006-02-27T20:30:00.000Z</published><updated>2006-02-28T08:19:29.426Z</updated><title type='text'>Hey, we do the WTFs Part II...</title><content type='html'>At this rate, we might need to make Connor an honorary member. Here's &lt;a href="http://www.oracledba.co.uk/tips/worst_plsql.htm"&gt;another gem &lt;/a&gt;from his &lt;a href="http://www.oracledba.co.uk/"&gt;web site &lt;/a&gt;that he's picked up on his travels. PL/SQL doesn't get much "better" than this...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-114111461601957950?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/114111461601957950/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=114111461601957950' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114111461601957950'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114111461601957950'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/02/hey-we-do-wtfs-part-ii.html' title='Hey, we do the WTFs Part II...'/><author><name>OraWTFGuy</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-114094797299871909</id><published>2006-02-26T08:48:00.000Z</published><updated>2006-02-26T18:06:37.380Z</updated><title type='text'>Tip: add DISTINCT to every query</title><content type='html'>&lt;p&gt;We all know that SQL can be a harsh mistress, and relational theorists such as Chris Date have long argued that the language is fundamentally flawed and that vendors have been misapplying relational theory from the start.&lt;/p&gt;&lt;p&gt;Now a Perl developer on perlmonks.org has been reading Date's book and finds that it explains all of his frustrations with databases. One tip for addressing their shortcomings is to add the handy &lt;tt&gt;DISTINCT&lt;/tt&gt; keyword to every single query, because stupid old SQL doesn't automatically apply the degree of uniqueness you might have in mind:&lt;/p&gt;

&lt;blockquote&gt;In fact, one of the founders of relational theory, C.J. Date, recommends that every SQL &lt;tt&gt;SELECT&lt;/tt&gt; statement be written as &lt;tt&gt;SELECT DISTINCT ...&lt;/tt&gt; Unfortunately, many folks get upset with this for a variety of reasons. First, DBMS do a horrible job of optimizing &lt;tt&gt;DISTINCT&lt;/tt&gt; queries. There are many cases where the &lt;tt&gt;DISTINCT&lt;/tt&gt; can be safely ignored but in practice, using &lt;tt&gt;DISTINCT&lt;/tt&gt; with large sets of data and complicated queries can have an abysmal impact on performance. I think this can be put into the "premature optimization" category, though. Until we know that &lt;tt&gt;DISTINCT&lt;/tt&gt; is causing an impact, isn't it better to improve the chance of getting correct results and worry about performance afterwards?&lt;/blockquote&gt;

&lt;p&gt;I had to read that a couple of times to realise that adding a &lt;tt&gt;DISTINCT&lt;/tt&gt; to every single query in the hope that it might mask some unknown deficiency in your model, your query, or the SQL language itself is not the "premature optimization" being referred to here - he means the idea that doing so might affect performance. After all, it might not, right?&lt;/p&gt;

&lt;p&gt;Read the rest of the discussion at perlmonks.org: &lt;a href="http://perlmonks.org/?node_id=515776" rel=nofollow&gt;"Why SQL Sucks (with a little Perl to fix it)"&lt;/a&gt;. It also appears on Database Debunkings, &lt;a href="http://www.dbdebunk.com/page/page/3010500.htm" rel=nofollow&gt;"On the sins of SQL"&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-114094797299871909?l=oracle-wtf.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://perlmonks.org/?node_id=515776' title='Tip: add DISTINCT to every query'/><link rel='replies' type='application/atom+xml' href='http://oracle-wtf.blogspot.com/feeds/114094797299871909/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=114094797299871909' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114094797299871909'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114094797299871909'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/02/tip-add-distinct-to-every-query.html' title='Tip: add DISTINCT to every query'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-114081518788101422</id><published>2006-02-24T20:59:00.000Z</published><updated>2006-02-24T21:07:46.336Z</updated><title type='text'>Hey, we do the WTFs...</title><content type='html'>I found &lt;a href="http://www.oracledba.co.uk/tips/bad_disable.htm"&gt;this beauty&lt;/a&gt; on Connor McDonald's &lt;a href="http://www.oracledba.co.uk"&gt;web site&lt;/a&gt;. It's perfect fodder for Oracle WTF and Connor is happy for us to include it here.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-114081518788101422?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/114081518788101422/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=114081518788101422' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114081518788101422'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114081518788101422'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/02/hey-we-do-wtfs.html' title='Hey, we do the WTFs...'/><author><name>OraWTFGuy</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-114081382558788801</id><published>2006-02-24T20:30:00.000Z</published><updated>2006-02-24T20:59:26.030Z</updated><title type='text'>Stop Press: Oracle Granted License To Extend February</title><content type='html'>Yes, it's official. Oracle has been granted permission to extend February by 3 days. Shame no-one told the developers responsible for INTERVAL arithmetic. &lt;p&gt;

&lt;pre&gt;
SQL&gt; SELECT DATE '2006-01-31' + INTERVAL '1' MONTH
  2  FROM   dual;
SELECT DATE '2006-01-31' + INTERVAL '1' MONTH
                           *
ERROR at line 1:
ORA-01839: date not valid for month specified
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-114081382558788801?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/114081382558788801/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=114081382558788801' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114081382558788801'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114081382558788801'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/02/stop-press-oracle-granted-license-to.html' title='Stop Press: Oracle Granted License To Extend February'/><author><name>OraWTFGuy</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-114031398787458803</id><published>2006-02-19T01:32:00.000Z</published><updated>2006-02-21T11:06:01.023Z</updated><title type='text'>Wanna Date?</title><content type='html'>&lt;p&gt;Dates are known to be exceedingly difficult and avoiding them at all costs is something of a skill. This function, in the spirit of &lt;a href="http://oracle-wtf.blogspot.com/2005/09/never-do-in-sql-what-you-can-do-in.html"&gt;Never do in SQL what you can do in PL/SQL&lt;/a&gt;, calculates a date range before calling another procedure that also avoided using dates for its input date parameters. So despite its absence, it is at least partially responsible for this mess.&lt;/p&gt;  &lt;p&gt;I stripped the code down to its date handling which studiously avoids using date calculations wherever possible, and uses string handling instead, leaving in the comments because they are also the documentation.&lt;/p&gt;  &lt;pre&gt;create or replace function start_date (
p_range         in      varchar2,
p_in_date       in      varchar2    -- DD-MON-YYYY format String
)
return varchar2
as
l_out_date varchar2(11);
month varchar2(10) := to_char(to_date(p_in_date,'DD-MON-YYYY'),'MON');
year varchar2(10)  := to_char(to_date(p_in_date,'DD-MON-YYYY'),'YYYY');
v_cnt_yr        number;
v_end_date      date    := to_date(p_in_date,'DD-MON-YYYY');
v_start_date    varchar2(11);
begin
if p_range = 'QTD' THEN

  if month in ('JAN','FEB','MAR') then
     -- if given month = march and date is 31
     -- then data for jan,feb and march.
     l_out_date := '01-JAN-'||year;
  elsif month in ('APR','MAY','JUN')  then
     l_out_date := '01-APR-'||year;
  elsif month in ('JUL','AUG','SEP')  then
     l_out_date := '01-JUL-'||year;
  elsif month in ('OCT','NOV','DEC')  then
     l_out_date := '01-OCT-'||year;
  end if;

elsif p_range = 'YTD' then

  -- beginning of the year.
   l_out_date := '01-JAN-'||year;

elsif p_range = 'M' or p_range='MTD' then

  -- beginning of month
   l_out_date := '01-'||month||'-'||year;

elsif p_range like 'B%' then
   v_cnt_yr     := substr(ltrim(rtrim(p_range)),2);
   -- We take the start date as the first day after trailing
   -- back the required no. of months
   l_out_date   := to_char(last_day(add_months(
                      last_day(v_end_date), -v_cnt_yr)) + 1,
                      'DD-MON-YYYY');
end if;
return l_out_date;
end;&lt;/pre&gt;  &lt;p&gt;After reading it I thought, "So what does this do that TRUNC doesn't?" Apparently not a lot when you need to get the month, quarter or year to date. If you try this at home remember to format the return of START_DATE for readability since it usefully returns a 4000 character string.&lt;/p&gt;&lt;p&gt;  &lt;/p&gt;&lt;pre&gt;SQL&gt; exec :d := '17-JUN-2006'

PL/SQL procedure successfully completed.

SQL&gt; select start_date('QTD',:d) start_date,
2    trunc(to_date(:d),'Q') from dual;

START_DATE  TRUNC(TO_DA
----------- -----------
01-APR-2006 01-APR-2006

SQL&gt; select start_date('YTD',:d) start_date,
2    trunc(to_date(:d),'Y') from dual;

START_DATE  TRUNC(TO_DA
----------- -----------
01-JAN-2006 01-JAN-2006

SQL&gt; select start_date('MTD',:d) start_date,
2    trunc(to_date(:d),'MM') from dual;

START_DATE  TRUNC(TO_DA
----------- -----------
01-JUN-2006 01-JUN-2006&lt;/pre&gt;  &lt;p&gt;But what about the mysterious 'B%' format mask? This calculates the first day of the month, where 'Bn' is n-1 months ago, tricky eh? In SQL we are forced to call two functions instead of having START_DATE call ADD_MONTHS for us with two bonus LAST_DAYS thrown in for good measure. The n-1 bit could even be a bug but who knows?&lt;/p&gt;   &lt;pre&gt;SQL&gt; select start_date('B12',:d) start_date,
2    trunc(add_months(to_date(:d),-11),'MM') from dual;

START_DATE  TRUNC(ADD_M
----------- -----------
01-JUL-2005 01-JUL-2005&lt;/pre&gt;   &lt;p&gt;The convenience obviously outweighs the problem of having to deal with an undocumented date function that accepts and returns strings. Also with this function I have the luxury of substituting 'M' for 'MTD', but not 'Y' for 'YTD' or 'Q' for 'QTD' though I suspect these could be improvements for versions 2.0 and 3.0.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-114031398787458803?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/114031398787458803/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=114031398787458803' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114031398787458803'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/114031398787458803'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/02/wanna-date.html' title='Wanna Date?'/><author><name>3360</name><uri>http://www.blogger.com/profile/15154122363413824960</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-113995027669122293</id><published>2006-02-14T20:44:00.000Z</published><updated>2006-02-14T20:51:16.710Z</updated><title type='text'>The Phantom's Gonna Git Ya</title><content type='html'>I know I'm asking for trouble here by offering an &lt;a href="http://asktom.oracle.com/pls/ask/f?p=4950:8:::::F4950_P8_DISPLAYID:854500633682"&gt;AskTom page&lt;/a&gt; for a WTF, but I couldn't resist. If there was ever a time you wanted your spelling to be spot on, it would be when posting a link to a spell-checker...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-113995027669122293?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/113995027669122293/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=113995027669122293' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113995027669122293'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113995027669122293'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/02/phantoms-gonna-git-ya.html' title='The Phantom&apos;s Gonna Git Ya'/><author><name>OraWTFGuy</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-113951132409098769</id><published>2006-02-09T18:25:00.000Z</published><updated>2006-02-10T23:14:33.296Z</updated><title type='text'>EAV Returns: The Concrete Elephant approach</title><content type='html'>&lt;p&gt;Anyone who has read &lt;a href="http://www.apress.com/book/bookDisplay.html?bID=314"&gt;Tales Of The Oak Table&lt;/a&gt;, not to mention &lt;a href="http://tonyandrews.blogspot.com/2004/10/otlt-and-eav-two-big-design-mistakes.html"&gt;Tony Andrews' blog&lt;/a&gt; or any of the countless articles and discussions on the subject on &lt;a href="http://asktom.oracle.com/pls/ask/f?p=4950:8:::::F4950_P8_DISPLAYID:10678084117056"&gt;AskTom&lt;/a&gt; and elsewhere, will know two things about the fabled "Entity-Attribute-Value" approach to database design, in which you model all "things" in one table with a "thing ID" and a "thing type", plus a second table holding one row per "attribute", and thus create an application that can model any conceivable type of thing, ever:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It seems like a clever idea at first.&lt;/li&gt;
&lt;li&gt;It isn't.&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;But wait. A poster on OTN forums ("&lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=360066&amp;start=0&amp;tstart=0"&gt;SIMPLE Database Design Problem&lt;/a&gt;") has solved the major problems inherent in the original Entity-Attribute-Value approach, by simply denormalising away the Attribute-Value part.&lt;/p&gt;
&lt;p&gt;Now the &lt;tt&gt;ENTITIES&lt;/tt&gt; table will have all the columns for every entity type. Maybe a lot of them will be null because "INVOICE" rows will use mainly different columns to "TROPICAL_DISEASE" rows, but disk space is cheap, and look at the simplification we have achieved by not having to babysit all those old-fashioned tables. And it's not a generic design any more, is it? It's concrete.&lt;/p&gt;

&lt;p&gt;The table would look something like this:&lt;/p&gt;

&lt;pre&gt;ENTITYID ENTITYTYPE NAME      PRICE DIET  COLOUR ANNUAL_TURNOVER
-------- ---------- --------- ----- ----- ------ ---------------
1        PERSON     William
2        FRUIT      Banana                Yellow
3        COMPANY    Megacorp                     100000000
4        ANIMAL     Fruitbat        Fruit
5        SNACK      Snickers  0.4&lt;/pre&gt;

&lt;p&gt;accompanied by a generic RELATIONS table like this:&lt;/p&gt;
&lt;pre&gt;ENTITY1 ENTITY2 RELATIONSHIP
------- ------- ------------
3       1       EMPLOYS
1       2       EATS
1       5       EATS&lt;/pre&gt;

&lt;p&gt;Want to list the snacks eaten by Megacorp employees? Simple:&lt;/p&gt;

&lt;pre&gt;SELECT emp.entityid, emp.name, snack.name, snack.price
FROM   entities emp
       JOIN relations emprel
       ON  emprel.entity2 = emp.entityid
       AND emprel.relationship = 'EMPLOYS'
 
       JOIN entities com
       ON com.entityid = emprel.entity1
       AND com.entitytype = 'COMPANY'
 
       JOIN relations snrel
       ON  snrel.entity1 = emp.entityid
       AND snrel.relationship = 'EATS'
 
       JOIN entities snack
       ON  snack.entityid = snrel.entity2
       AND snack.entitytype = 'SNACK'
 
WHERE  emp.entitytype = 'PERSON'
AND    com.name = 'Megacorp';&lt;/pre&gt;
&lt;p&gt;Want to make &lt;tt&gt;FRUITBAT&lt;/tt&gt; an employee of &lt;tt&gt;SNICKERS&lt;/tt&gt;?&lt;/p&gt;

&lt;pre&gt;INSERT INTO relations VALUES (5, 4, 'EMPLOYS');&lt;/pre&gt;

&lt;p&gt;The thread becomes increasingly surreal as more and more posters suggest likely issues, from performance (he's prototyped it and the slowdown is insignificant) to complexity (the code will be generated dynamically from an object library) and the limited number of columns per table in Oracle (he might go with MySQL) while Erdem  remains cheerfully confident that it will work (it won't).&lt;/p&gt;
&lt;p&gt;My thanks to 3360 for sharing this. Send your WTFs to us at &lt;a href="mailto:OracleWTF@bigfoot.com?subject=Oracle-WTF"&gt;OracleWTF@bigfoot.com&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-113951132409098769?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/113951132409098769/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=113951132409098769' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113951132409098769'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113951132409098769'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/02/eav-returns-concrete-elephant-approach.html' title='EAV Returns: The Concrete Elephant approach'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-113923526966829029</id><published>2006-02-06T14:01:00.000Z</published><updated>2006-02-06T14:17:26.800Z</updated><title type='text'>Counting Sheep</title><content type='html'>I'd not seen &lt;a href="http://forums.oracle.com/forums/thread.jspa?threadID=66144&amp;start=0&amp;tstart=0"&gt;this Oracle Forums thread&lt;/a&gt; before, though it started in 2002 and now has 198 replies.

Somebody once asked for some PL/SQL coding standards, someone else offered to email some, and then for ever after gets bombarded with requests from other people saying "Please send same to me at another-idiot-sheep@nobrain.com"

Every now and then someone kindly posts a URL to some PL/SQL standards on the web, or points out that these people are just getting their email addresses onto a lot of spam mailing lists, but on and on they go asking for a copy to be sent direct to them.

It's surprisingly funny.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-113923526966829029?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/113923526966829029/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=113923526966829029' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113923526966829029'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113923526966829029'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/02/counting-sheep.html' title='Counting Sheep'/><author><name>Tony Andrews</name><uri>http://www.blogger.com/profile/16750945985361011515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-113915899467498752</id><published>2006-02-05T17:00:00.000Z</published><updated>2006-02-05T17:06:02.640Z</updated><title type='text'>I Object, Your Honour...</title><content type='html'>Erm, excuse me for interrupting, but what exactly is this?

&lt;blockquote&gt;There are 2 ways to construct an ANYDATA. The CONVERT* calls enable construction of the ANYDATA in its entirety with a single call. They serve as explicit CAST functions from any type in the &lt;strong&gt;&lt;em&gt;&lt;span style="font-size:180%;"&gt;Oracle ORDBMS&lt;/span&gt; &lt;/em&gt;&lt;/strong&gt;to ANYDATA.&lt;/blockquote&gt;
(Found &lt;a href="http://download-west.oracle.com/docs/cd/B14117_01/appdev.101/b10802/t_anydat.htm#1001219"&gt;here&lt;/a&gt; in the 10.1 documentation).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-113915899467498752?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/113915899467498752/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=113915899467498752' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113915899467498752'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113915899467498752'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/02/i-object-your-honour.html' title='I Object, Your Honour...'/><author><name>OraWTFGuy</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-113873581361257657</id><published>2006-01-31T19:09:00.000Z</published><updated>2006-02-01T08:18:42.026Z</updated><title type='text'>INTEGER Type is Platform-Independent shock</title><content type='html'>&lt;p&gt;We are grateful to oracleplsqlprogramming.com for their &lt;a href="http://oracleplsqlprogramming.com/oppnews_200512.html" rel="nofollow"&gt;December 2005 Tip of the Month: Insights into PL/SQL Integers&lt;/a&gt;, in which we learn this:&lt;/p&gt;
&lt;blockquote&gt;&lt;b&gt;INTEGER&lt;/b&gt; - defined in the STANDARD package as a subtype of NUMBER, this datatype is implemented in a completely platform-independent fashion, which means that anything you do with NUMBER or INTEGER variables should work the same regardless of the hardware on which the database is installed.&lt;/blockquote&gt;
&lt;p&gt;And thank goodness for that, is what we say. Sometimes you just don't need platform-dependent results from your PL/SQL integer calculation depending on the hardware on which the database is installed.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-113873581361257657?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/113873581361257657/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=113873581361257657' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113873581361257657'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113873581361257657'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/01/integer-type-is-platform-independent.html' title='INTEGER Type is Platform-Independent shock'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-113768921126945073</id><published>2006-01-19T16:43:00.000Z</published><updated>2006-01-19T16:47:54.906Z</updated><title type='text'>When is a BLOB not a blob?</title><content type='html'>&lt;p&gt;When it's a Bee-Lob, apparently. If think you know how to pronounce some of the more common Oracle-related words, you have to check Eddie Awad's post, "&lt;a href="http://awads.net/wp/2006/01/18/char-or-car"&gt;Char or Car&lt;/a&gt;", and the follow-up comments...&lt;/p&gt;

&lt;p&gt;&lt;a href="http://awads.net/wp/2006/01/18/char-or-car"&gt;awads.net/wp/2006/01/18/char-or-car&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-113768921126945073?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/113768921126945073/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=113768921126945073' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113768921126945073'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113768921126945073'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/01/when-is-blob-not-blob.html' title='When is a BLOB not a blob?'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-113758657216364211</id><published>2006-01-18T12:06:00.000Z</published><updated>2006-01-18T12:28:59.510Z</updated><title type='text'>Two days before the day after tomorrow</title><content type='html'>Clearly a South Park fan worked here once:

&lt;pre&gt;
cat oracle_GetThisworkingDay

DATE=`date +%Y%m%d%H%M`
CUTOFF=$2

#!/bin/ksh
# oracle_GetThisworkingDay
# Script to retrieve the current working day (YYYYMMDD) from
# the working_calendar table in the Oracle database.
oracle_GetPreviousWorkingDay `oracle_GetNextWorkingDay $DATE $CUTOFF`

&lt;/pre&gt;

I'll spare you the contents of these scripts.

Suffice to say they call the following procedures:

&lt;pre&gt;
   FUNCTION previous_day (
      p_date                              DATE DEFAULT SYSDATE
   )
      RETURN VARCHAR2
   IS
      v_result                      VARCHAR2 (10);
   BEGIN
      SELECT dt
        INTO v_result
        FROM working_calendar
       WHERE dt = (SELECT MAX (dt)
                     FROM working_calendar
                    WHERE dt &lt; p_date );
    RETURN TO_CHAR(v_result,'YYYYMMDD');
  END;
&lt;/pre&gt;
( nice use of SQL there ) and of course...
&lt;pre&gt;
   FUNCTION next_day (
      p_now                               DATE DEFAULT CURRENT_DATE
   )
      RETURN DATE
   IS
      RESULT                        DATE;
   BEGIN
      SELECT MIN (dt)
        INTO RESULT
        FROM working_calendar
       WHERE dt &gt;= p_now + 1;

      RETURN RESULT;
   END;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-113758657216364211?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/113758657216364211/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=113758657216364211' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113758657216364211'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113758657216364211'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/01/two-days-before-day-after-tomorrow.html' title='Two days before the day after tomorrow'/><author><name>Adrian</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-113753223271815505</id><published>2006-01-17T21:08:00.000Z</published><updated>2006-01-18T13:39:19.720Z</updated><title type='text'>It's One More, Innit?</title><content type='html'>&lt;p&gt;&lt;i&gt;Thanks to Scott Lynch for submitting an example of how a J2EE application developer just might not trust the database to do its job. &lt;!--And not have a clue about how to interact with the database, either (clue: check out how many times the same statement is prepared.)--&gt;&lt;p&gt;&lt;p&gt;

Over to Scott...&lt;/i&gt;&lt;p&gt;

From a big bucks retail management system (now owned by a big bucks DBMS vendor).&lt;p&gt;

1. Get NextVal from the sequence.&lt;p&gt;
2. Assign the value, an integer, to a string.&lt;p&gt;
3. Check to see if the string they just created exists.&lt;p&gt;
4. Cast the integer that has been cast to a string, to a BigDecimal.&lt;p&gt;
5. Add 1 to it (because they're obviously smarter than some silly old sequence).&lt;p&gt;

I just love step 3.&lt;p&gt;

Sheer brilliance on that one. And it's repeated for almost every table in this particular little slice of the application.&lt;p&gt;

------------------------------------------------------------------------------------------------

&lt;pre&gt;
public long getNextId() throws java.sql.SQLException{
   if (conn == null)
   {
      throw new java.sql.SQLException("Connection not set");
   }
   long nextIdLong = 0;
   try
   {
      //Create a statement
      tStmt = conn.createStatement();

      //Create a query string to get all the fields from the table. The
      //presentation layer will decide which field to display
      String query = "SELECT some_seq.nextval FROM dual";

      //The complete query is executed
      rs = tStmt.executeQuery(query);
      rs.next();
      String nextIdString = rs.getString(1);

      if (nextIdString != null) {
         nextIdLong = ((new BigDecimal(nextIdString)).add(new BigDecimal(1))).longValue();
      }

      tStmt.close();

   } catch (SQLException e)
   {
      throw new java.sql.SQLException(e.toString());
   }
   return nextIdLong;
}
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-113753223271815505?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/113753223271815505/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=113753223271815505' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113753223271815505'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113753223271815505'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/01/its-one-more-innit.html' title='It&apos;s One More, Innit?'/><author><name>OraWTFGuy</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-113708685640816186</id><published>2006-01-12T16:57:00.000Z</published><updated>2006-02-08T08:26:46.566Z</updated><title type='text'>Bring out your WTFs</title><content type='html'>&lt;p&gt;Always on the lookout for blog material requiring minimal editorial effort, we welcome your WTF submissions. Amusing and instructive examples of mind-boggling Oracle-related madness (ideally short ones) can now be sent to us at our new e-mail address: &lt;a href="mailto:oraclewtf@bigfoot.com?subject=Oracle-WTF"&gt;oraclewtf@bigfoot.com&lt;/a&gt;. Please remember to include "OracleWTF" in your Subject line.&lt;/p&gt;

&lt;p&gt;I would also like to welcome our two new contributors, Tony Andrews and Scott Swank.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-113708685640816186?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/113708685640816186/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=113708685640816186' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113708685640816186'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113708685640816186'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/01/bring-out-your-wtfs_12.html' title='Bring out your WTFs'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-113708442360567800</id><published>2006-01-12T16:42:00.000Z</published><updated>2006-01-12T16:51:44.000Z</updated><title type='text'>Universal SQL Performance Improver Discovered</title><content type='html'>In &lt;a href="http://asktom.oracle.com/pls/ask/f?p=4950:8:::::F4950_P8_DISPLAYID:54694913325497"&gt;an AskTom thread&lt;/a&gt; this week, the poster wrote:
&lt;blockquote&gt;"...I have been told before by several people, and I have implemented myself on several SQLs that adding the clause "AND&amp;nbsp;1=1" literally to any SQL statement helps improve the performance of the SQL statement dramatically."&lt;/blockquote&gt;
&lt;p&gt;And we've all been wasting our time looking for a FAST=TRUE parameter.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-113708442360567800?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/113708442360567800/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=113708442360567800' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113708442360567800'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113708442360567800'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/01/universal-sql-performance-improver.html' title='Universal SQL Performance Improver Discovered'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-113630109225034585</id><published>2006-01-03T15:08:00.000Z</published><updated>2006-01-03T15:11:32.260Z</updated><title type='text'>Grow Your Own Concurrency Problem</title><content type='html'>What's that? the sound of ORA-00001: approaching...

&lt;pre&gt;
...
 FUNCTION key_not_in_table(pkey IN INT) RETURN BOOLEAN
 IS
  countkey INT;
 BEGIN
  SELECT count(key) INTO countkey
  FROM key_values WHERE key = pkey;

  IF countkey &gt; 0 THEN
   RETURN FALSE;
  END IF;
  RETURN TRUE;

 END key_not_in_table;
 
 PROCEDURE insert_or_update(pkey IN INT,
   pval IN INT)
 IS
 BEGIN
  IF key_not_in_table(pkey) THEN
   INSERT INTO key_values
   VALUES (key, value, 0);
  ELSE
   UPDATE key_values
   SET value =  pval
   WHERE key = pkey;
  END IF;
 END insert_or_update;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-113630109225034585?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/113630109225034585/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=113630109225034585' title='19 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113630109225034585'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113630109225034585'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/01/grow-your-own-concurrency-problem.html' title='Grow Your Own Concurrency Problem'/><author><name>Adrian</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>19</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-113622611032989527</id><published>2006-01-02T17:36:00.000Z</published><updated>2006-02-08T08:23:51.910Z</updated><title type='text'>Bring out your WTFs</title><content type='html'>Always on the lookout for blog material requiring minimum editorial effort, we welcome your WTFs. Amusing and instructive examples of mind-boggling Oracle-related madness (ideally short ones) can now be sent to us at our new e-mail address: &lt;a href=mailto:oraclewtf@bigfoot.com&gt;OracleWTF@bigfoot.com&lt;/a&gt;.

I would also like to welcome our two new WTF contributors, Tony Andrews and Scott Swank.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-113622611032989527?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/113622611032989527/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=113622611032989527' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113622611032989527'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113622611032989527'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2006/01/bring-out-your-wtfs.html' title='Bring out your WTFs'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-113594007758305802</id><published>2005-12-30T10:46:00.000Z</published><updated>2005-12-30T13:43:46.623Z</updated><title type='text'>Who needs modular code?</title><content type='html'>Wouldn’t it be nice if when people wrote some useful code, they tried to make it suitably modular and reusable?  This is what I have to contend with at the moment.  We have a large, complex system written in Oracle Forms that we are now partially re-writing in HTMLDB (hurrah!)  One function I want to replicate is the ability to change your own Oracle password; the current Forms application has a form to do this that looks like this:
&lt;blockquote&gt;
 Old Password: [                    ]

 New Password: [                    ]

 Confirm New Password: [                    ]
&lt;/blockquote&gt;
So that should be a moment’s work to redo, right?  Wrong.  There is a package of procedures for user maintenance that contains the following 2 procedures that are relevant:
&lt;pre&gt;
PROCEDURE change_password_validate
(p_username         IN VARCHAR2,
 p_old_password     IN VARCHAR2,
 p_new_password     IN VARCHAR2,
 p_confirm_password IN VARCHAR2,
 p_profile_name     IN VARCHAR2,
 p_mode             IN VARCHAR2 DEFAULT 'N',
 p_mask             IN  VARCHAR2) ;

PROCEDURE change_password_process
(p_username IN VARCHAR2,
 p_new_password IN VARCHAR2,
 p_confirm_password IN VARCHAR2,
 p_mask           IN VARCHAR2,
 p_profile_name IN VARCHAR2,
 p_encrypt_pw IN VARCHAR2,
 p_admin_mode IN VARCHAR2 DEFAULT NULL) ;
&lt;/pre&gt;
Some design flaws are immediately evident:
&lt;ul&gt;
&lt;li&gt;Validation is totally separate from processing.  If I choose to, I can skip the validate routine altogether and call the process routine to change the password to anything I like, regardless of whether I get the old password right or confirm it correctly.  (Actually, this foolish separation of validation from processing is a company standard!)
&lt;li&gt;I get to choose whether the password is to be stored (in our own application’s USERS table) in encrypted form or not.  HTF do &lt;b&gt;I&lt;/b&gt; know whether it should be encrypted or not?
&lt;li&gt;I need to supply something called p_mask, which I think may be something to do with the encryption process, or maybe the validation process – none of this is documented of course, or at least nobody knows where any such documentation may be found.  I have tried passing the word ‘mask’ and it seems to work, except that all subsequent attempt to change the password then fail on the validation of the “old” password – perhaps because it has been encrypted in an unexpected manner.
&lt;li&gt;I also need to supply something called p_profile_name, which I do happen to know is a user attribute something like a role, stored in the USERS table.  Well excuse me, but if I’m passing in the username as a parameter, why should I have to go look up the USERS record and obtain the profile_name value just to pass it into this lazy procedure?
&lt;li&gt;I don’t fully understand p_mode and p_admin_mode either, but at least they have defaults which I assume (for now) I can live with.
&lt;/ul&gt;
So instead of being a 5 minute job, this is probably going to occupy about a day of my time: locating source code (the packages are wrapped in the database), studying source code to see what it is doing.  And if all that fails, trying to find someone from the team that wrote the code and ask them to tell me what I should be doing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-113594007758305802?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/113594007758305802/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=113594007758305802' title='36 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113594007758305802'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113594007758305802'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2005/12/who-needs-modular-code.html' title='Who needs modular code?'/><author><name>Tony Andrews</name><uri>http://www.blogger.com/profile/16750945985361011515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>36</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-113577043088349932</id><published>2005-12-28T10:34:00.000Z</published><updated>2006-01-09T19:19:18.006Z</updated><title type='text'>EAV nightmare</title><content type='html'>My charitable Christmas mood only goes so far.

I'm looking through a spec which reads like a "database design nightmare!" theme advent calendar.  Each page reveals a potential disaster more frightening than the one before.

This is my favourite new year hang over inducing cocktail of entity attribute values and generic application design all wrapped up in a gloriously mal-specified mess.


&lt;pre&gt;
Table: Parameters

id  VARCHAR2(50) PRIMARY KEY  --The application requesting the value
identifier NUMBER       PRIMARY KEY  --The name of the parameter
type  CHAR(1) --‘I’, ‘S’ or ‘B’ is type of value for the parameter
string_val VARCHAR2(50) --‘Y’ or ‘N’ or NULL if BOOLEAN or the string 
integer_val NUMBER       -- The integer value

note: The id holds a value comprising the IP address, type of
application and the instance at that IP.
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-113577043088349932?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/113577043088349932/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=113577043088349932' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113577043088349932'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113577043088349932'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2005/12/eav-nightmare.html' title='EAV nightmare'/><author><name>Adrian</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-113527725997421558</id><published>2005-12-22T18:38:00.000Z</published><updated>2005-12-22T18:47:39.986Z</updated><title type='text'>Bracketing frenzy</title><content type='html'>&lt;p&gt;I just found myself decyphering this:&lt;/p&gt;&lt;pre&gt;SELECT ...
FROM report_results rpt
WHERE NOT ( (substr(rpt.report_type,2,1) in ('1','2','3','4','5')) and
          (rpt.sig_type = 'ISDNMA') and
          ((rpt.group_ctn != rpt.ctn_prefix||rpt.ctn_suffix) and
           (length(rpt.group_ctn) != length(rpt.ctn_prefix||rpt.ctn_suffix)) and
           ((length(rpt.group_ctn) != (length(rpt.ctn_prefix||rpt.ctn_suffix)-1)
           ))));&lt;/pre&gt;&lt;p&gt;Which turns out to mean this:&lt;/p&gt;&lt;pre&gt;SELECT ...
FROM   report_results rpt
WHERE  NOT (     SUBSTR(rpt.report_type,2,1) IN ('1','2','3','4','5')
            AND  rpt.sig_type = 'ISDNMA'
            AND  rpt.group_ctn != rpt.ctn_prefix||rpt.ctn_suffix
            AND  LENGTH(rpt.group_ctn) != LENGTH(rpt.ctn_prefix||rpt.ctn_suffix)
            AND  LENGTH(rpt.group_ctn) != LENGTH(rpt.ctn_prefix||rpt.ctn_suffix)-1 );&lt;/pre&gt;&lt;p&gt;No wonder there are no brackets left in the shops.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-113527725997421558?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/113527725997421558/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=113527725997421558' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113527725997421558'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113527725997421558'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2005/12/bracketing-frenzy.html' title='Bracketing frenzy'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-113294712452163972</id><published>2005-11-25T19:20:00.000Z</published><updated>2006-01-12T17:50:29.666Z</updated><title type='text'>Code Generation Frenzy</title><content type='html'>&lt;p&gt;Today's WTF moment is a bit of a monster, so I will try to explain what it does, and you can skim the actual code (this is probably a good idea) and still appreciate it.&lt;/p&gt;&lt;p&gt;Imagine that you have some static reference tables, let's say ORDER_STATUSES and LOCATIONS (amongst others), and you decide it would be a good idea to build an interface so that any application code can simply retrieve, say, the default order status or the head office location.&lt;/p&gt;&lt;p&gt;Being a bit clever, you notice that all the tables have the same structure, consisting of an ID and a description, and it occurs to you that if you UNIONed them all together, with the table name as a "type" key, you would have that generic lookup table you always wanted, along with a generic cursor to query it. (It avoids having one cursor per table, after all, so there is an efficiency gain already, right?) So you write this:&lt;/p&gt;
&lt;pre&gt;/* -------------------------------------------------------------------------------------
Name:    xxxx
Author   xxxx
Description: Script to create the types functions dynamically during schema creation
Input parameters: None
----------------------------------------------------------------------------------------*/
set serveroutput on size 1000000

variable v_destination_dir varchar2(256);
variable v_errorfilename varchar2(256);
variable v_datafile_name varchar2(256);

BEGIN
    :v_destination_dir := '&amp;1';
    :v_errorfilename := 'type_model_functions.err';
    :v_datafile_name := 'type_model_functions.lst';
END;
/

DECLARE
    CURSOR c_tables IS 
        SELECT DISTINCT table_name
        FROM   types_functions
        ORDER BY table_name;

    CURSOR c_types IS 
        SELECT table_name, function_name, REPLACE(type_value,'''','''''') type_value 
        FROM   types_functions
        WHERE  function_name IS NOT NULL
        ORDER BY table_name,function_name;

    v_prev_rec number; 
    file_handle  UTL_FILE.FILE_TYPE :=
                 UTL_FILE.FOPEN (:v_destination_dir,  :v_datafile_name, 'W'); 

BEGIN
    UTL_FILE.PUT_LINE(file_handle, 'set define off');
    UTL_FILE.PUT_LINE
    (file_handle, '/*----------------------------------------------------------------');
    UTL_FILE.PUT_LINE
    (file_handle, ' Name: type_model_functions.lst');
    UTL_FILE.PUT_LINE
    (file_handle, ' Description: Functions to return the id from the types tables');
    UTL_FILE.PUT_LINE
    (file_handle, ' (Package Specifications)');
    UTL_FILE.PUT_LINE
    (file_handle, ' Input parameters: None');
    UTL_FILE.PUT_LINE
    (file_handle, ' Author: xxxx');
    UTL_FILE.PUT_LINE
    (file_handle, chr(10));
    UTL_FILE.PUT_LINE
    (file_handle, '-----------------------------------------------------------------*/');
    UTL_FILE.PUT_LINE(file_handle, chr(9)|| 'CREATE OR REPLACE VIEW types_view AS ');
    v_prev_rec := 0;

    FOR r_tables IN c_tables LOOP
        IF v_prev_rec &lt;&gt; 0 THEN
            UTL_FILE.PUT_LINE(file_handle, chr(9)|| 'UNION');
        END IF;

        UTL_FILE.PUT_LINE
        ( file_handle
        , chr(9)|| 'SELECT typeid, typelabel, ''' ||
          r_tables.table_name||''' tablename from '||r_tables.table_name );

        v_prev_rec := c_tables%rowcount;
    END LOOP;

    UTL_FILE.PUT_LINE(file_handle, '/');
    UTL_FILE.PUT_LINE(file_handle, 'show err');
    UTL_FILE.PUT_LINE(file_handle, 'drop public synonym types_view ;');
    UTL_FILE.PUT_LINE(file_handle, 'create public synonym types_view for types_view ;');
    UTL_FILE.PUT_LINE(file_handle, 'grant select on types_view to public;');

    UTL_FILE.PUT_LINE(file_handle, 'CREATE OR REPLACE PACKAGE types AS ');

    FOR r_types IN c_types LOOP
        UTL_FILE.PUT_LINE
        ( file_handle
        , chr(9) ||
          '-- Function to return the typeid for ' ||
          r_types.type_value || ' ' || r_types.table_name );

        UTL_FILE.PUT_LINE
        (file_handle, chr(9)|| 'FUNCTION '||r_types.function_name||' RETURN NUMBER;');
        UTL_FILE.PUT_LINE
        (file_handle, chr(9)|| 'PRAGMA RESTRICT_REFERENCES ('||r_types.function_name||', WNDS);');
    END LOOP;

    UTL_FILE.PUT_LINE(file_handle, 'END types;');
    UTL_FILE.PUT_LINE(file_handle, '/');
    UTL_FILE.PUT_LINE(file_handle, 'show err');
    UTL_FILE.PUT_LINE(file_handle, chr(10));

    UTL_FILE.PUT_LINE
    (file_handle, 'CREATE OR REPLACE PACKAGE BODY types AS ');
    UTL_FILE.PUT_LINE
    (file_handle, chr(9)||'CURSOR c_types_view(p_typelabel varchar2, p_tablename varchar2) IS ');
    UTL_FILE.PUT_LINE
    (file_handle, chr(9)||'SELECT typeid from types_view ');
    UTL_FILE.PUT_LINE
    (file_handle, chr(9)||'WHERE  typelabel = p_typelabel and tablename = p_tablename ;');

    FOR r_types IN c_types LOOP
        UTL_FILE.PUT_LINE
        (file_handle, chr(9)|| 'FUNCTION '|| r_types.function_name||' RETURN NUMBER IS ');
        UTL_FILE.PUT_LINE
        (file_handle, chr(9)|| chr(9)|| 'v_typeid'||chr(9)||'NUMBER; ');
        UTL_FILE.PUT_LINE
        (file_handle, chr(9)|| 'BEGIN');
        UTL_FILE.PUT_LINE
        (file_handle, chr(9)|| chr(9)|| 'OPEN  c_types_view (''' ||
                                        r_types.type_value||''','''||r_types.table_name||''');');
        UTL_FILE.PUT_LINE
        (file_handle, chr(9)|| chr(9)|| 'FETCH c_types_view INTO v_typeid;');
        UTL_FILE.PUT_LINE
        (file_handle, chr(9)|| chr(9)|| 'IF c_types_view%NOTFOUND THEN ');
        UTL_FILE.PUT_LINE
        (file_handle, chr(9)|| chr(9)|| chr(9)|| 'RAISE no_data_found; ');
        UTL_FILE.PUT_LINE
        (file_handle, chr(9)|| chr(9)|| 'END IF; ');
        UTL_FILE.PUT_LINE
        (file_handle, chr(9)|| chr(9)|| 'CLOSE  c_types_view;');
        UTL_FILE.PUT_LINE
        (file_handle, chr(9)|| chr(9)|| 'RETURN v_typeid; ');
        UTL_FILE.PUT_LINE
        (file_handle, chr(9)|| 'EXCEPTION');
        UTL_FILE.PUT_LINE
        (file_handle, chr(9)|| chr(9)|| 'WHEN OTHERS THEN');

        UTL_FILE.PUT_LINE
        ( file_handle
        , chr(9)|| chr(9)|| chr(9) ||
          'RAISE_APPLICATION_ERROR(-20001, ''Function types.' ||
          r_types.function_name || ': '''||'||sqlerrm );' );

        UTL_FILE.PUT_LINE(file_handle, chr(9)|| 'END '|| r_types.function_name|| ';');
    END LOOP;

    UTL_FILE.PUT_LINE(file_handle, 'END types;');
    UTL_FILE.PUT_LINE(file_handle, '/');

    UTL_FILE.PUT_LINE(file_handle, 'show err');

    UTL_FILE.PUT_LINE(file_handle, 'drop public synonym types;');
    UTL_FILE.PUT_LINE(file_handle, 'create public synonym types for types;');
    UTL_FILE.PUT_LINE(file_handle, 'grant execute on types to public;');

    UTL_FILE.PUT_LINE(file_handle, 'exit');

    UTL_FILE.FCLOSE (file_handle);
END;
/

@&amp;1/type_model_functions.lst

exit&lt;/pre&gt;
Now, given a set of values in TYPES_VALUES like this:
&lt;!--
INSERT ALL
INTO types_functions VALUES ('order_statuses', 'get_default_order_status','Default')
INTO types_functions VALUES ('order_statuses', 'get_order_cancelled_status','Cancelled')
INTO types_functions VALUES ('order_statuses', 'get_order_dispatched_status','Dispatched')
INTO types_functions VALUES ('order_statuses', 'get_order_closed','Closed')
INTO types_functions VALUES ('locations', 'get_head_office_location','Head Office')
INTO types_functions VALUES ('locations', 'get_accounts_office_location','Accounts')
SELECT * FROM dual
--&gt;
&lt;pre&gt;TABLE_NAME      FUNCTION_NAME                TYPE_VALUE
--------------- ---------------------------- ---------------
order_statuses  get_default_order_status     Default
order_statuses  get_order_cancelled_status   Cancelled
order_statuses  get_order_dispatched_status  Dispatched
order_statuses  get_order_closed             Closed
locations       get_head_office_location     Head Office
locations       get_accounts_office_location Accounts&lt;/pre&gt;
the script generates something like this:
&lt;pre&gt;set define off
/*----------------------------------------------------------------------------
Name: type_model_functions.lst
Description: Packaged functions to return the typeid from the types tables
Input parameters: None
Author: xxxx
-----------------------------------------------------------------------------*/

CREATE OR REPLACE VIEW types_view AS 
SELECT typeid, typelabel, 'locations' tablename from locations
UNION
SELECT typeid, typelabel, 'order_statuses' tablename from order_statuses
/
show err
drop public synonym types_view ;
create public synonym types_view for types_view ;
grant select on types_view to public;

CREATE OR REPLACE PACKAGE types AS 
    -- Function to return the typeid for Accounts locations
    FUNCTION get_accounts_office_location RETURN NUMBER;
    PRAGMA RESTRICT_REFERENCES (get_accounts_office_location, WNDS);

    -- Function to return the typeid for Head Office locations
    FUNCTION get_head_office_location RETURN NUMBER;
    PRAGMA RESTRICT_REFERENCES (get_head_office_location, WNDS);

    -- Function to return the typeid for Default order_statuses
    FUNCTION get_default_order_status RETURN NUMBER;
    PRAGMA RESTRICT_REFERENCES (get_default_order_status, WNDS);

    -- Function to return the typeid for Cancelled order_statuses
    FUNCTION get_order_cancelled_status RETURN NUMBER;
    PRAGMA RESTRICT_REFERENCES (get_order_cancelled_status, WNDS);

    -- Function to return the typeid for Closed order_statuses
    FUNCTION get_order_closed RETURN NUMBER;
    PRAGMA RESTRICT_REFERENCES (get_order_closed, WNDS);

    -- Function to return the typeid for Dispatched order_statuses
    FUNCTION get_order_dispatched_status RETURN NUMBER;
    PRAGMA RESTRICT_REFERENCES (get_order_dispatched_status, WNDS);
END types;
/
show err


CREATE OR REPLACE PACKAGE BODY types AS 
    CURSOR c_types_view(p_typelabel varchar2, p_tablename varchar2) IS 
    SELECT typeid from types_view 
    WHERE  typelabel = p_typelabel and tablename = p_tablename ;

    FUNCTION get_accounts_office_location RETURN NUMBER IS 
        v_typeid NUMBER; 
    BEGIN
        OPEN  c_types_view ('Accounts','locations');
        FETCH c_types_view INTO v_typeid;
        IF c_types_view%NOTFOUND THEN 
            RAISE no_data_found; 
        END IF; 
        CLOSE  c_types_view;
        RETURN v_typeid; 
    EXCEPTION
        WHEN OTHERS THEN
            RAISE_APPLICATION_ERROR
            ( -20001, 'Function types.get_accounts_office_location: '||sqlerrm );
    END get_accounts_office_location;

    FUNCTION get_head_office_location RETURN NUMBER IS 
        v_typeid NUMBER; 
    BEGIN
        OPEN  c_types_view ('Head Office','locations');
        FETCH c_types_view INTO v_typeid;
        IF c_types_view%NOTFOUND THEN 
            RAISE no_data_found; 
        END IF; 
        CLOSE  c_types_view;
        RETURN v_typeid; 
    EXCEPTION
        WHEN OTHERS THEN
            RAISE_APPLICATION_ERROR
            ( -20001, 'Function types.get_head_office_location: '||sqlerrm );
    END get_head_office_location;

    FUNCTION get_default_order_status RETURN NUMBER IS 
        v_typeid NUMBER; 
    BEGIN
        OPEN  c_types_view ('Default','order_statuses');
        FETCH c_types_view INTO v_typeid;
        IF c_types_view%NOTFOUND THEN 
            RAISE no_data_found; 
        END IF; 
        CLOSE  c_types_view;
        RETURN v_typeid; 
    EXCEPTION
        WHEN OTHERS THEN
            RAISE_APPLICATION_ERROR
            ( -20001, 'Function types.get_default_order_status: '||sqlerrm );
    END get_default_order_status;

    FUNCTION get_order_cancelled_status RETURN NUMBER IS 
        v_typeid NUMBER; 
    BEGIN
        OPEN  c_types_view ('Cancelled','order_statuses');
        FETCH c_types_view INTO v_typeid;
        IF c_types_view%NOTFOUND THEN 
            RAISE no_data_found; 
        END IF; 
        CLOSE  c_types_view;
        RETURN v_typeid; 
    EXCEPTION
        WHEN OTHERS THEN
            RAISE_APPLICATION_ERROR
            ( -20001, 'Function types.get_order_cancelled_status: '||sqlerrm );
    END get_order_cancelled_status;

    FUNCTION get_order_closed RETURN NUMBER IS 
        v_typeid NUMBER; 
    BEGIN
        OPEN  c_types_view ('Closed','order_statuses');
        FETCH c_types_view INTO v_typeid;
        IF c_types_view%NOTFOUND THEN 
            RAISE no_data_found; 
        END IF; 
        CLOSE  c_types_view;
        RETURN v_typeid; 
    EXCEPTION
        WHEN OTHERS THEN
            RAISE_APPLICATION_ERROR
            ( -20001, 'Function types.get_order_closed: '||sqlerrm );
    END get_order_closed;

    FUNCTION get_order_dispatched_status RETURN NUMBER IS 
        v_typeid NUMBER; 
    BEGIN
        OPEN  c_types_view ('Dispatched','order_statuses');
        FETCH c_types_view INTO v_typeid;
        IF c_types_view%NOTFOUND THEN 
            RAISE no_data_found; 
        END IF; 
        CLOSE  c_types_view;
        RETURN v_typeid; 
    EXCEPTION
        WHEN OTHERS THEN
            RAISE_APPLICATION_ERROR
            ( -20001, 'Function types.get_order_dispatched_status: '||sqlerrm );
    END get_order_dispatched_status;
END types;
/
show err
drop public synonym types;
create public synonym types for types;
grant execute on types to public;
exit&lt;/pre&gt;&lt;p&gt;Now all you have to do is ensure that there are values in the LOCATIONS table with typelabels 'Head Office', 'Accounts' and so on, and whenever you run the script it will create or replace a whole new package implementing whatever you put in TYPES_FUNCTIONS, and application code can simply invoke &lt;tt&gt;types.get_accounts_office_location()&lt;/tt&gt;.&lt;/p&gt;&lt;p&gt;Now, I wonder whether there is a way to generate the TYPES_FUNCTIONS table...&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-113294712452163972?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/113294712452163972/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=113294712452163972' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113294712452163972'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113294712452163972'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2005/11/code-generation-frenzy.html' title='Code Generation Frenzy'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-113174329447390208</id><published>2005-11-11T20:51:00.000Z</published><updated>2005-11-11T21:08:14.496Z</updated><title type='text'>When RTFM Goes Wrong IV</title><content type='html'>&lt;span style="font-family:arial;font-size:85%;"&gt;The sheer size of Oracle's documentation set always astonishes me, and it's a wonder that any of it ever manages to evolve across versions. But sure enough, the important bits usually get a brush-up during major release changes and a few new bits get thrown in. &lt;/span&gt;&lt;span style="font-family:arial;font-size:85%;"&gt;But not so for a particularly dry part of Chapter 2 of the "Application Developers Guide - Fundamentals" for 10g Release 2 (Chapter 5 in earlier versions), subtitled "Improving Transaction Performance". &lt;p&gt;Remember this is 10.2 - it's bang up to date as far as Oracle releases go. I don't think that any further comment is required here else the post will get too long so I'll just send you to the link and suggest you take particular note of the comments on stored PL/SQL functions, ANALYZE and explicit cursors.&lt;p&gt;&lt;/span&gt;&lt;span style="font-family:Arial;font-size:85%;"&gt;&lt;/span&gt;
&lt;span style="font-family:Arial;font-size:85%;"&gt;&lt;a href="http://download-uk.oracle.com/docs/cd/B19306_01/appdev.102/b14251/adfns_sqlproc.htm#sthref179"&gt;http://download-uk.oracle.com/docs/cd/B19306_01/appdev.102/b14251/adfns_sqlproc.htm#sthref179&lt;/a&gt;&lt;/span&gt;
&lt;span style="font-family:arial;font-size:85%;"&gt;&lt;p&gt;The rollback segment entry can be forgiven as not everyone is using UNDO yet (though I always hated it as a piece of advice when I used rollback segments).&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-113174329447390208?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/113174329447390208/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=113174329447390208' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113174329447390208'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113174329447390208'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2005/11/when-rtfm-goes-wrong-iv.html' title='When RTFM Goes Wrong IV'/><author><name>OraWTFGuy</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-113173698412893374</id><published>2005-11-11T19:13:00.000Z</published><updated>2006-01-12T18:00:08.176Z</updated><title type='text'>You can never have too much redirection</title><content type='html'>&lt;p&gt;And who needs PL/SQL anyway when you already have all the procedural control you need, thanks to Mr Stephen Bourne and his excellent Shell?&lt;/p&gt;
&lt;pre&gt;
echo -------------------------------------  &gt;&gt; $LOGS/$MY_LOGFILE_NAME
echo Load the xxx schema tables for xyz &gt;&gt; $LOGS/$MY_LOGFILE_NAME
echo ------------------------------------- &gt;&gt; $LOGS/$MY_LOGFILE_NAME
sqlplus -s $XXX_USERNAME/$XXX_PASSWORD @$XYZ_BIN/xyz_load_xxx_data.sql $LOGS $MY_ERRORFILE_NAME &amp;#92&lt;br&gt;&gt;&gt; $LOGS/$MY_LOGFILE_NAME
retcode=`echo \$?`
if [ "$retcode" -ne 0 ] ;then
 echo Step failed &gt;&gt; $LOGS/$MY_LOGFILE_NAME
 exit $RETURN_GENERIC_FAIL
fi

echo ------------------------------------  &gt;&gt; $LOGS/$MY_LOGFILE_NAME
echo Processing abc files &gt;&gt; $LOGS/$MY_LOGFILE_NAME
echo ------------------------------------ &gt;&gt; $LOGS/$MY_LOGFILE_NAME
$xyz_BIN/xyz_process_abc_ndt_files.pl
retcode=`echo \$?`
if [ "$retcode" -ne 0 ] ;then
 echo Step failed &gt;&gt; $LOGS/$MY_LOGFILE_NAME
 exit $RETURN_GENERIC_FAIL
fi

echo ------------------------------------  &gt;&gt; $LOGS/$MY_LOGFILE_NAME
echo Processing MF files &gt;&gt; $LOGS/$MY_LOGFILE_NAME
echo ------------------------------------ &gt;&gt; $LOGS/$MY_LOGFILE_NAME
$xyz_BIN/xyz_process_def_ndt_files.pl
retcode=`echo \$?`
if [ "$retcode" -ne 0 ] ;then
 echo Step failed &gt;&gt; $LOGS/$MY_LOGFILE_NAME
 exit $RETURN_GENERIC_FAIL
fi

echo -------------------------------------  &gt;&gt; $LOGS/$MY_LOGFILE_NAME
echo Merge MF and customer tables for xyz &gt;&gt; $LOGS/$MY_LOGFILE_NAME
echo ------------------------------------- &gt;&gt; $LOGS/$MY_LOGFILE_NAME
sqlplus -s $XYZ_USERNAME/$XYZ_PASSWORD &amp;#92;&lt;br&gt; @$XYZ_BIN/xyz_merge_mf_and_customer_tables.sql $LOGS $MY_ERRORFILE_NAME &amp;#92;
&gt;&gt; $LOGS/$MY_LOGFILE_NAME
retcode=`echo \$?`
if [ "$retcode" -ne 0 ] ;then
 echo Step failed &gt;&gt; $LOGS/$MY_LOGFILE_NAME
 exit $RETURN_GENERIC_FAIL
fi

echo -------------------------------------  &gt;&gt; $LOGS/$MY_LOGFILE_NAME
echo Populate equipment table for xyz &gt;&gt; $LOGS/$MY_LOGFILE_NAME
echo ------------------------------------- &gt;&gt; $LOGS/$MY_LOGFILE_NAME
sqlplus -s $XYZ_USERNAME/$XYZ_PASSWORD &amp;#92; &lt;br&gt; @$XYZ_BIN/xyz_create_equipment.sql $LOGS $MY_ERRORFILE_NAME &amp;#92&lt;br&gt; &gt;&gt; $LOGS/$MY_LOGFILE_NAME
retcode=`echo \$?`
if [ "$retcode" -ne 0 ] ;then
 echo Step failed &gt;&gt; $LOGS/$MY_LOGFILE_NAME
 exit $RETURN_GENERIC_FAIL
fi

echo -------------------------------------  &gt;&gt; $LOGS/$MY_LOGFILE_NAME
echo Populate locations table for xyz &gt;&gt; $LOGS/$MY_LOGFILE_NAME
echo ------------------------------------- &gt;&gt; $LOGS/$MY_LOGFILE_NAME
sqlplus -s $XYZ_USERNAME/$XYZ_PASSWORD &amp;#92;&lt;br&gt; @$XYZ_BIN/xyz_create_locations.sql $LOGS $MY_ERRORFILE_NAME &amp;#92;&lt;br&gt; &gt;&gt; $LOGS/$MY_LOGFILE_NAME
retcode=`echo \$?`
if [ "$retcode" -ne 0 ] ;then
 echo Step failed &gt;&gt; $LOGS/$MY_LOGFILE_NAME
 exit $RETURN_GENERIC_FAIL
fi

runendt=`date`
echo ---------------------------------------------------- &gt;&gt; $LOGS/$MY_LOGFILE_NAME
echo "xyz dataload Ended - $runendt ....." &gt;&gt; $LOGS/$MY_LOGFILE_NAME
echo ---------------------------------------------------- &gt;&gt; $LOGS/$MY_LOGFILE_NAME
echo &gt;&gt; $LOGS/$MY_LOGFILE_NAME

exit $RETURN_SUCCESS&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-113173698412893374?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/113173698412893374/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=113173698412893374' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113173698412893374'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/113173698412893374'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2005/11/you-can-never-have-too-much.html' title='You can never have too much redirection'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-112932207132605214</id><published>2005-10-14T21:11:00.000+01:00</published><updated>2005-10-14T21:46:28.586+01:00</updated><title type='text'>Spot the difference</title><content type='html'>&lt;img style="margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://www.williamrobertson.pwp.blueyonder.co.uk/jpegs/associative_arrays1.jpg" border="0" alt="" /&gt;
&lt;img style="margin:0 0 10px 10px;" src="http://www.williamrobertson.pwp.blueyonder.co.uk/jpegs/associative_arrays2.jpg" border="0" alt="" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-112932207132605214?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/112932207132605214/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=112932207132605214' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/112932207132605214'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/112932207132605214'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2005/10/spot-difference.html' title='Spot the difference'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-112872796787221514</id><published>2005-10-07T23:58:00.000+01:00</published><updated>2005-10-08T00:52:07.220+01:00</updated><title type='text'>Prog rock</title><content type='html'>&lt;p&gt;Anyone who remembers The Ramones will have happy memories of their toetappingly monolithic slabs of pure punk pop. After a couple of albums of two-chord magic, however, there were those who said it was starting to sound samey, and I believe it was Joey Ramone's dad who commented in an interview that perhaps the boys might want to "complicate it up a bit".&lt;/p&gt;

&lt;p&gt;It seems the authors of Oracle Database 10g PL/SQL Programming (Oracle Press, 2004) chose to follow similar advice in their chapter on working with 8i, er, I mean 10g collections. Anyone looking for a funkier way to &lt;tt&gt;DELETE FROM addresses WHERE address_id = 11&lt;/tt&gt;, for example, need look no further:&lt;br&gt;
&lt;a href="http://www.peakretrieval.com/plsql/Chapter6/varray_dml1.sql" rel="nofollow" target=_twats&gt;www.peakretrieval.com/plsql/Chapter6/varray_dml1.sql&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And while we're at it,&lt;/p&gt;

&lt;pre&gt;SELECT column_value
FROM   &lt;a href="http://download-west.oracle.com/docs/cd/A87860_01/doc/server.817/a85397/state21b.htm#2066032" target=RTFM&gt;THE&lt;/a&gt; (SELECT CAST(emp_address AS varray_nested_table )
            FROM   emp
            WHERE  empno = 11);&lt;/pre&gt;

&lt;p&gt;(love that type name btw) could also be written as&lt;/p&gt;

&lt;pre&gt;SELECT column_value
FROM   emp, TABLE(emp_address)
WHERE  empno = 11;&lt;/pre&gt;

&lt;p&gt;but where's the fun in that?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-112872796787221514?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/112872796787221514/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=112872796787221514' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/112872796787221514'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/112872796787221514'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2005/10/prog-rock.html' title='Prog rock'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-112838378235187802</id><published>2005-10-04T00:22:00.000+01:00</published><updated>2005-10-12T10:44:43.406+01:00</updated><title type='text'>You can never have too many tables</title><content type='html'>&lt;p&gt;There is no problem that cannot be solved with a loop and some dynamic SQL.&lt;/p&gt;

&lt;p&gt;Problem: Your report can return rows for more than one feature code. How on Earth are you going to store the results?&lt;/p&gt;

&lt;p&gt;Solution: Loop through the FEATURES table, creating three dynamically named tables for each feature code. Problem solved.&lt;/p&gt;
&lt;pre&gt;BEGIN
FOR rec IN
    ( SELECT f.short_code ft FROM features f
      WHERE  f.chargeable = 'Y' )
LOOP
    BEGIN
        EXECUTE IMMEDIATE 'drop table r_t8_' || rec.ft ;
    EXCEPTION
        WHEN OTHERS THEN NULL;
    END;

    EXECUTE IMMEDIATE 'create table r_t8_' || rec.ft || '(' ||
    'report_type varchar2(50),' ||
    'report_date date,' ||
    'switch_id number,' ||
    'feat_count number,' ||
    'rental_rate number,' ||
    'discount number,' ||
    'rental_rating number)' ;

    BEGIN
        EXECUTE IMMEDIATE 'drop table r_t7_' || rec.ft ;
    EXCEPTION
        WHEN OTHERS THEN NULL;
    END;

    EXECUTE IMMEDIATE 'create table r_t7_' || rec.ft || '(' ||
    'report_type varchar2(50),' ||
    'report_date date,' ||
    'switch_id number,' ||
    'feat_count number,' ||
    'rental_rate number,' ||
    'discount number,' ||
    'rental_rating number)' ;

    BEGIN
        EXECUTE IMMEDIATE 'drop table r_t9_' || rec.ft ;
    EXCEPTION WHEN OTHERS THEN
        NULL;
    END;

    IF rec.ft &lt;&gt; 'ZZ' THEN
        EXECUTE IMMEDIATE 'create table r_t9_' || rec.ft || '(' ||
        'report_type varchar2(50),' ||
        'report_date date,' ||
        'switch_id number,' ||
        'feat_count number,' ||
        'rental_rate number,' ||
        'discount number,' ||
        'rental_rating number)' ;
    END IF;
END LOOP;
END;
/&lt;/pre&gt;
&lt;p&gt;Now, how to write those reports so they populate the right tables? I know...&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-112838378235187802?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/112838378235187802/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=112838378235187802' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/112838378235187802'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/112838378235187802'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2005/10/you-can-never-have-too-many-tables.html' title='You can never have too many tables'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-112834490700835913</id><published>2005-10-03T13:56:00.000+01:00</published><updated>2005-10-07T16:13:06.166+01:00</updated><title type='text'>Watching the Watcher-Watchers</title><content type='html'>I've just found a process that uses on-update triggers to insert rows into a table:
&lt;pre&gt;
Queue_Monitor_Table
( source_table_name varchar2(30)
  rowid             varchar2(16) /*lovely,  but not the point*/
  enqueued_yn       char(1)
  dequeued_yn       char(1) )
&lt;/pre&gt;
This is processed by a pl/sql "queue_monitor_listener" that is started in a background process.

A "queue_monitor_listener" if you can't guess, repeatedly scans the table for rows where enqueued_yn = 'N' and then it enqueues the rowid to an AQ queue,  called the "row_update_queue".  

When it's happy that a row has been enqueued,  it updates the enqueued_yn flag to "Y".

As you might fear, there is also dequeue process. This also runs in a background job.   When this has successfully dequeued from the row_update_queue, and done its task ( which could be the subject of a new WTF ),  it updates the Queue_Monitor_Table to set dequeued_yn = 'Y'.

Nice.

The fun really seems to have begun when,  in order to improve performance,  it was decided that several "queue_monitor_listener" processes should be started in parallel background processes.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-112834490700835913?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/112834490700835913/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=112834490700835913' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/112834490700835913'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/112834490700835913'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2005/10/watching-watcher-watchers.html' title='Watching the Watcher-Watchers'/><author><name>Adrian</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-112768607939957256</id><published>2005-09-29T08:15:00.000+01:00</published><updated>2005-09-29T08:53:13.866+01:00</updated><title type='text'>Never do in SQL what you can do in PL/SQL</title><content type='html'>&lt;P&gt;Back when I first started out as a trainee Forms developer, one of my colleagues had the bright idea of implementing some "CONNECT BY PRIOR" logic step by step, in Forms. The trigger would add a new blank record to the block, then retrieve the next row into it with SELECT INTO, then loop around until there were no more rows to process or Hell froze over. Perhaps unsurprisingly, it was a close thing.&lt;/P&gt;

&lt;P&gt;I mentioned to Scott Swank that we were always on the lookout for material, and he sent me the following code that he'd come across (after editing it for brevity and anonymity), and somehow it reminded me of that old Forms trigger. This pattern is repeated ten times throughout the code, checking for various child attributes by (how else?) looping through all the records one by one until the desired attribute is found &lt;i&gt;not&lt;/i&gt; to be true (and if something is not untrue then it must be true, right?)&lt;/P&gt;
&lt;pre&gt;PROCEDURE has_an_attribute
    ( x IN VARCHAR2, resultout OUT VARCHAR2 )
IS
    l_parent_id   VARCHAR2 (30);

    CURSOR c_child
    IS
        SELECT an_attribute
        FROM   child_table
        WHERE  parent_id = l_parent_id;
BEGIN
    l_parent_id := some_function(x);
    resultout := 'COMPLETE:Y';

    FOR v_child IN c_child
    LOOP
        IF v_child.an_attribute = 'N'
        THEN
            resultout := 'COMPLETE:N';
            EXIT;
        END IF;
    END LOOP;
END;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-112768607939957256?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/112768607939957256/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=112768607939957256' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/112768607939957256'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/112768607939957256'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2005/09/never-do-in-sql-what-you-can-do-in.html' title='Never do in SQL what you can do in PL/SQL'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-112792469896918665</id><published>2005-09-28T17:18:00.000+01:00</published><updated>2005-09-28T17:28:25.170+01:00</updated><title type='text'>Check List</title><content type='html'>&lt;pre&gt;
( ) Written dodgy concatenated embedded sql?
( ) Wrapped it in shell script?
( ) Littered it with literals?
( ) Included some random control characters?
( ) Released it without checking it works?

( ) Remembered to add the sarcastic comment questioning someone else's ability?
&lt;/pre&gt;
&lt;pre&gt;
# formatting had to be included in select statement
# could this suggest the database could use some normalisation?
strqry="select invoice_line_items.product_code||"
strqry=$strqry"invoice_line_items.customer_type||"
strqry=$strqry"invoice_line_items.product_sku||\n^D"
strqry=$strqry"substr(expiry_date,3,4)||"
strqry=$strqry"to_char(trunc(instant_cost/10000),'FMX')||"
strqry=$strqry"to_char(mod(instant_cost,10000),'FM0999')||"
strqry=$strqry"contract_type"
strqry=$strqry"from invoice_line_items, retail_calendar, customer_contract,"
strqry=$strqry"product_domain"
strqry=$strqry"where last_retail_day &gt;= retail_calendar.retail_day"
strqry=$strqry"and first_retail_day &lt;= retail_calendar.retail_day"
strqry=$strqry"and retail_calendar.day = $day"
strqry=$strqry"and retail_calendar.month = $month"
strqry=$strqry"and retail_calendar.year = $year"
strqry=$strqry"and invoice_line_items.line_code='$flag'"
strqry=$strqry"and customer_contract.line_code='$flag'"
strqry=$strqry"and invoice_line_items.product_code=customer_contract.product_code"
strqry=$strqry"and invoice_line_items.customer_type="
strqry=$strqry"      customer_contract.customer_type"
strqry=$strqry"and invoice_line_items.product_sku="
strqry=$strqry"      customer_contract.product_sku"
if [ $host_id != "-1" ]; then
        strqry=$strqry" and product_domain.host_id = $host_id"
fi
strqry=$strqry"and invoice_line_items.product_code=product_domain.product_code"
strqry=$strqry"and invoice_line_items.customer_type="
strqry=$strqry"      product_domain.customer_type"
strqry=$strqry"and invoice_line_items.product_sku="
strqry=$strqry"      product_domain.product_sku;"

&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-112792469896918665?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/112792469896918665/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=112792469896918665' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/112792469896918665'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/112792469896918665'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2005/09/check-list.html' title='Check List'/><author><name>Adrian</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-112741344976351494</id><published>2005-09-22T19:13:00.000+01:00</published><updated>2005-09-22T19:24:09.770+01:00</updated><title type='text'>Fun with String</title><content type='html'>It seems that my predecessor needed to convert a row of five columns into a column with five rows. Simple enough, you might think, once you realise that you can use a handy collection type in a TABLE() expression. But hey, why stop there when there is a much, much harder way involving a string-to-table function and a self-join on three columns? ...that aren't quite unique... (Table and column names changed to protect the guilty)
&lt;pre&gt;
SELECT ...
FROM   huge_table t
     , TABLE ( SELECT utils.string_to_table
                      ( t2.col1 || ',' || t2.col2 || ',' ||
                        t2.col3 || ',' || t2.col4 || ',' || t2.col5)
               FROM   huge_table t2
               WHERE  t2.switch_id = t.switch_id
               AND    t2.switch_ctn = t.switch_ctn
               AND    t2.phone_prefix = t.phone_prefix
               AND    ROWNUM &amp;lt; 2 )&lt;/pre&gt;
Now if that isn't half ample in the WHERE, I don't know what is.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-112741344976351494?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/112741344976351494/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=112741344976351494' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/112741344976351494'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/112741344976351494'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2005/09/fun-with-string.html' title='Fun with String'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-112676985649478064</id><published>2005-09-15T08:13:00.000+01:00</published><updated>2006-03-17T13:49:24.636Z</updated><title type='text'>Joins explained</title><content type='html'>&lt;p&gt;I must first give credit to Padders for spotting this article a couple of months back, and to Adrian for reminding me about it. He was poised to blog it when Thai pointed out that it had recently been added to Database Debunkings' &lt;a href="http://www.dbdebunk.com/laughcry.html"&gt;"To Laugh Or Cry"&lt;/a&gt; hall of shame. But of course there is no honour among bloggers and it's damned funny, so here it is. Remember to print out the following definitions and keep them by your desk in case you forget what a complex right inner join is:&lt;p&gt;

&lt;blockquote&gt;&lt;b&gt;Don't use joins&lt;/b&gt;
&lt;br&gt;
Joins become a problem with Oracle and SQL Server DBMSs because the two systems have fundamentally different approaches to the concept. Basically, joins don’t always work the same on every DBMS, and you can end up with unexpected result sets. Before we talk about the differences and how to get around them, you should understand the basic types of join clauses:
&lt;ul&gt;&lt;li&gt;&lt;b&gt;Join&lt;/b&gt;
&lt;br&gt;
Joins are powerful SQL commands for creating tables from data that is retrieved from multiple sources.

&lt;/li&gt;&lt;li&gt;&lt;b&gt;Equi-Join&lt;/b&gt;
&lt;br&gt;
Equi-Joins are formed by retrieving all the data from two separate sources and combining it into one, large table.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Inner/Outer Join&lt;/b&gt;
&lt;br&gt;
Inner Joins are joined on the inner columns of two tables. Outer Joins are joined on the outer columns of two tables.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Left/Right Join&lt;/b&gt;
&lt;br&gt;
Left Joins are joined on the left columns of two tables. Right Joins are joined on the right columns of two tables.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Compound/Complex Joins&lt;/b&gt;
&lt;br&gt;
There are also other kinds of joins—left/inner, left/outer, right/inner, and right/outer.&lt;/li&gt;&lt;/ul&gt;The important thing to remember about joins is to &lt;i&gt;not&lt;/i&gt; use them if you want your application to work well with different database servers.
&lt;/blockquote&gt;
&lt;p&gt;I love the way that it's exactly the kind of thing you would make up, if you were 12 and had absolutely no idea how to answer a homework question.&lt;/p&gt;
&lt;p&gt;While I'm at it I can't help quoting a bit more, this time about the well-known ADD command:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;b&gt;ANSI SQL: CREATE, DROP, ADD, UPDATE, DELETE, INSERT, SELECT&lt;/b&gt;
&lt;br&gt;
As a rule, the only commands you should use are:
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;CREATE and DROP for Data Definition Language (DDL).&lt;/li&gt;
   &lt;li&gt;ADD, UPDATE, DELETE and INSERT for Data Manipulation Language (DML).&lt;/li&gt;
   &lt;li&gt;SELECT for data retrieval.&lt;/li&gt;&lt;/ul&gt;
&lt;/blockquote&gt;
From the article &lt;a href="http://builder.com.com/5100-6388-1045051.html" rel="nofollow"&gt;"Database design for platform independence"&lt;/a&gt;, Builder.com 2002.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-112676985649478064?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/112676985649478064/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=112676985649478064' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/112676985649478064'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/112676985649478064'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2005/09/joins-explained.html' title='Joins explained'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-112626885799430972</id><published>2005-09-09T13:10:00.000+01:00</published><updated>2005-09-12T17:28:38.520+01:00</updated><title type='text'>Twirled Half Ample in the WHERE</title><content type='html'>It is of course completely unfair to post this message by someone who clearly does not speak English. Actually you have to admire his valiant effort to describe a problem with dynamic ref cursors in a foreign language, through what must be the world's most eccentric translation software, or possibly using only a rather old dictionary. (Credit also goes to Art Metzer who actually provided a solution.) But it remains our all-time favourite Oracle forum post, so here it is:
&lt;blockquote&gt;Hi!!

&lt;p&gt;I am with one doubts, I mounted one procedure that to need to return a cursor.&lt;/p&gt;

&lt;p&gt;The STRING SQL is must be twirled half ample in the "WHERE".&lt;/p&gt;

&lt;p&gt;For that haven't to make varios ifs, would like to know if is possible to create one parameter that it comes with where and to place in the routine to twirl, I tried to make this but not gave certain.&lt;/p&gt;

&lt;p&gt;It below follows:&lt;/p&gt;

&lt;pre&gt;OPEN RCURSOR FOR SELECT * FROM TABELA1 WHERE CAMPO1 &lt; 10 || VARIAVEL1&lt;/pre&gt;

&lt;p&gt;In var(VARIAVEL1) it would be:&lt;/p&gt;

&lt;pre&gt;'AND CAMPO2 = 3 AND CAMPO3 &gt; = 25'&lt;/pre&gt;

&lt;p&gt;For example, this would be possible?&lt;/p&gt;

&lt;p&gt;Or I will have exactly that to mount one 'IF' giant for to treat all the routine.&lt;/p&gt;

&lt;p&gt;Tks.&lt;/p&gt;
&lt;/blockquote&gt;
See &lt;a href="http://www.orafaq.com/forum/mv/msg/4467/12407/0"&gt;www.orafaq.com/forum/mv/msg/4467/12407/0&lt;/a&gt; for the original post.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-112626885799430972?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/112626885799430972/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=112626885799430972' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/112626885799430972'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/112626885799430972'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2005/09/twirled-half-ample-in-where.html' title='Twirled Half Ample in the WHERE'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-112575471790364853</id><published>2005-09-03T14:34:00.000+01:00</published><updated>2005-09-03T14:40:28.773+01:00</updated><title type='text'>If at first you don't succeed</title><content type='html'>Just came across this in a rather large query I have to fix:
&lt;pre&gt;NVL(di_core.di_tools.area_code_translate(v_switch_id,d.dncode),
    di_core.di_tools.area_code_translate(v_switch_id,d.dncode))&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-112575471790364853?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/112575471790364853/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=112575471790364853' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/112575471790364853'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/112575471790364853'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2005/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:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-112570181032828070</id><published>2005-09-02T23:38:00.000+01:00</published><updated>2005-09-03T14:32:50.640+01:00</updated><title type='text'>Mail it</title><content type='html'>I recently received the following request on a web forum:
&lt;blockquote&gt;Hello,
&lt;br&gt;&lt;br&gt;
Please let me know how can we send an oracle database via e-mail to other people.
Please reply ASAP as it is very urgent. The project is struck because of this.
&lt;br&gt;&lt;br&gt;
Thanks in advance&lt;/blockquote&gt;
Hmm. I replied asking for some descripton of the business requirement, and mentioned exp/imp utilities, .dmp files being typically smaller than an entire database, possibly XML, etc. Back came the reply:
&lt;blockquote&gt;Thank you sir for your inputs.
&lt;br&gt;&lt;br&gt;
Actually I am from core electronics, VLSI background.
&lt;br&gt;&lt;br&gt;
We need to configure a database (it contains all the information of components that can be used).
&lt;br&gt;&lt;br&gt;
I have worked with Access database(which we can send and receive by zipping and sending).
&lt;br&gt;&lt;br&gt;
Now the problem is that the person1 who is else where in globe has to send me the oracle database. Now we dont know how do we do that.We dont even have those passwords or anything... I just have no clue wht it is like .. wht options.. nothing
&lt;br&gt;&lt;br&gt;
Now could you please tell me how can we send the database
&lt;br&gt;&lt;br&gt;
Thanks
&lt;/blockquote&gt;
Oh dear. &lt;i&gt;What is the file extension of the files they are sending you?&lt;/i&gt; I asked. &lt;i&gt;Do you have an Oracle license?&lt;/i&gt; I must admit I had to look up VLSI ("Very Large Systems Integration", of course).

And then when all hope seemed lost:
&lt;blockquote&gt;got my way
&lt;br&gt;&lt;br&gt;
I asked the person having database to put it on FTP...
&lt;br&gt;&lt;br&gt;
i would then be able to get that whole folder and hence the database...
&lt;br&gt;&lt;br&gt;
Thanks for your time&lt;/blockquote&gt;
Problem solved I think.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-112570181032828070?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/112570181032828070/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=112570181032828070' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/112570181032828070'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/112570181032828070'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2005/09/mail-it.html' title='Mail it'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-112548536888644581</id><published>2005-08-31T11:45:00.000+01:00</published><updated>2005-09-09T16:56:08.373+01:00</updated><title type='text'>I'm not making it up</title><content type='html'>This gem is used at times of particularly high throughput to monitor the size of queues.

&lt;pre&gt;
PROCEDURE getqueuecount (
   queuename                  IN       VARCHAR2
  ,agentname                  IN       VARCHAR2
  ,queuecount                 OUT      INTEGER
)
IS
   queueoptions        DBMS_AQ.dequeue_options_t;
   messageproperties   DBMS_AQ.message_properties_t;
   MESSAGE             connect_db_external_q_type;
   messageid           RAW (16);
   nodequeuewaiting    EXCEPTION;
   dequeuewaiting      BOOLEAN                      := TRUE;
   nolock              EXCEPTION;
   PRAGMA EXCEPTION_INIT (nolock, -054);
   PRAGMA EXCEPTION_INIT (nodequeuewaiting, -25228);
BEGIN
   LOCK TABLE q_lock_table IN EXCLUSIVE MODE NOWAIT;
   queuecount                 := 0;
   queueoptions.WAIT          := 1;
   queueoptions.consumer_name := agentname;
   queueoptions.navigation    := DBMS_AQ.first_message;

   BEGIN
      WHILE (dequeuewaiting)
      LOOP
         DBMS_AQ.dequeue (queuename
                         ,queueoptions
                         ,messageproperties
                         ,MESSAGE
                         ,messageid
                         );
         queuecount  :=   queuecount  + 1;
      END LOOP;
   EXCEPTION
      WHEN nodequeuewaiting
      THEN
         dequeuewaiting             := FALSE;
   END;

   ROLLBACK;
EXCEPTION
   WHEN nolock
   THEN
      queuecount                 := -1;
END;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-112548536888644581?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/112548536888644581/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=112548536888644581' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/112548536888644581'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/112548536888644581'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2005/08/im-not-making-it-up.html' title='I&apos;m not making it up'/><author><name>Adrian</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-112541908316530633</id><published>2005-08-30T17:22:00.000+01:00</published><updated>2005-09-03T14:45:02.396+01:00</updated><title type='text'>Nesting instinct</title><content type='html'>It is said that the human brain can retain only seven facts in short term memory at one time. Or something like that. Test yourself anyway with the following example, which occurs in the middle of a 175-line INSERT statement, in a 1200-line package body, all written in much the same self-explanatory style:

&lt;pre&gt;INSERT INTO some_unsuspecting_table
WITH all_dn AS (SELECT ... FROM ...)
SELECT ...
       CASE WHEN SUBSTR(all_dn.dn_data,6,4) IN ('PODN','UNDN')
           THEN SUBSTR(all_dn.dn_data,6,4)
           ELSE
               NVL2
               ( NVL(l.len, substr(a.features,16,15)),
                 DECODE(MAX(CASE WHEN all_dn.dn_data LIKE '%MSN%'
                                 THEN 2
                                 ELSE
                                     CASE WHEN all_dn.dn_data LIKE '%TWDN%'
                                          THEN 1
                                     END
                            END)
                        OVER (PARTITION BY NVL(l.len, SUBSTR(a.features,16,15) ) ),
                        2, 'MSN',
                        1, 'TWDN', 'LINE' ),
                 CASE WHEN all_dn.dn_data LIKE '%MSN%'
                      THEN 'MSN'
                      ELSE all_dn.dn_data
                 END )
       END main_service_type
     , ...and so on...
FROM   etc etc;&lt;/pre&gt;

Now, how many levels of nesting was that?

What, you passed out somewhere around &lt;tt&gt;OVER (PARTITION BY NVL(l.len, SUBSTR(a.features,16,15) ) )&lt;/tt&gt;? Shame on you.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-112541908316530633?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/112541908316530633/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=112541908316530633' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/112541908316530633'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/112541908316530633'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2005/08/nesting-instinct.html' title='Nesting instinct'/><author><name>William Robertson</name><uri>http://www.blogger.com/profile/06976436975493102341</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.williamrobertson.pwp.blueyonder.co.uk/gifs/starfield.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-112541646749936272</id><published>2005-08-30T16:39:00.000+01:00</published><updated>2005-08-30T17:29:49.796+01:00</updated><title type='text'>The little things that snowball</title><content type='html'>There's nothing more I can say about this.
&lt;pre&gt;CREATE TABLE INVOICE_LINEITEM 
(
...
...
MONTH_OF_YEAR   CHAR(1)
...
)&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-112541646749936272?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/112541646749936272/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=112541646749936272' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/112541646749936272'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/112541646749936272'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2005/08/little-things-that-snowball.html' title='The little things that snowball'/><author><name>Adrian</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15861274.post-112539963447768618</id><published>2005-08-30T11:57:00.000+01:00</published><updated>2005-09-15T23:27:07.050+01:00</updated><title type='text'>Avoiding the overhead of SQL</title><content type='html'>Ok,  I'll go first,  even though this is more of a "whyTF".  

Have a look at this piece of genius.

I've only pulled the bare bones because these scripts are HUGE.

Names are changed for the usual reasons.

&lt;em&gt;dumpdb.sh follows:&lt;/em&gt;

&lt;pre&gt;
#!/bin/ksh

function showtables
{
  cat &lt;&lt; EOF
acc:client_account
amt:client_model_type
...
700 lines later
...
ugp:ultimate_group_parameter
vap:validation_parameter
EOF
}

function execSQL
{
eval "echo \"$SQL_HEADER$1$SQLTRAILER\" &amp;#92;
  |sqlplus -S $ORACONNECT   |path=/usr/xpg4/bin:"$PATH" awk -F: $AWK_PROG &amp;#92;
  | sed 's/::/: :/g' | sed 's/~:/:/g' &amp;#92;
  $OUT_FILTER &amp;#92;
  $ OUTPUT"
}
.
. 700 functions like this, one per table.
.
function fDump_client
{
    execSQL "select * from client;"
}
.

for table in $tables_to_dump
do
    if [[ "$TO_TAB_FILE" == "Y" ]]; then
        ## Send output to file named &amp;lttable&amp;gt.csv
        export OUTPUT=" &amp;gt $table.csv"
        echo "Dumping $table to $table.csv"
    fi
    # Get filter if required

    if [[ $? -eq 0 ]]; then
        # There is a specific function for this table so use it
        fDump_${table}

    else
        # No function - just use default SELECT
        execSQL "select * from ${table};"
    fi
done

&lt;/pre&gt;


&lt;em&gt;which is called by "application support scripts" as demonstrated:&lt;/em&gt;


&lt;pre&gt;
#!/bin/ksh

function select_client_access_type
{
    
    # dbselect gives:
    #
    # 1 CLIENT_KEY         NOT NULL CHAR(3)
    # 2 MEMBER_KEY         VARCHAR2(4)
    # 3 NAME               VARCHAR2(50)
    # 4 PHONE              VARCHAR2(22)
    # 5 ACCESS_ENABLED     VARCHAR2(1)
    # 6 ACCESS_TYPE        CHAR(1)
    # 7 MM_AND_OR_CLIENT   VARCHAR2(1)
    # 8 RIGHTS_GROUP_ID    NUMBER(4)
    # 9 MANAGER_ID         NUMBER(38)

    IFS=:
    if ! set -- $(dumpdb | grep "^${CLIENT_KEY}:")
    then
        echo "CLIENT '$CLIENT_KEY' not found"
        exit $EXIT_NO_CLIENT
    fi

    MEMBER_KEY="$2"
    ACCESS_ENABLED="$5"
    ACCESS_TYPE="$6"
    MM_AND_OR_CLIENT="$7"
    RIGHTS_GROUP_ID="$8"

    if [[ $ACCESS_ENABLED != Y ]]
    then
    if [[ $ACCESS_TYPE != T ]]
    then
        echo "CLIENT ACCESS_TYPE is $ACCESS_TYPE"
    fi
    fi
}
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15861274-112539963447768618?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/112539963447768618/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15861274&amp;postID=112539963447768618' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/112539963447768618'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15861274/posts/default/112539963447768618'/><link rel='alternate' type='text/html' href='http://oracle-wtf.blogspot.com/2005/08/avoiding-overhead-of-sql.html' title='Avoiding the overhead of SQL'/><author><name>Adrian</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry></feed>
