<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.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:feedburner="http://rssnamespace.org/feedburner/ext/1.0"><id>tag:blogger.com,1999:blog-8884584404576003487</id><updated>2009-07-10T01:15:31.823-04:00</updated><title type="text">ORACLENERD</title><subtitle type="html" /><link rel="alternate" type="text/html" href="http://www.oraclenerd.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default?start-index=26&amp;max-results=25" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://www.oraclenerd.com/atom.xml" /><author><name>oraclenerd</name><uri>http://www.blogger.com/profile/12412013306950057961</uri><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>285</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><link rel="self" href="http://feeds.feedburner.com/oraclenerd/RahJ" type="application/atom+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry><id>tag:blogger.com,1999:blog-8884584404576003487.post-3041890002040586614</id><published>2009-07-09T22:16:00.004-04:00</published><updated>2009-07-09T22:45:44.648-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="oel" /><category scheme="http://www.blogger.com/atom/ns#" term="virtualbox" /><title type="text">OEL: VirtualBox Guest Additions</title><content type="html">Thankfully, I managed to get Oracle (the Database) installed on Oracle (the Enterprise Linux).  No easy task for a rookie.&lt;br /&gt;&lt;br /&gt;Like most people, I don't like the 1024x768 default resolution, so I tried to install the VirtualBox Guest Additions.  I've tried like 22 times now.  Here are the 2 different errors I would find:&lt;pre class="code"&gt;[root@cent-1 VBOXADDITIONS_2.2.4_47978]# /bin/bash ./VBoxLinuxAdditions-x86.run&lt;br /&gt;Verifying archive integrity... All good.&lt;br /&gt;Uncompressing VirtualBox 2.2.4 Guest Additions for Linux installation&lt;br /&gt;.....................................................................&lt;br /&gt;.....................................................................&lt;br /&gt;.....................................................................&lt;br /&gt;...............&lt;br /&gt;VirtualBox 2.2.4 Guest Additions installation&lt;br /&gt;This system does not seem to have support for OpenGL direct rendering.&lt;br /&gt;VirtualBox requires Linux 2.6.27 or later for this.  Please see the log&lt;br /&gt;file /var/log/vboxadd-install.log &lt;br /&gt;if your guest uses Linux 2.6.27 and you still see this message.&lt;/pre&gt;/var/log/vboxadd-install.log looks like this:&lt;pre class="code"&gt;Installing VirtualBox 2.2.4 Guest Additions, built Fri May 29 19:13:34 CEST 2009&lt;br /&gt;&lt;br /&gt;Testing the setup of the guest system&lt;br /&gt;&lt;br /&gt;Could not find the Linux kernel header files - &lt;br /&gt;the directories /lib/modules/2.6.18-128.e15/build/include &lt;br /&gt;and /usr/src/linux/include do not exist.&lt;br /&gt;Giving up due to the problems mentioned above.&lt;/pre&gt;I googled "OpenGl direct rendering" and found &lt;a href="http://digitizor.com/2009/06/17/fix-no-support-opengl-direct-rendering-error-virtualbox-guest-additions-installation/"&gt;this&lt;/a&gt; entry.  The suggestion was to add "x11" to the end like this:&lt;pre class="code"&gt;/bash/bin ./VBoxLinuxAdditions-x86.run &lt;b&gt;x11&lt;/b&gt;&lt;/pre&gt;Tried that out and I got a different error, but one that matched what the log says, something like "install kernel headers" blah blah blah.  Greek.&lt;br /&gt;&lt;br /&gt;I tried using apt-get...it apprently doesn't exist on OEL (or Red Hat derivatives).  Ubuntu has dpkg...which doesn't work in OEL.  yum!  Let's try yum.  Where do I find the kernel headers?&lt;br /&gt;&lt;br /&gt;Online?  &lt;br /&gt;&lt;br /&gt;No.&lt;br /&gt;&lt;br /&gt;I wonder if they exist on the iso images?&lt;br /&gt;&lt;br /&gt;So I load up Enterprise-R5-U3-Server-i386-disc1.iso, navigate to the Server directory:&lt;pre class="code"&gt;&lt;table style="width:auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="http://picasaweb.google.com/lh/photo/qShhtMIOf-7fjXzSeu3M_A?feat=embedwebsite"&gt;&lt;img src="http://lh4.ggpht.com/_rhCtHYLiamQ/SlaojtUnlKI/AAAAAAAAElM/dsBph9sNkp8/s800/ls_ker.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/pre&gt;(Yes, it's a picture.  I can't copy out of the guest yet...shut up).&lt;br /&gt;&lt;br /&gt;Let's try kernel-headers (couldn't be that obvious could it?)&lt;pre class="code"&gt;[root@oracledb Server]# rpm -ivh kernel-headers-2.6.18-128.e15.i386.rpm&lt;br /&gt;warning: kernel-headers-2.6.18-128.e15.i386.rpm:  Header V3 DSA signature:  &lt;br /&gt;NOKEY, key ID 1e5e0159&lt;br /&gt;Preparing...               ################################### [100%]&lt;br /&gt;    package kernel-headers-2.6.18-128.e15.i386.rpm is already installed&lt;br /&gt;[root@oracledb Server]#&lt;/pre&gt;With a tried and true method, I select the next one, kernel-devel.  I'm not typing this one up.  I guess I should put the name here, in case someone is googling for it:  kernel-devel-2.6.18-128.e15.i686.rpm&lt;br /&gt;&lt;br /&gt;That one installed.  Unmount the OEL disc, remount the VBOX Guest Additions, /bin(g)/bash(bang) ./VBOXADDITIONS_2.2.4_47978(boom) and I'm done.  Now I just need to reboot to see if it &lt;i&gt;really&lt;/i&gt; works.&lt;br /&gt;&lt;br /&gt;Why can't &lt;a href="http://theappslab.com/2009/07/06/it-just-works-my-new-mantra/"&gt;it just work&lt;/a&gt;?&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-3853911845992923";
/* atom feed */
google_ad_slot = "1428191201";
google_ad_width = 728;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8884584404576003487-3041890002040586614?l=www.oraclenerd.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/RVpvdLy2WoXUEITklXf6r7Z-eU4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/RVpvdLy2WoXUEITklXf6r7Z-eU4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/RVpvdLy2WoXUEITklXf6r7Z-eU4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/RVpvdLy2WoXUEITklXf6r7Z-eU4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/3041890002040586614/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8884584404576003487&amp;postID=3041890002040586614" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/3041890002040586614" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/3041890002040586614" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/oraclenerd/RahJ/~3/aZoOYIfd5vE/oel-virtualbox-guest-additions.html" title="OEL: VirtualBox Guest Additions" /><author><name>oraclenerd</name><uri>http://www.blogger.com/profile/12412013306950057961</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="03223434293565733241" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/_rhCtHYLiamQ/SlaojtUnlKI/AAAAAAAAElM/dsBph9sNkp8/s72-c/ls_ker.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://www.oraclenerd.com/2009/07/oel-virtualbox-guest-additions.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-8884584404576003487.post-4233340970346185989</id><published>2009-07-08T23:18:00.003-04:00</published><updated>2009-07-08T23:42:59.235-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="LC" /><category scheme="http://www.blogger.com/atom/ns#" term="funny" /><category scheme="http://www.blogger.com/atom/ns#" term="family" /><title type="text">Stories of LC</title><content type="html">LC being Little Chet.  And no that is not some perverted reference...&lt;br /&gt;&lt;br /&gt;He said something pretty funny the other day, which reminded me of a bunch of little stories about him.  Since I post so many stories about &lt;a href="http://oraclenerd.com/labels/kate.html"&gt;Kate&lt;/a&gt;, I figured it's about time I do one on him.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Policy&lt;/b&gt;&lt;br /&gt;I get a cup of ice cream the other night and he immediately wants some too.  Mom asks if he has had any that day, and he replies, "Yes."&lt;br /&gt;&lt;br /&gt;"But there is no policy on ice cream."&lt;br /&gt;&lt;br /&gt;Me:  "No What?"&lt;br /&gt;&lt;br /&gt;LC:  "No policy."&lt;br /&gt;&lt;br /&gt;Kris and I look at each other and just start laughing.  He's 6 years old and he's talking about policy?  He's been hanging out with his mother way too much.&lt;br /&gt;&lt;br /&gt;To make sure we knew that he knew what he was talking about we asked him what he meant.&lt;br /&gt;&lt;br /&gt;LC:  "Well, I can have 2 popsicles a day.  But there's no limit on ice cream."&lt;br /&gt;&lt;br /&gt;Wow.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The Letter R&lt;/b&gt;&lt;br /&gt;In Pre-K 4 a couple of years ago, his teacher asked the class to say words that began with the letter R.&lt;br /&gt;&lt;br /&gt;The teacher started them off, "Rapunzel."&lt;br /&gt;&lt;br /&gt;"Rabbit!"&lt;br /&gt;&lt;br /&gt;"Rainbow."&lt;br /&gt;&lt;br /&gt;"Chet, do you have one?"&lt;br /&gt;&lt;br /&gt;"Craphead"&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Sea World&lt;/b&gt;&lt;br /&gt;After a day at Sea World with my parents and 2 small kids, we naturally gravitated to the Hospitality Suite.  For those who don't know, Anheuser Busch used to own Busch Gardens and Sea World.  Both parks, or both companies as there are more than one park for each, serve free beer.  There is a two beer limit.&lt;br /&gt;&lt;br /&gt;Anyway, Kris takes this opportunity to spend some time with Chet and she walks him over to the Clydesdales (while I drink her beer).&lt;br /&gt;&lt;br /&gt;Mom and son, holding hands...a perfect picture.&lt;br /&gt;&lt;br /&gt;"Mom, that's the biggest penis I've ever seen."&lt;br /&gt;&lt;br /&gt;All the people around them began laughing...OMG.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Jackass&lt;/b&gt;&lt;br /&gt;I believe this happened in 2006, while in Gainesville.  I would drive Chet to school, St. Patrick's Catholic school.  This was always a concern of mine because I have never been too careful with my choice of words around him.  &lt;br /&gt;&lt;br /&gt;My old boss had once shared a story with me about her daughter, at this same school, saying JFC (Jesus F$#%*&amp;% Christ).  I always thought the same would happen to me.&lt;br /&gt;&lt;br /&gt;It never did.  He had amazing control (besides the craphead comment above) at school.&lt;br /&gt;&lt;br /&gt;At school.&lt;br /&gt;&lt;br /&gt;Not at Publix though.&lt;br /&gt;&lt;br /&gt;We're shopping one day with him sitting in the basket when this woman comes out of the aisle and gets in front of us.&lt;br /&gt;&lt;br /&gt;"Move that F$#%*&amp;% Cart!"&lt;br /&gt;&lt;br /&gt;It was about all I could do to maintain composure.  He was 3, maybe 4 at the time.  Thankfully, the woman did not hear him.  If she had, I probably would have fallen down from laughing so hard.&lt;br /&gt;&lt;br /&gt;However, I managed to compose myself and give him a stern lecture about how inappropriate that was.&lt;br /&gt;&lt;br /&gt;I couldn't wait to get home to tell Kris.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The First Word&lt;/b&gt;&lt;br /&gt;I've probably talked about this before.  Yes, I have.  &lt;a href="http://www.oraclenerd.com/2009/04/kate.html"&gt;Here&lt;/a&gt;.  The similarity between my name and shit.  I've heard it all before...I actually used to introduce myself referencing &lt;a href="http://www.imdb.com/title/tt0090305/"&gt;Weird Science&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Me:  "Hi, I'm Chet"&lt;br /&gt;&lt;br /&gt;Them:  "Ted?"&lt;br /&gt;&lt;br /&gt;Me:  "Chet"&lt;br /&gt;&lt;br /&gt;Them:  "Jeff"&lt;br /&gt;&lt;br /&gt;Repeat this a few more times.&lt;br /&gt;&lt;br /&gt;Finally I'd say, "You know, "Chet" like the guy from Weird Science?"&lt;br /&gt;&lt;br /&gt;Them:  "Ohhhhh...yeah, the big pile of shit!"&lt;br /&gt;&lt;br /&gt;Me:...&lt;br /&gt;&lt;br /&gt;That reference is only useful with people of a certain age.  Twenty-somethings don't really get it.&lt;br /&gt;&lt;br /&gt;Anyway, I always thought I could get away with teaching Chet that for his first word.  Chet.  Shit.  Pretty close right?  I can't remember if he actually said it for his first word...it's a funny story none-the-less.&lt;br /&gt;&lt;br /&gt;I know I'm not the only one with funny child stories.  Anyone care to share?&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-3853911845992923";
/* atom feed */
google_ad_slot = "1428191201";
google_ad_width = 728;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8884584404576003487-4233340970346185989?l=www.oraclenerd.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/1to35tOdtnLxXnxrYFINwcSSw9A/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/1to35tOdtnLxXnxrYFINwcSSw9A/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/1to35tOdtnLxXnxrYFINwcSSw9A/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/1to35tOdtnLxXnxrYFINwcSSw9A/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/4233340970346185989/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8884584404576003487&amp;postID=4233340970346185989" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/4233340970346185989" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/4233340970346185989" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/oraclenerd/RahJ/~3/pOoMmQW38Bc/stories-of-lc.html" title="Stories of LC" /><author><name>oraclenerd</name><uri>http://www.blogger.com/profile/12412013306950057961</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="03223434293565733241" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">4</thr:total><feedburner:origLink>http://www.oraclenerd.com/2009/07/stories-of-lc.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-8884584404576003487.post-7601035064238948589</id><published>2009-07-08T17:33:00.003-04:00</published><updated>2009-07-08T17:52:45.530-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="documentation" /><category scheme="http://www.blogger.com/atom/ns#" term="database" /><category scheme="http://www.blogger.com/atom/ns#" term="oracle" /><title type="text">Oracle Concepts:  The Data Dictionary</title><content type="html">I have come to rely pretty heavily on the Data Dictionary as I don't typically use a GUI.  This stems from the fact that in my first professional IT job (reporting off of Oracle), I was given a tnsnames.ora file and something called SQL*Plus.  I came from Microsoft Access...I wanted pretty pictures of my database objects.  My first year was spent asking how to find the tables in a schema (schema?  what's that?), how to view the SQL that made up a view, and how to view the source code.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Find Tables&lt;/b&gt;&lt;pre class="code"&gt;SELECT * FROM user_tables;&lt;/pre&gt;&lt;b&gt;View Text&lt;/b&gt;&lt;pre class="code"&gt;SET LONG 100000&lt;br /&gt;SELECT text FROM user_views WHERE view_name = :your_view;&lt;/pre&gt;&lt;b&gt;View Source&lt;/b&gt;&lt;pre class="code"&gt;SELECT line, text &lt;br /&gt;FROM user_source &lt;br /&gt;WHERE name = :package_name&lt;br /&gt;  AND type = :package_spec_or_package_body;&lt;/pre&gt;Needless to say it wasn't fun.&lt;blockquote&gt;Without pain there is no progress.&lt;/blockquote&gt;What is the &lt;a href="http://download.oracle.com/docs/cd/B28359_01/server.111/b28318/datadict.htm#i2112"&gt;Data Dictionary&lt;/a&gt;?&lt;blockquote&gt;...data dictionary, which is a read-only set of tables that provides information about the database. A data dictionary contains:&lt;br /&gt;&lt;br /&gt;*  The definitions of all schema objects in the database (tables, views, indexes, clusters, synonyms, sequences, procedures, functions, packages, triggers, and so on)&lt;br /&gt;*  How much space has been allocated for, and is currently used by, the schema objects&lt;br /&gt;*  Default values for columns&lt;br /&gt;*  Integrity constraint information&lt;br /&gt;*  The names of Oracle Database users&lt;br /&gt;*  Privileges and roles each user has been granted&lt;br /&gt;*  Auditing information, such as who has accessed or updated various schema objects&lt;br /&gt;*  Other general database information&lt;br /&gt;&lt;/blockquote&gt;Not completely read-only as I found out &lt;a href="http://www.oraclenerd.com/2008/11/javaplsql-port-scanner-ii.html"&gt;once&lt;/a&gt;.  What's the point?  None really.  I just like being able to copy and paste the documentation.  OK, that's only partially true.  &lt;br /&gt;&lt;br /&gt;All the information that you retrieve via your nice GUI interface comes from these tables.  SQL Developer, JDeveloper, Toad, etc.  I believe some even have an option to view the SQL being submitted to the database.  If you haven't used (knowingly) the Data Dictionary before, check it out.  You can easily view all 651 views (10gR2) by issuing:&lt;pre class="code"&gt;SELECT * FROM dictionary;&lt;/pre&gt;Happy hunting.&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-3853911845992923";
/* atom feed */
google_ad_slot = "1428191201";
google_ad_width = 728;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8884584404576003487-7601035064238948589?l=www.oraclenerd.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/tRcHupqA3qnFoDChzTGRw6gplsI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/tRcHupqA3qnFoDChzTGRw6gplsI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/tRcHupqA3qnFoDChzTGRw6gplsI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/tRcHupqA3qnFoDChzTGRw6gplsI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/7601035064238948589/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8884584404576003487&amp;postID=7601035064238948589" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/7601035064238948589" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/7601035064238948589" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/oraclenerd/RahJ/~3/esE6FXa8yeg/oracle-concepts-data-dictionary.html" title="Oracle Concepts:  The Data Dictionary" /><author><name>oraclenerd</name><uri>http://www.blogger.com/profile/12412013306950057961</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="03223434293565733241" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://www.oraclenerd.com/2009/07/oracle-concepts-data-dictionary.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-8884584404576003487.post-4021267802983220481</id><published>2009-07-08T00:56:00.006-04:00</published><updated>2009-07-08T01:09:41.218-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="dba" /><category scheme="http://www.blogger.com/atom/ns#" term="database" /><category scheme="http://www.blogger.com/atom/ns#" term="oracle" /><title type="text">Oracle:  Getting Started</title><content type="html">A friend of mine recently expressed interest in learning Oracle.&lt;br /&gt;&lt;br /&gt;Here's what I sent him:&lt;blockquote&gt;Start here: &lt;br /&gt;&lt;br /&gt;Oracle Concepts Guide - &lt;a href="http://download.oracle.com/docs/cd/B28359_01/server.111/b28318/toc.htm"&gt;http://download.oracle.com/docs/cd/B28359_01/server.111/b28318/toc.htm&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You don’t have to read everything, but it’s probably the best place to start.  I’d be more than happy to answer some of the more “inane” questions (How do I do this?  How do I connect?  Etc).&lt;br /&gt;&lt;br /&gt;Oracle Documentation (List of Books) - &lt;a href="http://www.oracle.com/pls/db111/portal.all_book"&gt;http://www.oracle.com/pls/db111/portal.all_books&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Don’t be overwhelmed by that.  It’s ridiculous how much stuff there is out there.  I list some books out by discipline:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;DBA&lt;/b&gt;&lt;br /&gt;--&amp;nbsp;&amp;nbsp;2 Day DBA - &lt;a href="http://download.oracle.com/docs/cd/B28359_01/server.111/b28301/toc.htm"&gt;http://download.oracle.com/docs/cd/B28359_01/server.111/b28301/toc.htm&lt;/a&gt;&lt;br /&gt;----&amp;nbsp;&amp;nbsp;Easiest place to start (after the Concepts Guide)&lt;br /&gt;--&amp;nbsp;&amp;nbsp;Oracle Database Administrator’s Guide - &lt;a href="http://download.oracle.com/docs/cd/B28359_01/server.111/b28310/toc.htm"&gt;http://download.oracle.com/docs/cd/B28359_01/server.111/b28310/toc.htm&lt;/a&gt;&lt;br /&gt;----&amp;nbsp;&amp;nbsp;Definitely getting into the nitty gritty stuff here.&lt;br /&gt;&lt;b&gt;Developer&lt;/b&gt;&lt;br /&gt;--&amp;nbsp;&amp;nbsp;PL/SQL Language Reference - &lt;a href="http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28370/toc.htm"&gt;http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28370/toc.htm&lt;/a&gt;&lt;br /&gt;----&amp;nbsp;&amp;nbsp;That should help you get started with PL/SQL if you so choose&lt;br /&gt;&lt;br /&gt;For either role, the bible is probably the SQL Language Reference manual:  &lt;a href="http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/toc.htm"&gt;http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/toc.htm&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Usually what I do, is just download the software and try to get it running.  It’s super easy on Windows, a bit more difficult on *nix environments (I just recently installed Oracle on Oracle Enterprise Linux, my first go at a non-Windows environment).&lt;br /&gt;&lt;br /&gt;The documentation above is for 11g, the latest version.  You can get the software here:  &lt;a href="http://www.oracle.com/technology/software/products/database/index.html"&gt;http://www.oracle.com/technology/software/products/database/index.html&lt;/a&gt;  I’d suggest installing EE, might as well go full boat.  Plus, it doesn’t really make a difference resource wise.  If you have 1.5 to 2GB RAM, you should have plenty.  You can run an instance at about 512MB.&lt;br /&gt;&lt;br /&gt;It requires an account (free) and they do not spam.&lt;br /&gt;&lt;br /&gt;Also, try Oracle Database XE, a free (as in beer) standalone edition built off of the 10.2 kernel.  Application Express is used as the front end (a pretty sweet GUI tool).&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.oracle.com/technology/software/products/database/xe/index.html"&gt;http://www.oracle.com/technology/software/products/database/xe/index.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Hope that doesn’t scare you off too much.  ;)&lt;/blockquote&gt;Any other pointers?  I know there are tons of books so link them up if you feel they are worthy.&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-3853911845992923";
/* atom feed */
google_ad_slot = "1428191201";
google_ad_width = 728;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8884584404576003487-4021267802983220481?l=www.oraclenerd.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/bysUMbmsqMEXzP3fCxBxP1khnj0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/bysUMbmsqMEXzP3fCxBxP1khnj0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/bysUMbmsqMEXzP3fCxBxP1khnj0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/bysUMbmsqMEXzP3fCxBxP1khnj0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/4021267802983220481/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8884584404576003487&amp;postID=4021267802983220481" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/4021267802983220481" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/4021267802983220481" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/oraclenerd/RahJ/~3/8UhiM8aLHLY/oracle-getting-started.html" title="Oracle:  Getting Started" /><author><name>oraclenerd</name><uri>http://www.blogger.com/profile/12412013306950057961</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="03223434293565733241" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">6</thr:total><feedburner:origLink>http://www.oraclenerd.com/2009/07/oracle-getting-started.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-8884584404576003487.post-4971121303689853024</id><published>2009-07-07T17:15:00.001-04:00</published><updated>2009-07-07T17:23:27.866-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="plsql" /><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="ideas" /><category scheme="http://www.blogger.com/atom/ns#" term="development" /><category scheme="http://www.blogger.com/atom/ns#" term="humility" /><category scheme="http://www.blogger.com/atom/ns#" term="design" /><category scheme="http://www.blogger.com/atom/ns#" term="funny" /><title type="text">Classic:  Application Developers vs. Database Developers II</title><content type="html">&lt;i&gt;The original (with all the fun comments) can be found &lt;a href="http://www.oraclenerd.com/2008/12/application-developers-vs-database.html"&gt;here&lt;/a&gt;.  Originally posted on December 9, 2008.  This is the "followup" to yesterday's &lt;a href="http://www.oraclenerd.com/2009/07/classic-application-developers-vs.html"&gt;post&lt;/a&gt;.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;You can read the first article &lt;a href="http://www.oraclenerd.com/2008/02/application-developers-vs-database.html"&gt;here&lt;/a&gt;.  My application developer friend, Mr. M, emailed me and another fine gentleman this little blurb recently:&lt;br /&gt;&lt;br /&gt;Mr. M:&lt;br /&gt;&lt;blockquote&gt;OH YEAH BABY!!! TEN TIMES FASTER!!!! YEAH!!!!!!!!&lt;br /&gt;&lt;br /&gt;Hey seriously, what a tub of shit Oracle is. Where does this myth come from that it's such a great platform? Their client tools suck balls and it's generally just a pain in the ass to work with from a developer's point of view. But devs for some reason are under this impression that from thew server perspective it's rock solid and performant. Well, it may be solid, but it's a fucking turd. Our dba here - definitely an Oracle guy - has been tasked with looking into moving us onto an oss db. He basically refuses to even look at MySQL, stating that it's a mickey mouse worthless pile of shit (can't really argue with him there lol), so that basically leaves Postgres. So it's been a few weeks now, and he will basically admit now that Postgres completely waxes Oracle as far as performance goes. LOL We run RAC in production too. He's looking at failover, replication, blah blah blah now, we'll see what the verdict on that is. Oh, and Oracle AQ? That's a worthless pile of shit too. Why do they tack a fucking message queue that doesn't play nice with jms onto the fucking database, which is probably already overworked? Oh wait, that's right, they're in the business of selling per cpu licenses! Cocksuckers.&lt;/blockquote&gt;This was prompted by a recent Oracle email blast about the Exadata storage system/Warehouse.&lt;br /&gt;&lt;br /&gt;As I did before, I'll just put the email here.&lt;br /&gt;&lt;br /&gt;Me:&lt;br /&gt;&lt;blockquote&gt;Agreed, their client tools aren't all the great.  Which ones are you using?&lt;br /&gt;&lt;br /&gt;I use SQL*Plus (naturally), SQL Developer and JDeveloper.  The latter 2 tie in very nicely with Subversion.  With JDeveloper, when I want to try out Java, it's got a pretty good suite of tools. &lt;br /&gt;&lt;br /&gt;Oracle starting out catering to businesses, Microsoft started with the consumer.  Oracle has made pretty good strides in making their software more usable while Microsoft has made theirs more scalable.&lt;br /&gt;&lt;br /&gt;I haven't used AQ a whole lot and definitely not with Java.  I do know that it's billed as JMS compliant.&lt;br /&gt;&lt;br /&gt;Postgres has it's place and so does Oracle.  It is a great platform if you know how to leverage it.  PL/SQL is a 3GL (or is it 4) and you can write entire applications using it...and if you do that right, an incredibly robust and scalable application at that.&lt;/blockquote&gt;Mr. M:&lt;blockquote&gt;&lt;br /&gt;"It is a great platform if you know how to leverage it.  PL/SQL is a 3GL (or is it 4) and you can write entire applications using it...and if you do that right, an incredibly robust and scalable application at that."&lt;br /&gt;&lt;br /&gt;NO!!! NO!!! NOOOOO!!!&lt;br /&gt;&lt;br /&gt;I want to beat people like you who say this with a ball pean hammer. There are only a select few individuals on this earth who can write and read application logic written in SQL. AVOID THIS ANTI-PATTERN AT ALL COSTS! What is it with you f_cking database guys??? Why do you always want to stuff as much crap into the db as possible?&lt;br /&gt;&lt;br /&gt;DUDE! SQL IS A PILE OF SHIT FOR EXPRESSING APPLICATION LOGIC!!!&lt;br /&gt;&lt;br /&gt;It's fine for querying and manipulating sets of data, in a relational database. But it is a worthless sack of shit for expressing application logic!&lt;br /&gt;&lt;br /&gt;I'm having to dig through this f_cking abortion right now because some Oracle f_ckhead thought "you can write entire applications using it!" Blog that, mofo!&lt;/blockquote&gt;This was followed by a package he had been working on.  I wouldn't say it was the greatest, but it wasn't all bad either.&lt;br /&gt;&lt;br /&gt;Me:&lt;br /&gt;&lt;blockquote&gt;goodness gracious.&lt;br /&gt;&lt;br /&gt;"DUDE! SQL IS A PILE OF SHIT FOR EXPRESSING APPLICATION LOGIC!!!"&lt;br /&gt;&lt;br /&gt;disagree (naturally).  It's incredibly easy to do, you just don't know how yet...and it seems even the Oracle professionals out there don't either.&lt;br /&gt;&lt;br /&gt;I'll tell you this, the crazier the SQL or PL/SQL needed to derive and manipulate data the poorer the design.  Start with a good design and it all becomes very simple.&lt;/blockquote&gt;Of course note the use of "naturally" in my lexicon.  Thanks &lt;a href="http://theappslab.com/"&gt;Jake&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Mr. M:&lt;br /&gt;&lt;blockquote&gt;well dude, we are back to our old discussion - you arguing that procedural sql code is perfectly fine for building apps, and by extension, that the last 20 years of computer science have basically been a misguided lost journey down the meandering, fruitless trail of oop. um.....no. select this from that. otherwise keep that sql crap caged up where it belongs.&lt;br /&gt;&lt;br /&gt;btw, do the db guys here suck? seriously. i'm not competent enough to judge. (to be fair, apparently that crap i sent you is fairly old stuff, but still....)&lt;/blockquote&gt;Me:&lt;br /&gt;&lt;blockquote&gt;I would say, based on limited knowledge of software development, that the OOP movement was started because the database (specifically Oracle) was not mature enough to do what was needed.  Plus, I seem to recall that the OOP movement was supposed to have solved all the world's problems by now.&lt;br /&gt;&lt;br /&gt;It's further propogated due to the needs you specified in our discussion that day at WellCare (i.e. performance).  I still believe that if application developers better understood how a DB works (Oracle, MySQL, SQLServer, etc) they would end up writing less code.  Database constraints alone force you to write less (and better) code simultaneously ensuring good data.&lt;br /&gt;&lt;br /&gt;The code that I did look at (first 1000 lines or so) isn't great. &lt;br /&gt;1.  With all those IF THEN ELSE statements it's telling me that there's probably a better way to store the data.  Looks like they're missing an attribute that should be contained with a track.&lt;br /&gt;2.  using Object (PL/SQL) types to store data in the way they seem to be doing it is not the best way.  Again, probably a design issue.&lt;br /&gt;3.  When you do something like this:&lt;pre class="code"&gt;&lt;br /&gt;   UPDATE pb_album_metadata&lt;br /&gt;      SET primary_digital_flag = 0&lt;br /&gt;    WHERE album_id IN (SELECT b.album_id&lt;br /&gt;                       FROM (SELECT a.album_id AS album_id,&lt;br /&gt;                                MAX(a.album_id) OVER (PARTITION BY a.standard_upc) AS latest_album_id&lt;br /&gt;                             FROM pb_album_metadata a&lt;br /&gt;                             WHERE a.standard_upc = g_album_tab(1).standard_upc ) b&lt;br /&gt;                       WHERE b.album_id &lt;&gt; b.latest_album_id )&lt;br /&gt;         AND primary_digital_flag &lt;&gt; 0;&lt;/pre&gt;&lt;br /&gt;They should probably have considered end_date as an attribute of the album metadata.  While analytic functions are pretty cool, they're more for analyzing (OLAP) and not OLTP environments.&lt;br /&gt;&lt;br /&gt;That's for starters and without table definitions...&lt;/blockquote&gt;Me (again):&lt;br /&gt;&lt;blockquote&gt;oh yeah...and PL/SQL is/was built on top of ADA, FYI.&lt;/blockquote&gt;Mr. M:&lt;br /&gt;&lt;blockquote&gt;"I still believe that if application developers better understood how a DB works (Oracle, MySQL, SQLServer, etc) they would end up writing less code.  Database constraints alone force you to write less (and better) code simultaneously ensuring good data."&lt;br /&gt;&lt;br /&gt;Huh? What are we not understanding? What would be an example of a constraint that would force us to write less and better code?&lt;/blockquote&gt;Me:&lt;br /&gt;&lt;blockquote&gt;CHECK, NOT NULL (same as CHECK) and FOREIGN KEY constraints all fit into that category.&lt;br /&gt;&lt;br /&gt;Instead of having to check if a value is NULL when submitting it to the database, just submit and let the database throw an error, which you'll conveniently capture in your Exception block.  Same goes for CHECK constraints, columnA should be either one of three values (test, test1, test3), you won't have to check that in your application code, just catch the exception. FKs insure good data (proper relationships).&lt;br /&gt;&lt;br /&gt;A different perspective.  If you are going to pay for it, use that damn thing.  If you don't care, don't do it.  But over the course of an "enterprisey" application, you'll end up writing more code and make maintenance that much more difficult (did I do it there?).  Just those constraints will force you and the teams of application developers to put good data into the database.&lt;br /&gt;&lt;br /&gt;You can still do it in the application of course (form validation is a good place)...&lt;/blockquote&gt;Mr. M:&lt;br /&gt;&lt;blockquote&gt;Ahh, jeez dude, I wasn't sure if you were referring to the literal "constraint" or not.&lt;br /&gt;&lt;br /&gt;Dude, even f_cksticks like &lt;strike&gt;redacted&lt;/strike&gt; I think have a decent enough understanding of when and how to use db constraints. It's when you get into things like cursors or cost plans of subselects and anonymous tables (i think that's the name for it - where I say select something from (select some other crap). Then we defer to db gurus like yourself.&lt;br /&gt;&lt;br /&gt;But dude....."you won't have to check that in your application code, just catch the exception".......uh, don't ever repeat that off our little email group. And definitely don't go posting that on your blog. F_ck me man, it's a damn good thing we keep you db folks caged up in that rdbms box....&lt;/blockquote&gt;Me:&lt;br /&gt;&lt;blockquote&gt;So we've had this discussion at work...for a high transaction system, do Java/C/etc handle exceptions well or what?&lt;br /&gt;&lt;br /&gt;Why is it bad to deal with exceptions rather than coding to avoid them?&lt;br /&gt;&lt;br /&gt;I highly doubt even &lt;strike&gt;redacted&lt;/strike&gt; understood database constraints...him and his cohorts believed all database software would be commoditized and MySQL would be king in short order.&lt;/blockquote&gt;Mr. M:&lt;br /&gt;&lt;blockquote&gt;"for a high transaction system"&lt;br /&gt;&lt;br /&gt;Or for any system really....&lt;br /&gt;&lt;br /&gt;To use your example of check constraints (is this value one of....) or not null constraints, checking these rules in the Java code and in the database code would seem to violate DRY. But we do that alot, and it is acceptable in certain cases. For instance, we also probably violate DRY if we're checking this same rule say in Javascript on the front end. But we accept this tiny violation of DRY because it tends to make for a better user experience and as a performance gain too, for we avoid the round trip to the server. Now, what your advocating here is close to the same thing. You're basically saying, don't check for the not null constraint in Java code, just go ahead and hit the database, let the database throw back an exception to the Java code, presumably correct the problem, and then make another roundtrip to the database again. Dude, what are you thinking?!? This to say nothing of the fact that this also could be considered a violation of Fail Fast, and a violation of Defensive Programming - what happens if the dba forgot to add the not null constraint in production?&lt;br /&gt;&lt;br /&gt;Dude, listen to &lt;a href="http://www.theserverside.com/tt/knowledgecenter/knowledgecenter.tss?l=PodcastJohnDavies"&gt;this guy&lt;/a&gt;. For a "high transaction system" basically you want to treat the database, as much as you can, as just a dumb data holder. A f_cking dumpster, that you just throw sh_t into and pull shit back out, using no vendor-specific features if at all possible.&lt;br /&gt;&lt;br /&gt;Again, for we've had this discussion, but even in everyday apps, not just on Wall Street, the database is the bottleneck. And the database is the hardest layer to scale. So given those facts, you should design your app to do as little work in the database as possible.&lt;/blockquote&gt;I was laughing at this point because the link above points to one of our consulting architects (I'm not really sure what his role is at this point).&lt;br /&gt;Me:&lt;br /&gt;&lt;blockquote&gt;i agree in any application that you want to minimize the number of round trips...&lt;br /&gt;&lt;br /&gt;shocker...he's one of our architects.  he's spot on in many instances, but...&lt;br /&gt;&lt;br /&gt;database is the bottleneck because people don't know how to write SQL.  I'll certainly concede the wall street applications (for the time being anyway), but the rest of us with what we do on a daily basis...Oracle will scale far beyond the demands they place.  When that bottleneck shows up, 9 times out of 10 some dumb-ass c#/java guy thought he could write a better query than i.  besides, what's the idiot doing anything but a simple join anyway?  probably poor data model to start with...and we're right back where we started (sort of).&lt;/blockquote&gt;Mr. M:&lt;br /&gt;&lt;blockquote&gt;"database is the bottleneck because people don't know how to write SQL.....some dumb-ass c#/java guy thought he could write a better query than i."&lt;br /&gt;&lt;br /&gt;Dude, I'll grant you, people don't know how to write SQL, myself included. But that's not always why the database is the bottleneck. I think it's safe to say that's not even the majority of the reason. Yes, there are apps written by people who were just idiots, and they needlessly pummel the database, but that's definitely not the majority of scenarios. At my work the database is the bottleneck, and we run RAC in production. It's my understanding that even with RAC, there is a limit to how much you can scale that out. But any layer up from the database we are basically unlimited in how much we can scale that out. So it's very easy to stick another Apache box in front, or fire up another Weblogic server. But I can't do that with the database. We have 24 Weblogic servers for &lt;strike&gt;redacted&lt;/strike&gt;. The database is the bottleneck. And we don't have shitty sql code in the app. In fact, we have very few hand-written queries anywhere in the app. Persisting something to a database is really a low-level concern that as an application developer I shouldn't even have to be bothered with, except for the rare corner cases where the persistence abstraction I'm using is just a little bit too generic to handle things effectively. And we don't use these ORMs because we don't know how to write sql. To effectively use an ORM tool requires a deeper understanding of sql and databases than simply being able to write solid SQL code. (Not saying Java devs who use ORMs know SQL better than a dba, just that it requires better sql skills than is required of a Java dev to simply write JDBC/SQL.) Now, before you try to tell me that my ORM library isn't able to write as efficient of sql code as a dba of your caliber, keep in mind that ORM tools are pretty advanced. They're able to intelligently do things like batch sql updates, and let you apply transactional semantics much easier than with raw jdbc/sql. But the overwhelming reason developers have so thoroughly adopted ORM is because Structured Query Language is such a nasty piece of shit for expressing application logic. SQL is a declarative, procedural language. It's totally unsuited for writing application logic! This, more than anything else, is why organizations and dev teams should seek to restrict what is handled within a relational database as much as possible - because the programming interface to it is a fucking ancient backward dying dinosaur.&lt;/blockquote&gt;Mr. V (note, not Mr. M):&lt;br /&gt;&lt;blockquote&gt;My 2 canadian cents:&lt;br /&gt;The polyglot approach "... use different languages for different domain ..."&lt;br /&gt;Database was developed to manipulate data and should remain there.&lt;br /&gt;General purpose language was developed to encapsulate logic and should remain in that domain.&lt;br /&gt;You should not use DB to encapsulate business logic (in my opinion) no more than you would use HTML to create complex logic.&lt;br /&gt;&lt;br /&gt;While Java, C#, Python, etc are described as General Purpose languages, they, too, are really domain-constrained.  Their expressiveness are confined (and should be) to express low-level, tersed, explicit, verbose, and repetive logic (if that makes any sense).  Languages such as these are more suitable for low-level abstraction on top of which, richer, more expressive languages can be built.  We are seeing this now with the emergence of languages on the JVM (and arguably on the .Net's CLR).&lt;br /&gt;&lt;br /&gt;I think SQL as we know will take a back seat and a smart developer somewhere will create a new domain-specific language that lives on the VM and will push the SQL expression out of the RDBMS and closer to the code that needs it.  We are not there yet, but Microsfot is trying (see LINQ and all ORM papers).  This is not to say that there won't be isntances where tuning in the SQL-native language won't be necessary.  However, 80 to 90% of simple CRUD cases will be handled closer to the logic code that uses the data code.&lt;br /&gt;&lt;br /&gt;Again, that's my 2 canadian cents... I could go on.  But I have a meeting with &lt;strike&gt;redacted&lt;/strike&gt;.&lt;/blockquote&gt;Mr. V, I believe, is a little bit more sensible.  Mr. M on the other hand is just trying to rile (sp?) me up.&lt;br /&gt;&lt;br /&gt;Me:&lt;br /&gt;&lt;blockquote&gt;Someone will probably create something like that, but it still gets at the heart of one of my arguments, many developers don't know how to use a database thus will go to any means to circumvent it.  Embrace it I say.&lt;br /&gt;&lt;br /&gt;Ultimately for me, it comes down to simplicity.  I can write an application using PL/SQL that will scale very well for 90% of the solutions.  Of course that doesn't include the "fancy" javascript/Ajax stuff needed for the UI.  In my ever so humble opinion, this is a much better solution for a business in the long run.&lt;br /&gt;1.  You're more likely to change the middle tier than the database tier.  Java, asp, Ruby, what's next?&lt;br /&gt;2.  Fewer moving parts means lower cost of ownership, even with the CPU costs.  One person, one, was able to build and maintain a 350 page website.  Be hardpressed to do that with the more expressive languages.&lt;br /&gt;&lt;br /&gt;I think all of us are purists and very passionate about what we do.  It's probably the main reason we get along.  I thoroughly enjoy these conversations because it does force me to think...and that's always a good thing.&lt;/blockquote&gt;Mr. V:&lt;br /&gt;&lt;blockquote&gt;Haaa chet.&lt;br /&gt;You sorta made my point than diverged away.  Building an app in all PL/SQL is dangerous.  It's no safer than me building an app in all Java.  I can build very limited app in all Java.  The moment I need to interact with other domain (UI, data, low-level native code, etc), I have to switch to something that is closer to what I am trying to do.  If I need to create UI, I will pick a ui-centric environment, when I need to talk to DB, I will pass connect to a db and send in my SQL, and so forth.  I will use Java as the glue to bring it all togher. &lt;br /&gt;&lt;br /&gt;In the end, we may be saying the same thing, but using different accent.  O well.&lt;/blockquote&gt;And that's where it ended.  I must say it's always fun.  Mr. M and Mr. V are both very smart individuals and I highly respect what they do.  We have different perspectives...but I think they listen, if only a little, as I listen to them.  Their voices creep up on me especially now...which is definitely a good thing.&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-3853911845992923";
/* atom feed */
google_ad_slot = "1428191201";
google_ad_width = 728;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8884584404576003487-4971121303689853024?l=www.oraclenerd.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/anmcjhcyeT-58hSM9mLMLyXRPpo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/anmcjhcyeT-58hSM9mLMLyXRPpo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/anmcjhcyeT-58hSM9mLMLyXRPpo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/anmcjhcyeT-58hSM9mLMLyXRPpo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/4971121303689853024/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8884584404576003487&amp;postID=4971121303689853024" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/4971121303689853024" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/4971121303689853024" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/oraclenerd/RahJ/~3/WUJcjoPgnGk/classic-application-developers-vs_07.html" title="Classic:  Application Developers vs. Database Developers II" /><author><name>oraclenerd</name><uri>http://www.blogger.com/profile/12412013306950057961</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="03223434293565733241" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://www.oraclenerd.com/2009/07/classic-application-developers-vs_07.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-8884584404576003487.post-325612574443515851</id><published>2009-07-06T21:17:00.002-04:00</published><updated>2009-07-06T21:21:39.358-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="design" /><category scheme="http://www.blogger.com/atom/ns#" term="coherence" /><category scheme="http://www.blogger.com/atom/ns#" term="database" /><category scheme="http://www.blogger.com/atom/ns#" term="oracle" /><title type="text">Classic:  Application Developers vs. Database Developers</title><content type="html">&lt;i&gt;One of my favorite "articles" of all time.  I love these types of conversations, in the DB or the Middle Tier?  For the vast majority of us, the Database will do just fine.  As I've learned more about the data grids and the like, there are trade-offs, which aren't often discussed.  One way or another you lose data (say you decide to only UPDATE one time instead of 60).  Originally posted on February 20, 2008.  Enjoy.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;It started innocently enough with &lt;a href="http://thedailywtf.com/Articles/Those-Unstable-Databases--An-Interesting-Database-Field.aspx"&gt;this &lt;/a&gt; article.  I sent it out to about 20 colleagues.&lt;br /&gt;&lt;br /&gt;The best line from the article:&lt;br /&gt;"Jerry: "Yeah, databases cause lots of headaches. They crash all the time, corrupt data, etc. Using text files is better."&lt;br /&gt;&lt;br /&gt;One of my more recently arrived colleagues (I'll call him Mr. M) replied to everyone with this statement:&lt;br /&gt;&lt;br /&gt;"Kind of funny actually, databases are less and less important at the large investment banks, where they basically load everything up into a data grid across a several hundred node cluster. Writing to the db is way too slow."&lt;br /&gt;&lt;br /&gt;This started a day long exchange of emails.  What follows is the entire thread (up until my last post tonight).&lt;br /&gt;&lt;br /&gt;Me:&lt;br /&gt;"I would just argue that they don’t necessarily know how to write to databases.  I would however love to see benchmarking done on both methods.  Would be an interesting test..."&lt;br /&gt;&lt;br /&gt;Mr. M:&lt;br /&gt;"Well, my understanding is they just can’t scale out the db enough. Even something like Oracle RAC won’t work. And outside of the military, these are probably the top 1% of programmers in the world building this stuff."&lt;br /&gt;&lt;br /&gt;Me:&lt;br /&gt;"A benchmark would be the only way I would believe it.&lt;br /&gt;&lt;br /&gt;If you said the top 1% of database developers tried it and failed, I would be more likely to agree.&lt;br /&gt;&lt;br /&gt;My experience is that application developers != database developers.  Different type of thinking involved."&lt;br /&gt;&lt;br /&gt;Mr. M:&lt;br /&gt;"'A benchmark would be the only way I would believe it.' &lt;br /&gt;&lt;br /&gt;Do you need a benchmark before you would believe in-memory retrieval is faster than disk retrieval? Essentially, this is what we’re talking about.&lt;br /&gt;&lt;br /&gt;'If you said the top 1% of database developers tried it and failed, I would be more likely to agree. My experience is that application developers != database developers.  Different type of thinking involved.'&lt;br /&gt;&lt;br /&gt;Why? It’s an issue to do with application performance not simply database performance. Database concerns are a subset of application concerns, essentially a specialization, requiring less encompassing knowledge. ;)&lt;br /&gt;&lt;br /&gt;From the article you linked to (http://www.watersonline.com/public/showPage.html?page=432587)&lt;br /&gt;&lt;br /&gt;"Better data management is the answer, says Lewis Foti, manager of high-performance computing and grid at The Royal Bank of Scotland (RBS) global banking and markets. "For very large compute arrays, the key issue is data starvation and saturation. This problem requires data grids with high bandwidth and scalable, parallel access,&lt;br /&gt;...&lt;br /&gt;Banks are learning that data management in a distributed grid environment is very different from online transaction processing. "With so many data sources, distribution channels, demands for aggregation and analytics, surges in data volumes and complex dynamics between the flows, we need to manage 'data in motion' and give up the notion that data is somehow stored. It's dynamic, not static," says Michael Di Stefano, vice president and architect for financial services at GemStone Systems&lt;br /&gt;...&lt;br /&gt;There is even some debate over how small a unit of work can be put on today's grids. Di Stefano at GemStone, for example, says, "One client has gone from 200 trades per second in a program trading application to more than 6,000 trades per second. This shows what the technology can do."&lt;br /&gt;&lt;br /&gt;Yep, the writing is on the wall. Oracle knows it too.&lt;br /&gt;&lt;br /&gt;http://www.google.com/search?hl=en&amp;q=oracle+buys+tangosol&amp;btnG=Google+Search"&lt;br /&gt;&lt;br /&gt;Me:&lt;br /&gt;"Good points.  If it is in-memory it would be faster.  I have not had the pleasure to work on such a system.&lt;br /&gt;&lt;br /&gt;I do disagree with the database concerns being a subset of application concerns.  The data drives the app.  We’re probably getting religious at this point (or am I)."&lt;br /&gt;&lt;br /&gt;Mr. M:&lt;br /&gt;"‘The data drives the app.”&lt;br /&gt;&lt;br /&gt;Exactly, but who’s to say where the data comes from or in what format? My application data may reside completely in xml files, or maybe I get it from some third party web services a la the en vogue “mashup.” Heck, I may not even need to worry about a database anymore…. http://www.amazon.com/gp/browse.html?node=16427261  The database is only one particular concern of the overall application. And it’s the application that matters. Data is useless if it just sits on a disk somewhere. It’s the ways in which the application lets the users view and manipulate the data that adds value to the business. &lt;br /&gt;&lt;br /&gt;Yep, definitely a different type of thinking between application developers and database developers."&lt;br /&gt;&lt;br /&gt;Me:&lt;br /&gt;"Definitely religious now.&lt;br /&gt;&lt;br /&gt;Applications come and go, data stays the same.  Think Green Screens, EJBs, Ruby…what’s next?"&lt;br /&gt;&lt;br /&gt;Mr. M:&lt;br /&gt;"'Applications come and go'&lt;br /&gt;&lt;br /&gt;Exactly. Businesses are not static, nor are the markets they compete in. Changing applications are a function of changing business processes and changing markets.&lt;br /&gt;&lt;br /&gt;'data stays the same.' &lt;br /&gt;&lt;br /&gt;Nonsense. Otherwise UPDATE would not be an SQL reserved word. If you mean database technology stays the same, well, I’m more inclined to agree with that.&lt;br /&gt;&lt;br /&gt;'Think Green Screens, EJBs, Ruby...what’s next?'&lt;br /&gt;&lt;br /&gt;Whatever comes along to let the business more effectively respond to current market realities. Application platforms have evolved much faster than database platforms have. They’ve had to, their sphere of operation is much broader than that of databases, this is only natural, they deal with much broader concerns than do databases. Databases in the internet era function in essentially the same role they did in the era of dumb terminals. Clearly application platforms have evolved orders of magnitude more. Hence the statement, database concerns are a subset of application concerns.  &lt;br /&gt;&lt;br /&gt;Here’s a simple test….if I take some business application and I’m forced to throw away one or the other, either the database or the appl- wait a second, it doesn’t even make sense to finish it, does it? The business can live without the database. I could do all kinds of things with the data, I could stick it anywhere. The business can’t live without the application though. Another way to look at is, what do the business users look at, test, approve, and use? The database? Of course not, they look at the application. They could care less whether the data sits on disk in an RDBMS, xml, or flat files."&lt;br /&gt;&lt;br /&gt;Me:&lt;br /&gt;"We obviously violently disagree.&lt;br /&gt;&lt;br /&gt;Without the database (and I use database and data interchangebly), the business could no longer function.  The app is meaningless.  How would you contact your customer?  You couldn’t find it.&lt;br /&gt;&lt;br /&gt;'Exactly. Businesses are not static, nor are the markets they compete in. Changing applications are a function of changing business processes and changing markets.'&lt;br /&gt;&lt;br /&gt;Poorly designed applications…that is all."&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.oraclenerd.com/2007/09/today-one-of-my-more-feisty-colleages.html"&gt;A Feisty Colleague&lt;/a&gt;:&lt;br /&gt;"Using data and database interchangeably is incorrect.  A database is a mechanism for data storage.  XML data sets and flat files are mechanisms for data storage, too.  So is a file cabinet, because, the data doesn’t have to be electronic, it could be … gasp! … on paper, and the application to use that data would be hands for holding the paper and a pencil to update and add data to the page."&lt;br /&gt;&lt;br /&gt;Me:&lt;br /&gt;"No it isn’t.  I take into account xml files, flat files, web services (but not paper, unless it’s scanned) and all that.  It would be consumed by the database and then accessed by the application via SQL.&lt;br /&gt;&lt;br /&gt;(that’s for Mr. M and the feisty one)"&lt;br /&gt;&lt;br /&gt;At which point someone forwarded the home page for &lt;a href="http://www.oracle.com/technology/products/timesten/index.html"&gt;Oracle's TimesTen In-Memory Database&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Me:&lt;br /&gt;"A database on/in the mid-tier...Perfect!"&lt;br /&gt;&lt;br /&gt;Mr. M:&lt;br /&gt;"Implicit acknowledgment that disk IO operations that come with traditional database access simply can’t match the performance of in-memory data access (a point which you previously were unconvinced of but now seem perfectly accepting of the idea once you see it’s got Oracle’s imprimatur on it).  &lt;br /&gt;&lt;br /&gt;Of course, why any application developer would want to program against an SQL interface if they weren’t forced to is beyond me. It is orthogonal to the programming model of most application platform languages. &lt;br /&gt;&lt;br /&gt;Surely Oracle recognize this fact too or they wouldn’t be buying Tangosol and other data grid technologies. Of course, most of those products are far more technically advanced than TimesTen or anything Oracle has in that space. &lt;br /&gt;&lt;br /&gt;Incidentally, it’s illustrative to note that Coherence and other products like it were for the most part designed and built by application programmers. The development of all these products is pretty much driven by the needs of the large investment banks on Wall Street. These trading applications simply had too many concurrent transactions to use an RDBMS (a problem quite a number of public domains now share, most famously google.com, nope, no RDBMS there, yet miraculously there is still data). The database just simply would not scale to such a degree. So the application developers, by necessity, came up with an alternate solution that did work, a fully transactional cache of data replicated across a cluster with node numbers in the thousands, and no relational model whatsoever to speak of. A perfect example of how database concerns are only one, sometimes small, concern amongst many that application developers must be aware of and ready to solve."&lt;br /&gt;&lt;br /&gt;Me:&lt;br /&gt;"Like you said initially, the top 1%.&lt;br /&gt;&lt;br /&gt;Many of us will never touch a system like this.&lt;br /&gt;&lt;br /&gt;I will certainly concede that it is faster (still would love to see benchmarking though), but that still leaves 99% of the applications out there that do not require that kind of performance."&lt;br /&gt;&lt;br /&gt;Me (again):&lt;br /&gt;"And don’t forget, I use data and database interchangeably.  Applications are nothing without the data right?&lt;br /&gt;&lt;br /&gt;As to the object/relational impedance mismatch...well, more people that don’t know how to work in sets.  Looping is what they understand.  I understand the application side more than you seem to give me credit for. &lt;br /&gt;&lt;br /&gt;I’m not saying applications aren’t important, they are.  Data (databases) and applications go hand in hand.  If the application went away though, they could still access their data via SELECT statements (yes, via an application client tool), however painful that may be.  Applications make retrieving data that much easier for our users.  &lt;br /&gt;&lt;br /&gt;If anyone wants to unsubscribe from this mailing list, just let us know.  This is fun for me (I’m guessing Mr. M too)."&lt;br /&gt;&lt;br /&gt;Needless to say it was a fun day.  It didn't get [too] personal.  More than anything I'm happy to have an equally passionate colleague.  &lt;br /&gt;&lt;br /&gt;Besides, he claims he was just fracking around with me. ;)&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-3853911845992923";
/* atom feed */
google_ad_slot = "1428191201";
google_ad_width = 728;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8884584404576003487-325612574443515851?l=www.oraclenerd.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/GmEB4O88kEpMq0PY090lRyZRtAU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/GmEB4O88kEpMq0PY090lRyZRtAU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/GmEB4O88kEpMq0PY090lRyZRtAU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/GmEB4O88kEpMq0PY090lRyZRtAU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/325612574443515851/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8884584404576003487&amp;postID=325612574443515851" title="16 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/325612574443515851" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/325612574443515851" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/oraclenerd/RahJ/~3/fq22-I2q-_Y/classic-application-developers-vs.html" title="Classic:  Application Developers vs. Database Developers" /><author><name>oraclenerd</name><uri>http://www.blogger.com/profile/12412013306950057961</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="03223434293565733241" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">16</thr:total><feedburner:origLink>http://www.oraclenerd.com/2009/07/classic-application-developers-vs.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-8884584404576003487.post-5367393360345264882</id><published>2009-07-05T23:02:00.002-04:00</published><updated>2009-07-05T23:35:02.738-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="sql" /><category scheme="http://www.blogger.com/atom/ns#" term="plsql" /><category scheme="http://www.blogger.com/atom/ns#" term="security" /><category scheme="http://www.blogger.com/atom/ns#" term="database" /><category scheme="http://www.blogger.com/atom/ns#" term="oracle" /><title type="text">SQL:  SYS_CONTEXT</title><content type="html">In my experience so far, I've seen very few places where &lt;a href="http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/functions172.htm"&gt;SYS_CONTEXT&lt;/a&gt; is used.  It is typically used in conjunction with &lt;a href="http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/statements_5002.htm#i2060927"&gt;CONTEXT&lt;/a&gt;s and also Virtual Private Database (VPD).&lt;br /&gt;&lt;br /&gt;Oracle has a built in namespace called USERENV and their is a wealth of &lt;a href="http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/functions172.htm#g1513460"&gt;information&lt;/a&gt; you can retrieve from there.  I wrote up a quick view to demonstrate the use of SYS_CONTEXT:&lt;pre class="code"&gt;SELECT&lt;br /&gt;  SYS_CONTEXT( 'USERENV', 'ACTION' ) action,&lt;br /&gt;  SYS_CONTEXT( 'USERENV', 'AUTHENTICATION_METHOD' ) authentication_method,&lt;br /&gt;  SYS_CONTEXT( 'USERENV', 'BG_JOB_ID' ) bg_job_id,&lt;br /&gt;  SYS_CONTEXT( 'USERENV', 'CLIENT_IDENTIFIER' ) client_identifier,&lt;br /&gt;  SYS_CONTEXT( 'USERENV', 'CLIENT_INFO' ) client_info,&lt;br /&gt;  SYS_CONTEXT( 'USERENV', 'CURRENT_SCHEMAID' ) current_schemaid,&lt;br /&gt;  SYS_CONTEXT( 'USERENV', 'CURRENT_SCHEMA' ) current_schema,&lt;br /&gt;  SYS_CONTEXT( 'USERENV', 'CURRENT_USER' ) current_user,&lt;br /&gt;  SYS_CONTEXT( 'USERENV', 'DB_DOMAIN' ) db_domain,&lt;br /&gt;  SYS_CONTEXT( 'USERENV', 'DB_NAME' ) db_name,&lt;br /&gt;  SYS_CONTEXT( 'USERENV', 'DB_UNIQUE_NAME' ) db_unique_name,&lt;br /&gt;  SYS_CONTEXT( 'USERENV', 'HOST' ) host,&lt;br /&gt;  SYS_CONTEXT( 'USERENV', 'INSTANCE' ) instance,&lt;br /&gt;  SYS_CONTEXT( 'USERENV', 'INSTANCE_NAME' ) instance_name,&lt;br /&gt;  SYS_CONTEXT( 'USERENV', 'IP_ADDRESS' ) ip_address,&lt;br /&gt;  SYS_CONTEXT( 'USERENV', 'ISDBA' ) isdba,&lt;br /&gt;  SYS_CONTEXT( 'USERENV', 'LANG' ) lang,&lt;br /&gt;  SYS_CONTEXT( 'USERENV', 'LANGUAGE' ) language,&lt;br /&gt;  SYS_CONTEXT( 'USERENV', 'NETWORK_PROTOCOL' ) network_protocol,&lt;br /&gt;  SYS_CONTEXT( 'USERENV', 'NLS_CALENDAR' ) nls_calendar,&lt;br /&gt;  SYS_CONTEXT( 'USERENV', 'NLS_CURRENCY' ) nls_currency,&lt;br /&gt;  SYS_CONTEXT( 'USERENV', 'OS_USER' ) os_user,&lt;br /&gt;  SYS_CONTEXT( 'USERENV', 'SERVER_HOST' ) server_host,&lt;br /&gt;  SYS_CONTEXT( 'USERENV', 'TERMINAL' ) terminal&lt;br /&gt;FROM dual&lt;/pre&gt;Which yields the following:&lt;pre class="code"&gt;ACTION:  NULL&lt;br /&gt;AUTHENTICATION_METHOD:  PASSWORD&lt;br /&gt;BG_JOB_ID:  NULL&lt;br /&gt;CLIENT_IDENTIFIER:  NULL&lt;br /&gt;CLIENT_INFO:  NULL&lt;br /&gt;CURRENT_SCHEMAID:  88&lt;br /&gt;CURRENT_SCHEMA:  CJUSTICE&lt;br /&gt;CURRENT_USER:  CJUSTICE&lt;br /&gt;DB_DOMAIN:  NULL&lt;br /&gt;DB_NAME:  testing&lt;br /&gt;DB_UNIQUE_NAME:  testing&lt;br /&gt;HOST:  cdj-laptop&lt;br /&gt;INSTANCE:  1&lt;br /&gt;INSTANCE_NAME:  TESTING&lt;br /&gt;IP_ADDRESS:  192.168.1.4&lt;br /&gt;ISDBA:  FALSE&lt;br /&gt;LANG:  US&lt;br /&gt;LANGUAGE:  AMERICAN_AMERICA.WE8MSWIN1252&lt;br /&gt;NETWORK_PROTOCOL:  tcp&lt;br /&gt;NLS_CALENDAR:  GREGORIAN&lt;br /&gt;NLS_CURRENCY:  $&lt;br /&gt;OS_USER:  chet&lt;br /&gt;SERVER_HOST:  oracledb&lt;br /&gt;TERMINAL:  UNKNOWN&lt;/pre&gt;Basically, these are global variables that Oracle stores on the current session/user.&lt;br /&gt;&lt;br /&gt;You can create a context for just about anything you want.  I've used them in the past along with table based security in a stateless environment.  In essence, I create a record in a table with a SESSION_ID, I then store that in the context (global variable) and I use that to reconnect to the database each time.  &lt;br /&gt;&lt;br /&gt;I promise to have an example of using it in the near future.&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-3853911845992923";
/* atom feed */
google_ad_slot = "1428191201";
google_ad_width = 728;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8884584404576003487-5367393360345264882?l=www.oraclenerd.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/gH9OTYUc3u6-deyTE_F15saUK_4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/gH9OTYUc3u6-deyTE_F15saUK_4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/gH9OTYUc3u6-deyTE_F15saUK_4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/gH9OTYUc3u6-deyTE_F15saUK_4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/5367393360345264882/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8884584404576003487&amp;postID=5367393360345264882" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/5367393360345264882" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/5367393360345264882" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/oraclenerd/RahJ/~3/Wq97-N5tbAc/sql-syscontext.html" title="SQL:  SYS_CONTEXT" /><author><name>oraclenerd</name><uri>http://www.blogger.com/profile/12412013306950057961</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="03223434293565733241" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.oraclenerd.com/2009/07/sql-syscontext.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-8884584404576003487.post-4439879791084345159</id><published>2009-07-02T00:21:00.005-04:00</published><updated>2009-07-02T01:18:11.403-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="failed" /><category scheme="http://www.blogger.com/atom/ns#" term="ideas" /><category scheme="http://www.blogger.com/atom/ns#" term="development" /><category scheme="http://www.blogger.com/atom/ns#" term="work" /><category scheme="http://www.blogger.com/atom/ns#" term="life" /><title type="text">Learning From Failure</title><content type="html">I think I began reading &lt;a href="http://thedailywtf.com"&gt;The Daily WTF&lt;/a&gt; about 4 years ago.  I don't miss or skip a post.&lt;br /&gt;&lt;br /&gt;I remember this one time, probably about the time I began reading the site, I had to automate a process to move files from one server to another.  Originally, I had tried to create a network drive (yes, it was Windows) on the database server so that I could just use a simple Java class to read the directory and then load the files via DBMS_LOB.&lt;br /&gt;&lt;br /&gt;I had ultimately decided on a service, but I didn't know how to write one for Windows.  Then I found the &lt;a href="http://wrapper.tanukisoftware.org/doc/english/introduction.html"&gt;Java Service Wrapper&lt;/a&gt; which would allow me to write the guts in Java and then install it on Windows as a service.  Perfect.&lt;br /&gt;&lt;br /&gt;Now that I had that settled, I had to figure out how to detect when a file was read to be moved.  I decided on a looping mechanism, to check every minute or so, to see if a file was available.  It looked something like this (I'm a tad rusty, so bear with me):&lt;pre class="code"&gt;package project1;&lt;br /&gt;&lt;br /&gt;import java.util.Date;&lt;br /&gt;&lt;br /&gt;public class Class1&lt;br /&gt;{&lt;br /&gt;  public static void main(String[] args)&lt;br /&gt;  {&lt;br /&gt;    Class1 class1 = new Class1();&lt;br /&gt;    Date d = new Date();&lt;br /&gt;    long l = d.getTime() + 1000000000;&lt;br /&gt;    String s = String.valueOf( l );&lt;br /&gt;    &lt;br /&gt;    for ( int i = 0; i &lt; l; i++ )&lt;br /&gt;    {&lt;br /&gt;      //some sort of MOD "wait" here, then check for the file&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;/pre&gt;It wasn't pretty, but it seemed to work.&lt;br /&gt;&lt;br /&gt;Then I got a call from the server admin.&lt;br /&gt;&lt;br /&gt;SA:  "You've got something running on this machine that's spiking the CPU."&lt;br /&gt;&lt;br /&gt;Me:  "Really?  I can't think of anything."&lt;br /&gt;&lt;br /&gt;SA:  "Well, take a look and see if you can find anything."&lt;br /&gt;&lt;br /&gt;Me:  "10-4"&lt;br /&gt;&lt;br /&gt;Sure enough, go into Task Manager and there's java.exe hogging up all the CPU.  WTF?&lt;br /&gt;&lt;br /&gt;I just ran this on my machine and you can see the CPU start to spike:&lt;br /&gt;&lt;br /&gt;&lt;table style="width:auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="http://picasaweb.google.com/lh/photo/0mo8oo9prZkuPBTn3M9APA?feat=embedwebsite"&gt;&lt;img src="http://lh5.ggpht.com/_rhCtHYLiamQ/Skw9Q1wZNZI/AAAAAAAAEhM/qroXLlLDYGU/s800/cpu_spike.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;Off to Google to see what I can find.  During my research, I found mention of a small method called &lt;a href="http://java.sun.com/javase/6/docs/api/java/lang/Thread.html#sleep(long)"&gt;Thread.sleep(long)&lt;/a&gt;.  So I replaced my brilliant add 1000000 to the current date with Thread.sleep(6000), or whatever equals 60 seconds.  Problem solved.&lt;br /&gt;&lt;br /&gt;A short time later I read a post on The Daily WTF about the same exact problem (I can't find the exact post for the life of me).  The "victim" did the exact same thing I did.  The solution was the Thread.sleep() call.&lt;br /&gt;&lt;br /&gt;Me = &lt;a href="http://www.failblog.org"&gt;FAIL&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;One more short example.&lt;br /&gt;&lt;br /&gt;Over beers, a &lt;a href="http://www.oraclenerd.com/2009/04/mentoring.html"&gt;friend&lt;/a&gt; (see last entry) of mine and I were discussing the failure of the North Korean missile launch.  I said, "Idiots."  He said, "They're going to learn a lot more from that failure than they would have had it suceeded."&lt;br /&gt;&lt;br /&gt;Spoken like a true engineer I guess.&lt;br /&gt;&lt;br /&gt;The point?  You learn by trying.  You learn my doing.  You learn by failing.  Whether you realize it or not, you learn.  (Well, some people don't, but that's another post).  If you're reading here though, that probably means you have a passion for what you do.  That means that you are trying.  You are learning (maybe not here specifically ;).&lt;br /&gt;&lt;br /&gt;Here's to trying and failing and hopefully trying and succeeding.&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-3853911845992923";
/* atom feed */
google_ad_slot = "1428191201";
google_ad_width = 728;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8884584404576003487-4439879791084345159?l=www.oraclenerd.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/suYtzQWZdioGoJpkhTL-mVMZkKA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/suYtzQWZdioGoJpkhTL-mVMZkKA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/suYtzQWZdioGoJpkhTL-mVMZkKA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/suYtzQWZdioGoJpkhTL-mVMZkKA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/4439879791084345159/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8884584404576003487&amp;postID=4439879791084345159" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/4439879791084345159" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/4439879791084345159" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/oraclenerd/RahJ/~3/BhbDu1uJSjs/learning-from-failure.html" title="Learning From Failure" /><author><name>oraclenerd</name><uri>http://www.blogger.com/profile/12412013306950057961</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="03223434293565733241" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/_rhCtHYLiamQ/Skw9Q1wZNZI/AAAAAAAAEhM/qroXLlLDYGU/s72-c/cpu_spike.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.oraclenerd.com/2009/07/learning-from-failure.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-8884584404576003487.post-1013157870512353547</id><published>2009-06-29T23:45:00.002-04:00</published><updated>2009-06-29T23:58:40.446-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="documentation" /><category scheme="http://www.blogger.com/atom/ns#" term="constraints" /><title type="text">Constraints:  ENABLE NOVALIDATE</title><content type="html">&lt;a href="http://www.oraclenerd.com/2009/06/oracle-concepts-data-integrity-rules.html"&gt;Yesterday&lt;/a&gt; while perusing the &lt;a href="http://download.oracle.com/docs/cd/B28359_01/server.111/b28318/toc.htm"&gt;Concepts Guide&lt;/a&gt;, I stumbled across the ENABLE NOVALIDATE keywords for the definition of a Foreign Key constraint.  I've always known it was there, just never used it, or thought to use it.&lt;br /&gt;&lt;br /&gt;It can be a big benefit while working on a legacy system.&lt;br /&gt;&lt;br /&gt;Suppose you have a table, T_CHILD:&lt;pre class="code"&gt;CREATE TABLE t_child&lt;br /&gt;(&lt;br /&gt;  child_id NUMBER(10)&lt;br /&gt;    CONSTRAINT pk_childid PRIMARY KEY,&lt;br /&gt;  soon_to_be_parent_id NUMBER(10)&lt;br /&gt;);&lt;br /&gt;&lt;br /&gt;INSERT INTO t_child&lt;br /&gt;  ( child_id,&lt;br /&gt;    soon_to_be_parent_id )&lt;br /&gt;SELECT&lt;br /&gt;    rownum,&lt;br /&gt;    TRUNC( dbms_random.value( -9999, -1 ) )&lt;br /&gt;FROM dual&lt;br /&gt;  CONNECT BY LEVEL &lt;= 10;&lt;/pre&gt;This table has been around for quite some time.  You decide that you would like to constrain the values in the SOON_TO_BE_PARENT_ID column.  First, here's the data that exists:&lt;pre class="code"&gt;CJUSTICE@TESTING&gt;SELECT * FROM t_child;&lt;br /&gt;&lt;br /&gt;  CHILD_ID SOON_TO_BE_PARENT_ID&lt;br /&gt;---------- --------------------&lt;br /&gt;         1                -5560&lt;br /&gt;         2                -1822&lt;br /&gt;         3                -2499&lt;br /&gt;         4                -7039&lt;br /&gt;         5                -8718&lt;br /&gt;         6                -1019&lt;br /&gt;         7                -9997&lt;br /&gt;         8                -9553&lt;br /&gt;         9                -4477&lt;br /&gt;        10                -1458&lt;/pre&gt;Now I'll create a table that will contain the values I want to constraint SOON_TO_BE_PARENT_ID to, call it a lookup or reference table.&lt;pre class="code"&gt;CREATE TABLE t_parent&lt;br /&gt;(&lt;br /&gt;  parent_id NUMBER(10)&lt;br /&gt;    CONSTRAINT pk_parentid PRIMARY KEY&lt;br /&gt;);&lt;/pre&gt;I'll populate it with some data:&lt;pre class="code"&gt;INSERT INTO t_parent( parent_id )&lt;br /&gt;SELECT rownum&lt;br /&gt;FROM dual&lt;br /&gt;  CONNECT BY LEVEL &lt;= 10;&lt;br /&gt;&lt;br /&gt;CJUSTICE@TESTING&gt;SELECT * FROM T_PARENT;&lt;br /&gt;&lt;br /&gt; PARENT_ID&lt;br /&gt;----------&lt;br /&gt;         1&lt;br /&gt;         2&lt;br /&gt;         3&lt;br /&gt;         4&lt;br /&gt;         5&lt;br /&gt;         6&lt;br /&gt;         7&lt;br /&gt;         8&lt;br /&gt;         9&lt;br /&gt;        10&lt;br /&gt;&lt;br /&gt;10 rows selected.&lt;/pre&gt;Now I'll add the constraint that references the PARENT_ID column of T_PARENT&lt;pre class="code"&gt;ALTER TABLE t_child&lt;br /&gt;  ADD CONSTRAINT fk_parentid&lt;br /&gt;  FOREIGN KEY ( soon_to_be_parent_id )&lt;br /&gt;  REFERENCES t_parent( parent_id )&lt;br /&gt;  &lt;b&gt;ENABLE&lt;br /&gt;  NOVALIDATE&lt;/b&gt;;&lt;/pre&gt;and rename the column to PARENT_ID:&lt;pre class="code"&gt;ALTER TABLE t_child RENAME COLUMN soon_to_be_parent_id TO parent_id;&lt;/pre&gt;What will this do?  I should no longer be able to enter a value into T_CHILD.PARENT_ID that does not exist in T_PARENT, but it will ignore anything that already exists.&lt;pre class="code"&gt;INSERT INTO t_child&lt;br /&gt;  ( child_id,&lt;br /&gt;    parent_id )&lt;br /&gt;VALUES&lt;br /&gt;  ( 11,&lt;br /&gt;    11 );&lt;br /&gt;&lt;br /&gt;INSERT INTO t_child&lt;br /&gt;*&lt;br /&gt;ERROR at line 1:&lt;br /&gt;ORA-02291: integrity constraint (CJUSTICE.FK_PARENTID) violated - parent key not found&lt;/pre&gt;Perfect!  Now I'll add a value that does exist in T_PARENT.&lt;pre class="code"&gt;INSERT INTO t_child&lt;br /&gt;  ( child_id,&lt;br /&gt;    parent_id )&lt;br /&gt;VALUES&lt;br /&gt;  ( 11,&lt;br /&gt;    10 );&lt;br /&gt;&lt;br /&gt;1 row created.&lt;/pre&gt;Win!&lt;br /&gt;&lt;br /&gt;This is just another reminder why you must read the Concepts Guide.  By the way, I found the quote I was looking for from Mr. Kyte (h/t &lt;a href="http://twitter.com/boneist"&gt;@boneist&lt;/a&gt;)&lt;blockquote&gt;"...if you simply read the Concepts Guide...and retain just 10%..., you’ll already know 90% more than most people do"&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-3853911845992923";
/* atom feed */
google_ad_slot = "1428191201";
google_ad_width = 728;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8884584404576003487-1013157870512353547?l=www.oraclenerd.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/KzGv-Nehaa6e4WfDyDcJqZpurFE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/KzGv-Nehaa6e4WfDyDcJqZpurFE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/KzGv-Nehaa6e4WfDyDcJqZpurFE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/KzGv-Nehaa6e4WfDyDcJqZpurFE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/1013157870512353547/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8884584404576003487&amp;postID=1013157870512353547" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/1013157870512353547" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/1013157870512353547" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/oraclenerd/RahJ/~3/8X6Q85x4MOk/constraints-enable-novalidate.html" title="Constraints:  ENABLE NOVALIDATE" /><author><name>oraclenerd</name><uri>http://www.blogger.com/profile/12412013306950057961</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="03223434293565733241" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.oraclenerd.com/2009/06/constraints-enable-novalidate.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-8884584404576003487.post-4317784730089804573</id><published>2009-06-29T17:44:00.002-04:00</published><updated>2009-06-29T17:49:04.432-04:00</updated><title type="text">Classic:  DBMS_APPLICATION_INFO</title><content type="html">&lt;i&gt;I've decided to post a few "classics" from long before anyone paid attention...as opposed to now, when 30 people pay attention.  I originally posted this on 12/02/2007 at 10:04 PM which you can find &lt;a href="http://www.oraclenerd.com/2007/12/instrumentation-dbmsapplicationinfo.html"&gt;here&lt;/a&gt;.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Instrumentation has something that I have come to rely on fairly heavily.  I believe I first read about it on asktom, but the one that really spurred me on was this &lt;a href="http://tkyte.blogspot.com/2005/06/instrumentation.html"&gt;post on instrumentation&lt;/a&gt; on his personal blog.&lt;br /&gt;&lt;br /&gt;Initially, I couldn't really wrap my head around instrumentation.  I don't know why it was so difficult; I had a similar problem with sessions when I first started my career.  I look back now and it just seems so obvious.&lt;br /&gt;&lt;br /&gt;Now that I am doing datawarehouse work, nothing is fast.  Fast to me is now one hour to load 30 or 40 million records.  No more split second queries for me.&lt;br /&gt;&lt;br /&gt;We currently use no tools.  It's straight PL/SQL.  Instrumentation of the code is ideal.  Actually, it's more instrumentation to aid monitoring.  The tool most easily used is provided by Oracle in the &lt;a href="http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_appinf.htm#CHECEIEB"&gt;DBMS_APPLICATION_INFO&lt;/a&gt; package.&lt;br /&gt;&lt;br /&gt;There are three subprograms that I use most, SET_MODULE, SET_ACTION and most importantly SET_SESSION_LONGOPS.  I hadn't started using it until this year, I mainly stuck to the first two.  SET_SESSION_LONGOPS is now part of my procedure/function template I've created in JDeveloper.&lt;br /&gt;&lt;br /&gt;What it allows you to do is set a row in the v$session_longops view (I know it's not actually putting the row in the view...it's the underlying table, but I digress).  You can then monitor how your job is doing.&lt;br /&gt;&lt;br /&gt;Here's an example:&lt;pre class="code"&gt;dbms_application_info.set_session_longops&lt;br /&gt;  ( rindex =&amp;gt; g_index,&lt;br /&gt;    slno =&amp;gt; g_slno,&lt;br /&gt;    op_name =&amp;gt; 'GETTING MEMBER DATA',&lt;br /&gt;    sofar =&amp;gt; 0,&lt;br /&gt;    totalwork =&amp;gt; l_table.COUNT + 1,&lt;br /&gt;    target_desc =&amp;gt; 'GETTING MEMBER DATA' );&lt;/pre&gt;g_index and g_slno are global variables in the package.  l_table is a PL/SQL TABLE OF VARCHAR2.  &lt;br /&gt;&lt;br /&gt;Now you can monitor the progress of your job in v$session_longops!&lt;br /&gt;&lt;br /&gt;Here's the query I use:&lt;pre class="code"&gt;SELECT &lt;br /&gt;  username,&lt;br /&gt;  sid,&lt;br /&gt;  serial#,&lt;br /&gt;  TO_CHAR( start_time, 'MM/DD/YYYY HH24:MI:SS' ) start_ti,&lt;br /&gt;  time_remaining rem,&lt;br /&gt;  elapsed_seconds ela,&lt;br /&gt;  ROUND( ( sofar / REPLACE( totalwork, 0, 1 ) ) * 100, 2 ) per,&lt;br /&gt;  sofar,&lt;br /&gt;  totalwork work,&lt;br /&gt;  message,&lt;br /&gt;  target_desc&lt;br /&gt;FROM v$session_longops&lt;br /&gt;WHERE start_time &gt;= SYSDATE - 1 &lt;br /&gt;ORDER BY start_time DESC&lt;/pre&gt;Now you too can sit for hours and watch your job move incrementally forward!&lt;br /&gt;&lt;br /&gt;But seriously, it does help tremendously to know where a job is at.  You can further use the SET_MODULE and SET_ACTION calls to see a specific point in the processing (inside a loop).&lt;br /&gt;&lt;br /&gt;Here's the code in context:&lt;pre class="code"&gt;PROCEDURE get_member_data&lt;br /&gt;IS&lt;br /&gt;  l_exists INTEGER;&lt;br /&gt;  TYPE table_of_lobs IS TABLE OF VARCHAR2(3);&lt;br /&gt;  l_table TABLE_OF_LOBS := TABLE_OF_LOBS( 'COM', 'ORG' );&lt;br /&gt;  l_count INTEGER := 0;&lt;br /&gt;BEGIN&lt;br /&gt;  --check to see if there is enrollment data, if not, move on&lt;br /&gt;  SELECT COUNT(*)&lt;br /&gt;  INTO l_exists&lt;br /&gt;  FROM members&lt;br /&gt;  WHERE rownum &lt; 2;&lt;br /&gt;  &lt;br /&gt;  IF l_exists = 1 THEN--data exists, truncate and reload&lt;br /&gt;  &lt;br /&gt;    g_index := dbms_application_info.set_session_longops_nohint;&lt;br /&gt;      &lt;br /&gt;    EXECUTE IMMEDIATE 'TRUNCATE TABLE member_stg';&lt;br /&gt;&lt;br /&gt;    g_audit_key := p_audit.begin_load&lt;br /&gt;                    ( p_targettable =&gt; 'MEMBER_STG',&lt;br /&gt;                      p_loadsource =&gt; 'MEMBER_SOURCE',&lt;br /&gt;                      p_loadstatus =&gt; 'PRE',&lt;br /&gt;                      p_loadprogram =&gt; 'GET_MEMBER_DATA',&lt;br /&gt;                      p_commenttext =&gt; 'INSERT' );&lt;br /&gt;&lt;B&gt;&lt;br /&gt;    dbms_application_info.set_session_longops&lt;br /&gt;      ( rindex =&gt; g_index,&lt;br /&gt;        slno =&gt; g_slno,&lt;br /&gt;        op_name =&gt; 'GETTING MEMBERS',&lt;br /&gt;        sofar =&gt; 0,&lt;br /&gt;        totalwork =&gt; l_table.COUNT + 1,&lt;br /&gt;        target_desc =&gt; 'GETTING MEMBERS' );&lt;br /&gt;&lt;/B&gt;&lt;br /&gt;  FOR i IN 1..l_table.COUNT LOOP&lt;br /&gt;    l_count := l_count + 1;&lt;br /&gt;&lt;br /&gt;    INSERT INTO member_stg&lt;br /&gt;    SELECT *&lt;br /&gt;    FROM members;&lt;br /&gt;&lt;br /&gt;    g_total_rows_affected := g_total_rows_affected + sql%rowcount;&lt;br /&gt;&lt;br /&gt;    COMMIT;&lt;br /&gt;&lt;B&gt;&lt;br /&gt;    dbms_application_info.set_session_longops&lt;br /&gt;      ( rindex =&gt; g_index,&lt;br /&gt;        slno =&gt; g_slno,&lt;br /&gt;        op_name =&gt; 'GETTING MEMBERS',&lt;br /&gt;        sofar =&gt; l_count,&lt;br /&gt;        totalwork =&gt; l_table.COUNT + 1,&lt;br /&gt;        target_desc =&gt; 'GETTING MEMBERS' );&lt;br /&gt;&lt;/B&gt;  &lt;br /&gt;  END LOOP;&lt;br /&gt;&lt;br /&gt;  p_audit.end_load&lt;br /&gt;    ( p_auditkey =&gt; g_audit_key,&lt;br /&gt;      p_loadstatus =&gt; 'SUC',&lt;br /&gt;      p_rowsuccess =&gt; g_total_rows_affected );&lt;br /&gt;  &lt;br /&gt;  gather_table_stats&lt;br /&gt;    ( p_tablename =&gt; 'MEMBER_STG',&lt;br /&gt;      p_schemaname =&gt; 'MYHOME' );&lt;br /&gt;&lt;B&gt;&lt;br /&gt;  dbms_application_info.set_session_longops&lt;br /&gt;    ( rindex =&gt; g_index,&lt;br /&gt;      slno =&gt; g_slno,&lt;br /&gt;      op_name =&gt; 'GETTING MEMBERS',&lt;br /&gt;      sofar =&gt; l_count + 1,&lt;br /&gt;      totalwork =&gt; l_table.COUNT + 1,&lt;br /&gt;      target_desc =&gt; 'GETTING MEMBERS' );&lt;br /&gt;&lt;/B&gt;&lt;br /&gt;  END IF;&lt;br /&gt;&lt;br /&gt;EXCEPTION&lt;br /&gt;  WHEN others THEN&lt;br /&gt;    p_audit.failed_load&lt;br /&gt;      ( p_auditkey =&gt; g_audit_key,&lt;br /&gt;        p_comments =&gt; SQLCODE || ' ' || SQLERRM );&lt;br /&gt;    RAISE;&lt;br /&gt;&lt;br /&gt;END get_member_data;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-3853911845992923";
/* atom feed */
google_ad_slot = "1428191201";
google_ad_width = 728;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8884584404576003487-4317784730089804573?l=www.oraclenerd.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/0Kr_fPmBznF1pdanpxYUS0UeKVE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/0Kr_fPmBznF1pdanpxYUS0UeKVE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/0Kr_fPmBznF1pdanpxYUS0UeKVE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/0Kr_fPmBznF1pdanpxYUS0UeKVE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/4317784730089804573/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8884584404576003487&amp;postID=4317784730089804573" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/4317784730089804573" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/4317784730089804573" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/oraclenerd/RahJ/~3/sKkIlMdUx1Y/classic-dbmsapplicationinfo.html" title="Classic:  DBMS_APPLICATION_INFO" /><author><name>oraclenerd</name><uri>http://www.blogger.com/profile/12412013306950057961</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="03223434293565733241" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.oraclenerd.com/2009/06/classic-dbmsapplicationinfo.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-8884584404576003487.post-4396541625605308275</id><published>2009-06-29T01:17:00.004-04:00</published><updated>2009-06-29T01:30:39.156-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="documentation" /><category scheme="http://www.blogger.com/atom/ns#" term="database" /><category scheme="http://www.blogger.com/atom/ns#" term="oracle" /><title type="text">Oracle Concepts:  Data Integrity Rules</title><content type="html">I'm reading through the &lt;a href="http://download.oracle.com/docs/cd/B28359_01/server.111/b28318/toc.htm"&gt;Concepts&lt;/a&gt; manual again as mentioned on &lt;a href="http://www.oraclenerd.com/2009/06/oracle-concepts.html"&gt;last week&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I'm going to make a small effort to post some of the key concepts here over the next couple of weeks.  If you've read through the Concepts Guide before, this can serve as a brief refresher.  If not, good, you're exposed to something new.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://download.oracle.com/docs/cd/B28359_01/server.111/b28318/data_int.htm#BABJIIGH"&gt;Data Integrity Rules&lt;/a&gt;&lt;blockquote&gt;This section describes the rules that can be applied to table columns to enforce different types of data integrity.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Null rule&lt;/b&gt;: A null rule is a rule defined on a single column that allows or disallows inserts or updates of rows containing a null (the absence of a value) in that column.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Unique column values&lt;/b&gt;: A unique value rule defined on a column (or set of columns) allows the insert or update of a row only if it contains a unique value in that column (or set of columns).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Primary key values&lt;/b&gt;: A primary key value rule defined on a key (a column or set of columns) specifies that each row in the table can be uniquely identified by the values in the key.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Referential integrity rules&lt;/b&gt;: A referential integrity rule is a rule defined on a key (a column or set of columns) in one table that guarantees that the values in that key match the values in a key in a related table (the referenced value).&lt;br /&gt;&lt;br /&gt;Referential integrity also includes the rules that dictate what types of data manipulation are allowed on referenced values and how these actions affect dependent values. The rules associated with referential integrity are:&lt;br /&gt;&lt;br /&gt;    * &lt;b&gt;Restrict&lt;/b&gt;: Disallows the update or deletion of referenced data.&lt;br /&gt;    * &lt;b&gt;Set to null&lt;/b&gt;: When referenced data is updated or deleted, all associated dependent data is set to NULL.&lt;br /&gt;    * &lt;b&gt;Set to default&lt;/b&gt;: When referenced data is updated or deleted, all associated dependent data is set to a default value.&lt;br /&gt;    * &lt;b&gt;Cascade&lt;/b&gt;: When referenced data is updated, all associated dependent data is correspondingly updated. When a referenced row is deleted, all associated dependent rows are deleted.&lt;br /&gt;    * &lt;b&gt;No action&lt;/b&gt;: Disallows the update or deletion of referenced data. This differs from RESTRICT in that it is checked at the end of the statement, or at the end of the transaction if the constraint is deferred. (Oracle Database uses No Action as its default action.)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Complex integrity checking&lt;/b&gt;: A user-defined rule for a column (or set of columns) that allows or disallows inserts, updates, or deletes of a row based on the value it contains for the column (or set of columns).&lt;/blockquote&gt;Reading on past the brief section to the &lt;a href="http://download.oracle.com/docs/cd/B28359_01/server.111/b28318/data_int.htm#CHDEEGEG"&gt;Constraint States&lt;/a&gt; I found this nugget:&lt;blockquote&gt;ENABLE NOVALIDATE means that the constraint is checked, but it does not have to be true for all rows. This allows existing rows to violate the constraint, while ensuring that all new or modified rows are valid.&lt;/blockquote&gt;This is a great tool for legacy systems.  You have data in the column(s) that you can't really do anything with, but you want to insure that all future data that goes in that particular column(s) matches the parent key.  &lt;br /&gt;&lt;br /&gt;Of course the ideal is to somehow clean the data up, but you don't always have that option.  This is a good first step towards to overall cleanup of your legacy system.&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-3853911845992923";
/* atom feed */
google_ad_slot = "1428191201";
google_ad_width = 728;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8884584404576003487-4396541625605308275?l=www.oraclenerd.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/tnxfM0T0-_d5-csJ8Snd_VFNJHQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/tnxfM0T0-_d5-csJ8Snd_VFNJHQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/tnxfM0T0-_d5-csJ8Snd_VFNJHQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/tnxfM0T0-_d5-csJ8Snd_VFNJHQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/4396541625605308275/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8884584404576003487&amp;postID=4396541625605308275" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/4396541625605308275" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/4396541625605308275" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/oraclenerd/RahJ/~3/mLKLb9hptBU/oracle-concepts-data-integrity-rules.html" title="Oracle Concepts:  Data Integrity Rules" /><author><name>oraclenerd</name><uri>http://www.blogger.com/profile/12412013306950057961</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="03223434293565733241" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.oraclenerd.com/2009/06/oracle-concepts-data-integrity-rules.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-8884584404576003487.post-4868544754447916745</id><published>2009-06-28T22:59:00.003-04:00</published><updated>2009-06-28T23:05:02.231-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="apex" /><title type="text">APEX:  URL Syntax</title><content type="html">This is more for my own edification than anything.  I always forget which place the ClearCache inhabits.&lt;pre class="code"&gt;f?p=App:Page:Session:Request:Debug:ClearCache:itemNames:PrinterFriendly&lt;/pre&gt;With numbers so I don't have to count every time:&lt;pre class="code"&gt;f?p=App1:Page2:Sess3:Requ4:Debug5:Cache6:items7:printer8&lt;br /&gt;&lt;br /&gt;f?p=1:2:3:4:5:6:7:8&lt;/pre&gt;Link to the documentation is &lt;a href="http://download.oracle.com/docs/cd/E14373_01/appdev.32/e11838/concept.htm#BEIFCDGF"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-3853911845992923";
/* atom feed */
google_ad_slot = "1428191201";
google_ad_width = 728;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8884584404576003487-4868544754447916745?l=www.oraclenerd.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/R6iNnb62Azv2nu4aQmkgPOqavxI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/R6iNnb62Azv2nu4aQmkgPOqavxI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/R6iNnb62Azv2nu4aQmkgPOqavxI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/R6iNnb62Azv2nu4aQmkgPOqavxI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/4868544754447916745/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8884584404576003487&amp;postID=4868544754447916745" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/4868544754447916745" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/4868544754447916745" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/oraclenerd/RahJ/~3/4-w7hng10Co/apex-url-syntax.html" title="APEX:  URL Syntax" /><author><name>oraclenerd</name><uri>http://www.blogger.com/profile/12412013306950057961</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="03223434293565733241" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://www.oraclenerd.com/2009/06/apex-url-syntax.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-8884584404576003487.post-3289379762841293555</id><published>2009-06-26T21:07:00.002-04:00</published><updated>2009-06-26T21:49:23.134-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="documentation" /><title type="text">Oracle Concepts</title><content type="html">Years and years of reading &lt;a href="http://asktom.oracle.com"&gt;AskTom&lt;/a&gt;, if there's one thing that I really come away with, it's read.  RTFM.  Specifically though, he's telling everyone to read the &lt;a href="http://download.oracle.com/docs/cd/B28359_01/server.111/b28318/toc.htm"&gt;Concepts Guide&lt;/a&gt;.  Paraphrasing:&lt;blockquote&gt;If you can get a good look at the Concepts Guide by sticking your head...&lt;/blockquote&gt;That's not the one.&lt;blockquote&gt;If you read the Concepts Guide you'll have 10% of the knowledge that 90% don't have.&lt;/blockquote&gt;Nope.&lt;blockquote&gt;If 90% of the people would read 10% of the Concepts Guide, they'd be able to program in C...?&lt;/blockquote&gt;Seriously, I need help.&lt;br /&gt;&lt;br /&gt;If you do know the saying I'm talking about, please share.  I can't seem to find it &lt;a href="http://xkcd.com/323/"&gt;anywhere&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Ultimately it doesn't matter what was said.  I'm reading the Concepts Guide again, browsing through it really, trying to find something new.  Then I noticed this:&lt;br /&gt;&lt;br /&gt;&lt;table style="width:auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="http://picasaweb.google.com/lh/photo/XUQKteVkkszOhIWWr7cZ1g?feat=embedwebsite"&gt;&lt;img src="http://lh6.ggpht.com/_rhCtHYLiamQ/SkVwxv_OAUI/AAAAAAAAEgo/A0FuEDaw30E/s800/oracle_concepts.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;I know it's a "feature" and all, but does it have to be so prominently displayed?  Couldn't it be buried in the Appendix of the PL/SQL Guide or something?  This is especially important since Mr. Kyte is telling all the new people to read the Concepts Guide.  &lt;br /&gt;&lt;br /&gt;Perhaps the new people figure it out, the ones that have read the Concepts Guide anyway. I've run across too many "experienced" database developers that can't create apps without them.  My guess is that they have barely hit &lt;i&gt;any&lt;/i&gt; of the documentation, let alone the Concepts Guide.&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-3853911845992923";
/* atom feed */
google_ad_slot = "1428191201";
google_ad_width = 728;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8884584404576003487-3289379762841293555?l=www.oraclenerd.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/PQFAsa4mUc7pG2vy4OmAKCwNbmM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/PQFAsa4mUc7pG2vy4OmAKCwNbmM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/PQFAsa4mUc7pG2vy4OmAKCwNbmM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/PQFAsa4mUc7pG2vy4OmAKCwNbmM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/3289379762841293555/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8884584404576003487&amp;postID=3289379762841293555" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/3289379762841293555" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/3289379762841293555" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/oraclenerd/RahJ/~3/idDvr1wrk4Y/oracle-concepts.html" title="Oracle Concepts" /><author><name>oraclenerd</name><uri>http://www.blogger.com/profile/12412013306950057961</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="03223434293565733241" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/_rhCtHYLiamQ/SkVwxv_OAUI/AAAAAAAAEgo/A0FuEDaw30E/s72-c/oracle_concepts.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.oraclenerd.com/2009/06/oracle-concepts.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-8884584404576003487.post-372524083347417581</id><published>2009-06-25T23:03:00.003-04:00</published><updated>2009-06-25T23:14:08.545-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="null" /><category scheme="http://www.blogger.com/atom/ns#" term="database" /><category scheme="http://www.blogger.com/atom/ns#" term="oracle" /><title type="text">A NULL Observation, III</title><content type="html">Part I &lt;a href="http://www.oraclenerd.com/2009/06/null-observation.html"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Part II &lt;a href="http://www.oraclenerd.com/2009/06/null-observation-ii.html"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;OK, we have a winner.  &lt;a href="http://www.blogger.com/profile/11570869033287689498"&gt;Coskan Gundogar&lt;/a&gt; suggested in the &lt;a href="http://www.oraclenerd.com/2009/06/null-observation.html?showComment=1245913037892#c8928800955057591395"&gt;comments&lt;/a&gt;, that using the MODIFY clause of the ALTER TABLE statement should work.  Let's see:&lt;pre class="code"&gt;desc t_null&lt;br /&gt;&lt;br /&gt;Name                    Null?    Type&lt;br /&gt;----------------------- -------- ----------------&lt;br /&gt;COL1                             VARCHAR2(30)&lt;br /&gt;&lt;br /&gt;CJUSTICE@TESTING&gt;ALTER TABLE T_NULL DROP CONSTRAINT nn_col1_tn;&lt;br /&gt;&lt;br /&gt;Table altered.&lt;br /&gt;&lt;br /&gt;CJUSTICE@TESTING&gt;ALTER TABLE t_null MODIFY ( col1 CONSTRAINT nn_col1_tn NOT NULL );&lt;br /&gt;&lt;br /&gt;Table altered.&lt;br /&gt;&lt;br /&gt;CJUSTICE@TESTING&gt;@DESC T_NULL&lt;br /&gt;Name                    Null?    Type&lt;br /&gt;----------------------- -------- ----------------&lt;br /&gt;COL1                    NOT NULL VARCHAR2(30)&lt;/pre&gt;Voila!&lt;br /&gt;&lt;br /&gt;Much better.  The question still remains as to what's going on in the background.  Until now, I had never thought that white space mattered in anything Oracle.  Very strange.&lt;br /&gt;&lt;br /&gt;Maybe I can get &lt;a href="http://www.oraclue.com"&gt;Miladin&lt;/a&gt; to dig through the internals and see what's really going on.&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-3853911845992923";
/* atom feed */
google_ad_slot = "1428191201";
google_ad_width = 728;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8884584404576003487-372524083347417581?l=www.oraclenerd.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/K3DfdMCSjcVYfPZzS07eltDn_2c/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/K3DfdMCSjcVYfPZzS07eltDn_2c/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/K3DfdMCSjcVYfPZzS07eltDn_2c/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/K3DfdMCSjcVYfPZzS07eltDn_2c/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/372524083347417581/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8884584404576003487&amp;postID=372524083347417581" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/372524083347417581" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/372524083347417581" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/oraclenerd/RahJ/~3/kGYjzcCQODE/null-observation-iii.html" title="A NULL Observation, III" /><author><name>oraclenerd</name><uri>http://www.blogger.com/profile/12412013306950057961</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="03223434293565733241" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://www.oraclenerd.com/2009/06/null-observation-iii.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-8884584404576003487.post-425500808184243706</id><published>2009-06-25T00:06:00.006-04:00</published><updated>2009-06-25T23:18:47.782-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="null" /><category scheme="http://www.blogger.com/atom/ns#" term="database" /><category scheme="http://www.blogger.com/atom/ns#" term="oracle" /><title type="text">A NULL Observation, II</title><content type="html">Shoot me, I couldn't let &lt;a href="http://www.oraclenerd.com/2009/06/null-observation.html"&gt;this&lt;/a&gt; go.  Plus, I needed a reason to test drive my new &lt;a href="http://www.oraclenerd.com/2009/06/virtual-box-oel-11g-apex.html"&gt;sandbox&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The part about the space had me a little perplexed:&lt;pre class="code"&gt;CJUSTICE@TESTING&gt;SELECT&lt;br /&gt;  2    table_name,&lt;br /&gt;  3    constraint_name,&lt;br /&gt;  4    constraint_type,&lt;br /&gt;  5    search_condition,&lt;br /&gt;  6    status&lt;br /&gt;  7  FROM user_constraints&lt;br /&gt;  8  ORDER BY table_name;&lt;br /&gt;&lt;br /&gt;TABLE_NAME           CONSTRAINT_NAME      C SEARCH_CONDITION     STATUS&lt;br /&gt;-------------------- -------------------- - -------------------- --------&lt;br /&gt;T_NOT_NULL           NN_COL1_TNN          C "COL1" IS NOT NULL   ENABLED&lt;br /&gt;T_NOT_NULL_CHECK     NN_COL1_TNNC         C  "COL1" IS NOT NULL  ENABLED&lt;br /&gt;T_NULL               NN_COL1_TN           C  col1 IS NOT NULL    ENABLED&lt;/pre&gt;Here's the DDL that created that constraint:&lt;pre class="code"&gt;ALTER TABLE t_not_null_check DROP CONSTRAINT nn_col1_tnnc;&lt;br /&gt;&lt;br /&gt;ALTER TABLE t_not_null_check&lt;br /&gt;  ADD CONSTRAINT nn_col1_tnnc&lt;br /&gt;  CHECK ( "COL1" IS NOT NULL );&lt;/pre&gt;Note the white space there.  I like putting a space after a parenthesis as I believe it makes it slightly easier to read.&lt;br /&gt;&lt;br /&gt;With that in mind, watch this:&lt;pre class="code"&gt;ALTER TABLE t_not_null_check DROP CONSTRAINT nn_col1_tnnc;&lt;br /&gt;&lt;br /&gt;ALTER TABLE t_not_null_check&lt;br /&gt;  ADD CONSTRAINT nn_col1_tnnc&lt;br /&gt;  CHECK ("COL1" IS NOT NULL);&lt;/pre&gt;Note that I removed the space between the "(" and the """.  Here's what it looks like:&lt;pre class="code"&gt;SELECT &lt;br /&gt;  table_name, &lt;br /&gt;  constraint_name, &lt;br /&gt;  constraint_type, &lt;br /&gt;  search_condition&lt;br /&gt;FROM user_constraints&lt;br /&gt;ORDER BY table_name;&lt;br /&gt;&lt;br /&gt;TABLE_NAME       CONSTRAINT_N C SEARCH_CONDITION&lt;br /&gt;---------------- ------------ - ------------------------------&lt;br /&gt;T_NOT_NULL       NN_COL1_TNN  C "COL1" IS NOT NULL&lt;br /&gt;T_NOT_NULL_CHECK NN_COL1_TNNC C "COL1" IS NOT NULL&lt;br /&gt;T_NULL           NN_COL1_TN   C "COL1" IS NOT NULL&lt;br /&gt;&lt;br /&gt;CJUSTICE@TESTING&gt;desc t_not_null_check&lt;br /&gt; Name    Null?   Type&lt;br /&gt; ----------------------- -------- ----------------&lt;br /&gt; COL1      VARCHAR2(30)&lt;/pre&gt;The leading space is gone now.  Null? still shows up as NULL.  I would assume that most GUI apps get their data from USER/ALL/DBA_TAB_COLUMNS, so let's take a look:&lt;pre class="code"&gt;SELECT &lt;br /&gt;  table_name, &lt;br /&gt;  column_name, &lt;br /&gt;  nullable&lt;br /&gt;FROM user_tab_columns&lt;br /&gt;ORDER BY table_name;&lt;br /&gt;&lt;br /&gt;TABLE_NAME       COLUMN_NAME                    N&lt;br /&gt;---------------- ------------------------------ -&lt;br /&gt;T_NOT_NULL       COL1                           N&lt;br /&gt;T_NOT_NULL_CHECK COL1                           Y&lt;br /&gt;T_NULL           COL1                           Y&lt;/pre&gt;How about USER_TAB_COLS?&lt;pre class="code"&gt;SELECT &lt;br /&gt;  table_name, &lt;br /&gt;  column_name, &lt;br /&gt;  nullable&lt;br /&gt;FROM user_tab_cols&lt;br /&gt;ORDER BY table_name;&lt;br /&gt;&lt;br /&gt;TABLE_NAME       COLUMN_NAME                    N&lt;br /&gt;---------------- ------------------------------ -&lt;br /&gt;T_NOT_NULL       COL1                           N&lt;br /&gt;T_NOT_NULL_CHECK COL1                           Y&lt;br /&gt;T_NULL           COL1                           Y&lt;/pre&gt;Nothing to see there.&lt;br /&gt;&lt;br /&gt;So, there &lt;i&gt;&lt;b&gt;is&lt;/b&gt;&lt;/i&gt; a difference between defining a NOT NULL constraint using either the NOT NULL or CHECK syntax.  In USER_CONSTRAINTS, there are 4 distinct constraint types:&lt;br /&gt;1.&amp;nbsp;&amp;nbsp;P = PRIMARY&lt;br /&gt;2.&amp;nbsp;&amp;nbsp;U = UNIQUE&lt;br /&gt;3.&amp;nbsp;&amp;nbsp;R = REFERENCE or FOREIGN KEY&lt;br /&gt;4.&amp;nbsp;&amp;nbsp;C = CHECK&lt;br /&gt;&lt;br /&gt;What's the lesson here?  Well, if doing analysis, you can't just depend on using the DESCRIBE command from SQL*PLus to see what is required and what is not.  Of course you can't depend on that for everything.  Interesting "problem" none-the-less.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;b&gt;Update&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;Part III (the final solution) is &lt;a href="http://www.oraclenerd.com/2009/06/null-observation-iii.html"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-3853911845992923";
/* atom feed */
google_ad_slot = "1428191201";
google_ad_width = 728;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8884584404576003487-425500808184243706?l=www.oraclenerd.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/e-6f-gUC5QcqeDY0Ilmf3zxsD_U/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/e-6f-gUC5QcqeDY0Ilmf3zxsD_U/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/e-6f-gUC5QcqeDY0Ilmf3zxsD_U/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/e-6f-gUC5QcqeDY0Ilmf3zxsD_U/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/425500808184243706/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8884584404576003487&amp;postID=425500808184243706" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/425500808184243706" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/425500808184243706" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/oraclenerd/RahJ/~3/lxv-DJTITBI/null-observation-ii.html" title="A NULL Observation, II" /><author><name>oraclenerd</name><uri>http://www.blogger.com/profile/12412013306950057961</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="03223434293565733241" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.oraclenerd.com/2009/06/null-observation-ii.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-8884584404576003487.post-2493608450701169539</id><published>2009-06-24T21:48:00.002-04:00</published><updated>2009-06-24T22:18:07.271-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="kate" /><title type="text">Kate:  The TV Star</title><content type="html">A couple of weeks ago a colleague of mine said she was enrolling her girls in the school across the street from work.  &lt;br /&gt;&lt;br /&gt;School?  What school?&lt;br /&gt;&lt;br /&gt;It's the &lt;a href="http://www.blossomschool.org/"&gt;Blossom Montessori School for the Deaf&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Your girls aren't deaf.&lt;br /&gt;&lt;br /&gt;No they aren't, but they've opened up the summer program to all children.&lt;br /&gt;&lt;br /&gt;Interesting.  All I could think about was I might get to drive &lt;a href="http://oraclenerd.com/labels/kate.html"&gt;Kate&lt;/a&gt; to school.  WIN!  My friend later brought over some paperwork and I passed that on to Kris.&lt;br /&gt;&lt;br /&gt;The next day, Kris called and was thoroughly impressed.  They knew what &lt;a href="http://www.google.com/search?hl=en&amp;q=define%3A+apraxia&amp;btnG=Search"&gt;apraxia&lt;/a&gt; was, unlike her local public school.  &lt;br /&gt;&lt;br /&gt;Kate has been in the ELP program for about a year and a half.  ELP stands for Early Learning Program.  It's designed for kids who, for one reason or another, have fallen behind.  I think it falls between regular classes and Special Education (think Down's Syndrome).&lt;br /&gt;&lt;br /&gt;Anyway, they recently provided us with her year-end report.  It's not required though because the end of the year is really December.  On the report, they crossed out (literally) the December date and hand-wrote the current date (June something).  On top of that injustice (pun intended), they stated that Kate had made no progress since the last review.&lt;br /&gt;&lt;br /&gt;Seriously, why would you do that?  Why would you even entertain the idea of making &lt;a href="http://twitter.com/ktjustice"&gt;@ktjustice&lt;/a&gt; mad?  Mad is an understatement actually.&lt;br /&gt;&lt;br /&gt;&lt;table style="width:auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="http://picasaweb.google.com/lh/photo/kzRB226zl4ayXKqTpN8yQA?feat=embedwebsite"&gt;&lt;img src="http://lh4.ggpht.com/_rhCtHYLiamQ/SkLcF74CX4I/AAAAAAAAEgE/NFeVkqIrxvY/s800/kris_on_twitter.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;Needless to say, we signed Kate up for Blossom.&lt;br /&gt;&lt;br /&gt;Kate signs, a little bit.  &lt;a href="http://www.lifeprint.com/asl101/pages-signs/p/please.htm"&gt;Please&lt;/a&gt;, &lt;a href="http://www.lifeprint.com/asl101/pages-signs/m/more.htm"&gt;More&lt;/a&gt;, All Done.  I don't think we pursued that hard because of her hands.  She's been in school for 2 weeks now and seems to enjoy it.  I think she signed &lt;a href="http://www.lifeprint.com/asl101/pages-signs/m/momdad.htm"&gt;Daddy&lt;/a&gt; this evening (poor Mommy).&lt;br /&gt;&lt;br /&gt;Today they took a field trip to the Clearwater Aquarium and lo and behold, a news crew was there!&lt;br /&gt;&lt;br /&gt;&lt;table style="width:auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="http://video.tbo.com/m/23204172/summer-camping-with-a-dolphin.htm"&gt;&lt;img src="http://lh5.ggpht.com/_rhCtHYLiamQ/SkLYonYMM5I/AAAAAAAAEgA/hfLsk450HZw/s800/kate_on_tv.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;(I was having problems getting this to display, so just click-through if it doesn't show up).&lt;br /&gt;&lt;br /&gt;Kate shows up at 1:02...with her back to everone else...standing, while everyone else is sitting.&lt;br /&gt;&lt;div class="ezEmbeddedPlayerDiv"&gt;&lt;br /&gt;  &lt;script type="text/javascript" src="http://video.tbo.com/widgets/630/frame.js?width=640&amp;height=440&amp;episode=23204172"&gt;&amp;#a0;&lt;/script&gt;&lt;br /&gt;  &lt;br/&gt;&lt;br /&gt;  &lt;br/&gt;&lt;br /&gt;  &lt;a id="ezEmbedSiteLink" href="http://video.tbo.com/m/23204172/summer-camping-with-a-dolphin.htm" target="_blank"&gt;Watch this at Tampa Bay Online&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-3853911845992923";
/* atom feed */
google_ad_slot = "1428191201";
google_ad_width = 728;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8884584404576003487-2493608450701169539?l=www.oraclenerd.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/UEziVzQwvLaHHXEluU7-RUrqmtQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/UEziVzQwvLaHHXEluU7-RUrqmtQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/UEziVzQwvLaHHXEluU7-RUrqmtQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/UEziVzQwvLaHHXEluU7-RUrqmtQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/2493608450701169539/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8884584404576003487&amp;postID=2493608450701169539" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/2493608450701169539" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/2493608450701169539" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/oraclenerd/RahJ/~3/Dncn0baRVOo/kate-tv-star.html" title="Kate:  The TV Star" /><author><name>oraclenerd</name><uri>http://www.blogger.com/profile/12412013306950057961</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="03223434293565733241" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/_rhCtHYLiamQ/SkLcF74CX4I/AAAAAAAAEgE/NFeVkqIrxvY/s72-c/kris_on_twitter.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.oraclenerd.com/2009/06/kate-tv-star.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-8884584404576003487.post-3905105549566255682</id><published>2009-06-24T17:24:00.006-04:00</published><updated>2009-06-25T23:17:08.892-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="null" /><category scheme="http://www.blogger.com/atom/ns#" term="database" /><category scheme="http://www.blogger.com/atom/ns#" term="oracle" /><title type="text">A NULL Observation</title><content type="html">As I've been doing a lot of analysis lately, I've found a slightly annoying "problem."&lt;br /&gt;&lt;br /&gt;I typically use JDev or SQLDev to see details on a table, more than just a DESCRIBE from SQL*Plus can give me anyway.  &lt;br /&gt;&lt;br /&gt;This "problem" relates to how NULL columns are displayed, both via DESCRIBE and the previously mentioned tools.&lt;br /&gt;&lt;br /&gt;First up, my favorite, the table definition with inline constraints.&lt;pre class="code"&gt;CREATE TABLE t_not_null&lt;br /&gt;(&lt;br /&gt;  col1 VARCHAR2(30)&lt;br /&gt;    CONSTRAINT nn_col1_tnn NOT NULL&lt;br /&gt;);&lt;/pre&gt;Let's see how it looks in a SQL Worksheet (Columns):&lt;br /&gt;&lt;table style="width:auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="http://picasaweb.google.com/lh/photo/sGnubCXIb2Ro_nHTS67kZg?feat=embedwebsite"&gt;&lt;img src="http://lh3.ggpht.com/_rhCtHYLiamQ/SkKbxQbX01I/AAAAAAAAEfo/lf1rbeN78KU/s800/t_null_columns.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;Constraints:&lt;br /&gt;&lt;table style="width:auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="http://picasaweb.google.com/lh/photo/gCI5kAammdVOOF5kU3AP_g?feat=embedwebsite"&gt;&lt;img src="http://lh5.ggpht.com/_rhCtHYLiamQ/SkKbxTt9xXI/AAAAAAAAEfs/Q17KQqjVC6Q/s800/t_null_constraints.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;SQL*Plus (DESCRIBE):&lt;pre class="code"&gt;CJUSTICE@TESTING&gt;desc t_not_null&lt;br /&gt; Name                    Null?    Type&lt;br /&gt; ----------------------- -------- ----------------&lt;br /&gt; COL1                    NOT NULL VARCHAR2(30)&lt;/pre&gt;Now I'll create a different table, this time instead of using NOT NULL, I'll use the CHECK syntax.&lt;pre class="code"&gt;CREATE TABLE t_not_null_check&lt;br /&gt;(&lt;br /&gt;  col1 VARCHAR2(30)&lt;br /&gt;    CONSTRAINT nn_col1_tnnc CHECK ( col1 IS NOT NULL )&lt;br /&gt;);&lt;/pre&gt;Columns:&lt;br /&gt;&lt;table style="width:auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="http://picasaweb.google.com/lh/photo/mAPd8OzT7nPR3kDz6ChMBg?feat=embedwebsite"&gt;&lt;img src="http://lh5.ggpht.com/_rhCtHYLiamQ/SkKdSgp4STI/AAAAAAAAEfw/xM72Lc_dVBs/s800/t_not_null_check_columns.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;Nullable = Yes?  Hmmm...&lt;br /&gt;&lt;br /&gt;Constraints:&lt;br /&gt;&lt;table style="width:auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="http://picasaweb.google.com/lh/photo/1WE8T0iiPH4NQXL8O_EnlQ?feat=embedwebsite"&gt;&lt;img src="http://lh3.ggpht.com/_rhCtHYLiamQ/SkKdSxuhTdI/AAAAAAAAEf0/YjjUCccDMVQ/s800/t_not_null_check_constraints.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;DESCRIBE&lt;pre class="code"&gt;CJUSTICE@TESTING&gt;desc t_not_null_check&lt;br /&gt; Name                    Null?    Type&lt;br /&gt; ----------------------- -------- ----------------&lt;br /&gt; COL1                             VARCHAR2(30)&lt;/pre&gt;Interesting, it doesn't show up in the "Null?" column like it did with the NOT NULL syntax used above.&lt;br /&gt;&lt;br /&gt;Now I'll create a table with no inline constraint defined.&lt;pre class="code"&gt;CREATE TABLE t_null&lt;br /&gt;(&lt;br /&gt;  col1 VARCHAR2(30)&lt;br /&gt;);&lt;/pre&gt;I know (famous last words) I can't use the NOT NULL syntax in an out-of-line constraint:&lt;pre class="code"&gt;ALTER TABLE t_null&lt;br /&gt;  ADD CONSTRAINT nn_col1_tn NOT NULL;&lt;br /&gt;  ADD CONSTRAINT nn_col1_tn NOT NULL&lt;br /&gt;                            *&lt;br /&gt;ERROR at line 2:&lt;br /&gt;ORA-00904: : invalid identifier&lt;/pre&gt;So I use the CHECK syntax:&lt;pre class="code"&gt;ALTER TABLE t_null&lt;br /&gt;  ADD CONSTRAINT nn_col1_tn&lt;br /&gt;  CHECK ( col1 IS NOT NULL );&lt;br /&gt;&lt;br /&gt;Table altered.&lt;/pre&gt;Columns:&lt;br /&gt;&lt;table style="width:auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="http://picasaweb.google.com/lh/photo/ee3VZfLksH_B2qHisI7rmQ?feat=embedwebsite"&gt;&lt;img src="http://lh3.ggpht.com/_rhCtHYLiamQ/SkKgEl6qrPI/AAAAAAAAEf4/YY_lAYMGm0g/s800/t_null_columns.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;Constraints:&lt;br /&gt;&lt;table style="width:auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="http://picasaweb.google.com/lh/photo/YmdGW0-nmUBh9DBSLKN0zQ?feat=embedwebsite"&gt;&lt;img src="http://lh6.ggpht.com/_rhCtHYLiamQ/SkKgE_coP3I/AAAAAAAAEf8/CQaEUXSVL0U/s800/t_null_constraints.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;DESCRIBE&lt;pre class="code"&gt;CJUSTICE@TESTING&gt;desc t_null&lt;br /&gt; Name                    Null?    Type&lt;br /&gt; ----------------------- -------- ----------------&lt;br /&gt; COL1                             VARCHAR2(30)&lt;/pre&gt;Very odd.&lt;br /&gt;&lt;br /&gt;Let's look at the dictionary:&lt;pre class="code"&gt;SELECT&lt;br /&gt;  table_name,&lt;br /&gt;  constraint_name,&lt;br /&gt;  constraint_type,&lt;br /&gt;  search_condition,&lt;br /&gt;  status&lt;br /&gt;FROM user_constraints&lt;br /&gt;ORDER BY table_name;&lt;br /&gt;&lt;br /&gt;TABLE_NAME           CONSTRAINT_NAME      C SEARCH_CONDITION     STATUS&lt;br /&gt;-------------------- -------------------- - -------------------- --------&lt;br /&gt;T_NOT_NULL           NN_COL1_TNN          C "COL1" IS NOT NULL   ENABLED&lt;br /&gt;T_NOT_NULL_CHECK     NN_COL1_TNNC         C  col1 IS NOT NULL    ENABLED&lt;br /&gt;T_NULL               NN_COL1_TN           C  col1 IS NOT NULL    ENABLED&lt;/pre&gt;Interesting, I wonder if the fact that it's not UPPERcased and in quotes?&lt;pre class="code"&gt;CJUSTICE@TESTING&gt;DROP TABLE t_not_null_check;&lt;br /&gt;&lt;br /&gt;Table dropped.&lt;br /&gt;&lt;br /&gt;Elapsed: 00:00:00.04&lt;br /&gt;CJUSTICE@TESTING&gt;CREATE TABLE t_not_null_check&lt;br /&gt;  2  (&lt;br /&gt;  3    col1 VARCHAR2(30)&lt;br /&gt;  4      CONSTRAINT nn_col1_tnnc CHECK ( "COL1" IS NOT NULL )&lt;br /&gt;  5  );&lt;br /&gt;&lt;br /&gt;Table created.&lt;/pre&gt;DESCRIBE&lt;pre class="code"&gt;CJUSTICE@TESTING&gt;DESC T_NOT_NULL_CHECK&lt;br /&gt; Name                    Null?    Type&lt;br /&gt; ----------------------- -------- ----------------&lt;br /&gt; COL1                             VARCHAR2(30)&lt;/pre&gt;OK, Null? is still...NULL.&lt;pre class="code"&gt;CJUSTICE@TESTING&gt;SELECT&lt;br /&gt;  2    table_name,&lt;br /&gt;  3    constraint_name,&lt;br /&gt;  4    constraint_type,&lt;br /&gt;  5    search_condition,&lt;br /&gt;  6    status&lt;br /&gt;  7  FROM user_constraints&lt;br /&gt;  8  ORDER BY table_name;&lt;br /&gt;&lt;br /&gt;TABLE_NAME           CONSTRAINT_NAME      C SEARCH_CONDITION     STATUS&lt;br /&gt;-------------------- -------------------- - -------------------- --------&lt;br /&gt;T_NOT_NULL           NN_COL1_TNN          C "COL1" IS NOT NULL   ENABLED&lt;br /&gt;&lt;b&gt;T_NOT_NULL_CHECK     NN_COL1_TNNC         C  "COL1" IS NOT NULL  ENABLED&lt;/b&gt;&lt;br /&gt;T_NULL               NN_COL1_TN           C  col1 IS NOT NULL    ENABLED&lt;/pre&gt;Why is there that extra space in front of "COL1" IS NOT NULL?  &lt;br /&gt;&lt;br /&gt;I ended my investigation there as it seems to be a waste of time.  I just found it interesting that there was a difference in how you defined a NOT NULL constraint and whether or not it would show up in the DESCRIBE command.  Anyone out there notice this before?&lt;br /&gt;&lt;br /&gt;Read Part II &lt;a href="http://www.oraclenerd.com/2009/06/null-observation-ii.html"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Part III (the final solution) is &lt;a href="http://www.oraclenerd.com/2009/06/null-observation-iii.html"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-3853911845992923";
/* atom feed */
google_ad_slot = "1428191201";
google_ad_width = 728;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8884584404576003487-3905105549566255682?l=www.oraclenerd.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/9t4yyWky1ZHtxQyo93pdP86Gm8g/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/9t4yyWky1ZHtxQyo93pdP86Gm8g/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/9t4yyWky1ZHtxQyo93pdP86Gm8g/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/9t4yyWky1ZHtxQyo93pdP86Gm8g/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/3905105549566255682/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8884584404576003487&amp;postID=3905105549566255682" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/3905105549566255682" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/3905105549566255682" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/oraclenerd/RahJ/~3/t94JAcUF0XA/null-observation.html" title="A NULL Observation" /><author><name>oraclenerd</name><uri>http://www.blogger.com/profile/12412013306950057961</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="03223434293565733241" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/_rhCtHYLiamQ/SkKbxQbX01I/AAAAAAAAEfo/lf1rbeN78KU/s72-c/t_null_columns.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">5</thr:total><feedburner:origLink>http://www.oraclenerd.com/2009/06/null-observation.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-8884584404576003487.post-9131964315115903036</id><published>2009-06-23T22:37:00.003-04:00</published><updated>2009-06-24T00:34:01.817-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="oel" /><category scheme="http://www.blogger.com/atom/ns#" term="apex" /><category scheme="http://www.blogger.com/atom/ns#" term="virtualbox" /><category scheme="http://www.blogger.com/atom/ns#" term="dba" /><title type="text">Virtual Box, OEL, 11g, ApEx</title><content type="html">Finally.&lt;br /&gt;&lt;br /&gt;After many months and many attempts, I have managed to install a database on a non-windows platform.  I think I deserve a little credit.  ;)&lt;br /&gt;&lt;br /&gt;In &lt;a href="http://www.oraclenerd.com/2009/01/fun-with-linux.html"&gt;January&lt;/a&gt;, I began installing Ubuntu Intrepid Ibex on all of my home computers.  What this meant for me is that I was often without one because I screwed something up.  I even got so far as to install Oracle XE on Ubuntu which took 2 &lt;a href="http://www.oraclenerd.com/2009/01/oracle-xe-on-ubuntu-intrepid-ibex-part.html"&gt;blog&lt;/a&gt; &lt;a href="http://www.oraclenerd.com/2009/01/oracle-xe-on-ubuntu-intrepid-ibex-part_21.html"&gt;posts&lt;/a&gt;.  &lt;br /&gt;&lt;br /&gt;Just before COLLABORATE 09, I installed Jaunty Jackalope on my &lt;a href="http://www.oraclenerd.com/2009/05/ubuntu-jaunty-jackalope.html"&gt;laptop&lt;/a&gt;.  Then I got the crazy idea to install Oracle on Ubuntu.  I ended up having to wipe the hard drive and start fresh.  I have no doubt that it (Oracle) can be installed on Ubuntu, it just takes someone much more experienced than I.&lt;br /&gt;&lt;br /&gt;Armed with a fresh install, I was going the virtual route.  Inspired, I believe, by this &lt;a href="http://www.oraclenerd.com/2009/05/ubuntu-jaunty-jackalope.html?showComment=1243419449289#c5385699455121253475"&gt;comment&lt;/a&gt; (&lt;a href="http://blog.aristadba.com/"&gt;Aman Sharma&lt;/a&gt;).&lt;br /&gt;1.&amp;nbsp;&amp;nbsp;Install &lt;strike&gt;Sun's&lt;/strike&gt; Oracle's VirtualBox&lt;br /&gt;2.&amp;nbsp;&amp;nbsp;Download the latest version of Oracle Enterprise Linux (v5)&lt;br /&gt;&lt;br /&gt;I think that's the point I realized my first installation of Jaunty was hosed, and by hosed I mean unrecoverable by me.  I couldn't see the 2nd partition, the one with all the room.&lt;br /&gt;&lt;br /&gt;3.&amp;nbsp;&amp;nbsp;Create OEL virtual machine&lt;br /&gt;4.&amp;nbsp;&amp;nbsp;Follow this &lt;a href="http://www.oracle.com/technology/pub/articles/smiley-11gr1-install.html"&gt;guide&lt;/a&gt; to get it ready to install the Oracle database (seriously?  Why does OEL not come ready for the database server?)&lt;br /&gt;&lt;br /&gt;&lt;table style="width:auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="http://picasaweb.google.com/lh/photo/Gq4VhIt_e2cj-YTN8w7SDg?feat=embedwebsite"&gt;&lt;img src="http://lh4.ggpht.com/_rhCtHYLiamQ/SkGSN75P00I/AAAAAAAAEfg/MM2ddEElJkM/s400/oel_11g.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;4a.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;There's no mention of opening up the firewall in that article.  It's probably obvious to most...&lt;br /&gt;5.&amp;nbsp;&amp;nbsp;Connect to Oracle from the host machine&lt;br /&gt;6.&amp;nbsp;&amp;nbsp;ApEx?  Which version am I running?  3.0?  That won't do.  Download ApEx 3.2&lt;br /&gt;7.&amp;nbsp;&amp;nbsp;Install ApEx&lt;br /&gt;8.&amp;nbsp;&amp;nbsp;Configure Embedded PL/SQL Gateway for port 80&lt;br /&gt;8a.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Ports below 1024 are reserved for privileged processes...Configure Embedded PL/SQL Gateway for port 8080&lt;br /&gt;9.&amp;nbsp;&amp;nbsp;Connect from host machine.&lt;br /&gt;&lt;br /&gt;&lt;table style="width:auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="http://picasaweb.google.com/lh/photo/PCVIaTycQcm8gg8q90pICw?feat=embedwebsite"&gt;&lt;img src="http://lh6.ggpht.com/_rhCtHYLiamQ/SkGSNgx2GDI/AAAAAAAAEfY/Do9bbjt-FkM/s400/apex.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;9a.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Login to ApEx.&lt;br /&gt;&lt;br /&gt;&lt;table style="width:auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="http://picasaweb.google.com/lh/photo/qux8Prfj29LGGl1csKAK4w?feat=embedwebsite"&gt;&lt;img src="http://lh5.ggpht.com/_rhCtHYLiamQ/SkGSNjONofI/AAAAAAAAEfc/U4blS5GL-uw/s400/apex_admin.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;10.&amp;nbsp;&amp;nbsp;WIN!&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-3853911845992923";
/* atom feed */
google_ad_slot = "1428191201";
google_ad_width = 728;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8884584404576003487-9131964315115903036?l=www.oraclenerd.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/nDBt5l03Su-cuhusVyLBCsJhdLk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/nDBt5l03Su-cuhusVyLBCsJhdLk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/nDBt5l03Su-cuhusVyLBCsJhdLk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/nDBt5l03Su-cuhusVyLBCsJhdLk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/9131964315115903036/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8884584404576003487&amp;postID=9131964315115903036" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/9131964315115903036" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/9131964315115903036" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/oraclenerd/RahJ/~3/CIGoWrwUohI/virtual-box-oel-11g-apex.html" title="Virtual Box, OEL, 11g, ApEx" /><author><name>oraclenerd</name><uri>http://www.blogger.com/profile/12412013306950057961</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="03223434293565733241" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/_rhCtHYLiamQ/SkGSN75P00I/AAAAAAAAEfg/MM2ddEElJkM/s72-c/oel_11g.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">6</thr:total><feedburner:origLink>http://www.oraclenerd.com/2009/06/virtual-box-oel-11g-apex.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-8884584404576003487.post-6112052276039714746</id><published>2009-06-23T17:00:00.002-04:00</published><updated>2009-06-23T18:44:19.618-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="plsql" /><category scheme="http://www.blogger.com/atom/ns#" term="howto" /><title type="text">PL/SQL: Split Key-Value Pairs</title><content type="html">In a continuation from a previous post, &lt;a href="http://www.oraclenerd.com/2009/06/plsql-split-url-parameters.html"&gt;PL/SQL: Split URL Parameters&lt;/a&gt;, I give you the key/value splitting!  (cheese, I know...I'm bored).&lt;br /&gt;&lt;br /&gt;In that previous post, I was taking a URL string and splitting it based on the delimiter, which is typically the ampersand &amp;amp;.  In ApEx it is the colon :.  I'd take a wild guess and say there are others, but I'm not going to look them up.  An example string looks like this:&lt;pre class="code"&gt;param1=value1&amp;param2=value2&lt;/pre&gt;Etc.  Etc.  Etc.&lt;br /&gt;&lt;br /&gt;The output of that split looks like this:&lt;pre class="code"&gt;param1=value1&lt;br /&gt;param2=value2&lt;/pre&gt;Now you need that string parsed.  Instead of just a string being returned however, you'd like to know the name of the parameter as well, thus key/value.  Desired format looks like this:&lt;pre class="code"&gt;KEY         VALUE&lt;br /&gt;----------- -----------&lt;br /&gt;param1      value1&lt;br /&gt;param2      value2&lt;/pre&gt;First up, I'll create the SQL objects (user defined types):&lt;pre class="code"&gt;CREATE TYPE r_key_value AS OBJECT&lt;br /&gt;(&lt;br /&gt;  key VARCHAR2(100),&lt;br /&gt;  value VARCHAR2(100)&lt;br /&gt;)&lt;br /&gt;/&lt;br /&gt;&lt;br /&gt;CREATE TYPE t_key_value AS TABLE OF r_key_value&lt;br /&gt;/&lt;/pre&gt;I could easily do this using PL/SQL tables, but I have future plans.&lt;pre class="code"&gt;DECLARE&lt;br /&gt;  l_string VARCHAR2(1000) := 'param1=value1&amp;param2=value2';&lt;br /&gt;  l_table T_KEY_VALUE := T_KEY_VALUE();&lt;br /&gt;  l_delimiter VARCHAR2(5) := '&amp;';&lt;br /&gt;  l_delimiter_length INTEGER := LENGTH( l_delimiter );&lt;br /&gt;  l_key VARCHAR2(100);&lt;br /&gt;  l_value VARCHAR2(100);&lt;br /&gt;  l_keyvalue VARCHAR2(200);&lt;br /&gt;  l_counter INTEGER := 0;&lt;br /&gt;  l_new VARCHAR2(4000);&lt;br /&gt;  l_start INTEGER := 1;&lt;br /&gt;  l_end INTEGER := 0;&lt;/pre&gt;This will eventually turn into a Function, but I'm just doing some smoke testing now to get the logic right.  More extensive testing will be performed in the future with SQLUnit.&lt;pre class="code"&gt;BEGIN&lt;br /&gt;  IF SUBSTR( l_string, -1, 1 ) &lt;&gt; l_delimiter THEN&lt;br /&gt;    l_string := l_string || l_delimiter;&lt;br /&gt;  END IF;&lt;br /&gt;&lt;br /&gt;  l_new := l_string;&lt;br /&gt;  p( L_NEW );&lt;/pre&gt;I still haven't figured out the best way to grab the last token without appending the delimiter onto the end.  It feels like a kludge, but for now, it works.&lt;pre class="code"&gt;  LOOP&lt;br /&gt;    l_counter := l_counter + 1;&lt;br /&gt;    l_end := INSTR( l_new, l_delimiter, 1 );&lt;br /&gt;    l_keyvalue := SUBSTR( l_new, 1, l_end - 1 );&lt;br /&gt;    EXIT WHEN l_keyvalue IS NULL;&lt;br /&gt;    &lt;br /&gt;    l_table.EXTEND(1);&lt;br /&gt;    l_key := SUBSTR( l_keyvalue, 1, INSTR( l_keyvalue, '=' ) - 1 );&lt;br /&gt;    l_value := SUBSTR( l_keyvalue, INSTR( l_keyvalue, '=' ) + 1 );&lt;br /&gt;    l_table(l_counter) := R_KEY_VALUE( l_key, l_value );&lt;br /&gt;    l_start := l_start + ( l_end + ( l_delimiter_length - 1 ) );&lt;br /&gt;    l_new := SUBSTR( l_string, l_start );&lt;br /&gt;  END LOOP;&lt;/pre&gt;Regular expressions would be the best fit here.  Until I learn them (yes, I hear you, "Isn't this the perfect opportunity?"), I'm going to do it the hard way.&lt;br /&gt;&lt;br /&gt;Finally, just printing out to the console so I can see the results.&lt;pre class="code"&gt;  p( 'table counter:  ' || l_table.COUNT );&lt;br /&gt;  FOR I IN 1..l_table.COUNT LOOP&lt;br /&gt;    p( 'key:    ' || l_table(i).key );&lt;br /&gt;    p( 'value:  ' || l_table(i).value );&lt;br /&gt;    p( '' );&lt;br /&gt;  END LOOP;&lt;/pre&gt;Run it and I get the following:&lt;pre class="code"&gt;CJUSTICE@TESTING&gt;@C:\TEMP\S&lt;br /&gt;table counter:  2&lt;br /&gt;key:    param1&lt;br /&gt;value:  value1&lt;br /&gt;key:    param2&lt;br /&gt;value:  value2&lt;br /&gt;&lt;br /&gt;PL/SQL procedure successfully completed.&lt;br /&gt;&lt;br /&gt;Elapsed: 00:00:00.07&lt;/pre&gt;Now I just need to wrap this up into package form and I'm all done.  That will be another post with the unit tests provided.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;i&gt;Update&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;So after rereading this post, I realized that I just confused it with the previous post on splitting URL strings.  Probably the best solution would be to combine these 2 functions, or at least pipe out the key/value pairs from the main function (previous post).  Did I catch a niner in there?&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-3853911845992923";
/* atom feed */
google_ad_slot = "1428191201";
google_ad_width = 728;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8884584404576003487-6112052276039714746?l=www.oraclenerd.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/50fDitKN_hcbx7H4CiN1XCoCqjw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/50fDitKN_hcbx7H4CiN1XCoCqjw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/50fDitKN_hcbx7H4CiN1XCoCqjw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/50fDitKN_hcbx7H4CiN1XCoCqjw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/6112052276039714746/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8884584404576003487&amp;postID=6112052276039714746" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/6112052276039714746" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/6112052276039714746" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/oraclenerd/RahJ/~3/GLTQDoDqnVk/plsql-split-key-value-pairs.html" title="PL/SQL: Split Key-Value Pairs" /><author><name>oraclenerd</name><uri>http://www.blogger.com/profile/12412013306950057961</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="03223434293565733241" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.oraclenerd.com/2009/06/plsql-split-key-value-pairs.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-8884584404576003487.post-2373569621806170162</id><published>2009-06-16T20:34:00.003-04:00</published><updated>2009-06-16T20:53:59.295-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="design" /><category scheme="http://www.blogger.com/atom/ns#" term="coherence" /><category scheme="http://www.blogger.com/atom/ns#" term="database" /><category scheme="http://www.blogger.com/atom/ns#" term="oracle" /><title type="text">Data Grids for Database Developers</title><content type="html">Back at &lt;a href="http://www.oraclenerd.com/2009/05/collaborate-09-day-3-wrap-up.html"&gt;COLLABORATE&lt;/a&gt;, I met one &lt;a href="http://blackbeanbag.net/wp/"&gt;Patrick Peralta&lt;/a&gt;, member of the Coherence team (reason #109 to go to conferences).&lt;br /&gt;&lt;br /&gt;I spent about 2 hours with Mr. Peralta that day and had quite a bit of fun.  I learned a couple of new tricks (&lt;a href="http://www.oracle.com/technology/products/jrockit/index.html"&gt;JRockit&lt;/a&gt; for one) and got a &lt;i&gt;slightly&lt;/i&gt; better understanding of Coherence.&lt;br /&gt;&lt;br /&gt;I emphasized "slightly" because I still don't quite know how to use it.  Caching data, I get that part.  I guess I do understand it from a high-level perspective...it's the &lt;i&gt;where&lt;/i&gt; part that I haven't quite grasped yet.&lt;br /&gt;&lt;br /&gt;One thing I asked Mr. Peralta to do for me was to right it up, blog it.  Show me (us) how and when to use it.  Through &lt;a href="http://twitter.com/patrickperalta"&gt;twitter&lt;/a&gt;, he's shared with me some links.  Specifically this &lt;a href="http://coherence.oracle.com/display/COH34UG/Defining+a+Data+Grid"&gt;one&lt;/a&gt; on how to define a Data Grid.&lt;br /&gt;&lt;br /&gt;Finally (he did not mention that he likes to procrastinate), he's written something up, &lt;a href=" http://blackbeanbag.net/wp/2009/06/13/an-introduction-to-data-grids-for-database-developers/"&gt;An Introduction to Data Grids for Database Developers&lt;/a&gt;.&lt;blockquote&gt;&lt;b&gt;Smarter Caching&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;An obvious (or maybe &lt;a href="http://www.codinghorror.com/blog/archives/001105.html"&gt;not so obvious&lt;/a&gt; depending on who you ask) first step in scaling a database application is to cache as much as you can. This is fairly easy to do if you have a single app server hitting a database. It becomes more interesting however as you add more app servers to the mix. For instance:&lt;br /&gt;&lt;br /&gt;    * Is it OK if the caches on your app servers are out of sync?&lt;br /&gt;    * What happens if one of the app servers wants to update an item in the cache?&lt;br /&gt;    * How do you minimize the number of database hits to refresh the cache?&lt;br /&gt;    * What if you don’t have enough memory on the app server to cache everything?&lt;/blockquote&gt;It's a very interesting technology.  I would highly encourage you to click through and give it a go.  Leave comments here or abroad.&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-3853911845992923";
/* atom feed */
google_ad_slot = "1428191201";
google_ad_width = 728;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8884584404576003487-2373569621806170162?l=www.oraclenerd.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/kKJ6c3X39OR6w0gfxIGH2UuTHiM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/kKJ6c3X39OR6w0gfxIGH2UuTHiM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/kKJ6c3X39OR6w0gfxIGH2UuTHiM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/kKJ6c3X39OR6w0gfxIGH2UuTHiM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/2373569621806170162/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8884584404576003487&amp;postID=2373569621806170162" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/2373569621806170162" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/2373569621806170162" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/oraclenerd/RahJ/~3/ZWl2N6rd-q0/data-grids-for-database-developers.html" title="Data Grids for Database Developers" /><author><name>oraclenerd</name><uri>http://www.blogger.com/profile/12412013306950057961</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="03223434293565733241" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.oraclenerd.com/2009/06/data-grids-for-database-developers.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-8884584404576003487.post-1098861547573688607</id><published>2009-06-16T17:00:00.005-04:00</published><updated>2009-06-16T17:03:32.980-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="sql" /><category scheme="http://www.blogger.com/atom/ns#" term="oracle" /><title type="text">Oracle's New INSERT Syntax</title><content type="html">Not really Oracle's...just mine.&lt;br /&gt;&lt;br /&gt;I'm busy debugging&lt;pre class="code"&gt;  VALUES&lt;br /&gt;  *&lt;br /&gt;ERROR at line 19:&lt;br /&gt;ORA-00947: not enough values&lt;/pre&gt;I manually count the columns and they're the same.  Run it again.&lt;pre class="code"&gt;  VALUES&lt;br /&gt;  *&lt;br /&gt;ERROR at line 19:&lt;br /&gt;ORA-00947: not enough values&lt;/pre&gt;I then cut and paste both "halves" of the INSERT statement into excel so I can get a row-by-row compare.  &lt;br /&gt;&lt;br /&gt;&lt;table style="width:auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="http://picasaweb.google.com/lh/photo/-5LHWQsKZ_dx-yOVDkbHnw?feat=embedwebsite"&gt;&lt;img src="http://lh6.ggpht.com/_rhCtHYLiamQ/SjffCNh-_AI/AAAAAAAAEe8/Pxs3IRJfcx0/s800/excel.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;Everything looks good, go!&lt;pre class="code"&gt;  VALUES&lt;br /&gt;  *&lt;br /&gt;ERROR at line 19:&lt;br /&gt;ORA-00947: not enough values&lt;/pre&gt;WTF?&lt;br /&gt;&lt;br /&gt;I still haven't figured it out, but that excel picture gave me an idea...&lt;br /&gt;&lt;br /&gt;I tend to put one column on each line, for large tables, this takes up quite a bit of vertical space.  I've seen others put columns (and values) on the same line.  Just looks ugly to me.  Here's what this table looks like:&lt;pre class="code"&gt;INSERT INTO my_table&lt;br /&gt;  ( id,&lt;br /&gt;    create_date,&lt;br /&gt;    update_date,&lt;br /&gt;    col1,&lt;br /&gt;    col2,&lt;br /&gt;    col3,&lt;br /&gt;    col4,&lt;br /&gt;    col5,&lt;br /&gt;    col6,&lt;br /&gt;    col7,&lt;br /&gt;    col8,&lt;br /&gt;    col9,&lt;br /&gt;    col10,&lt;br /&gt;    col11,&lt;br /&gt;    col12,&lt;br /&gt;    col13,&lt;br /&gt;    col14 ) &lt;br /&gt;VALUES &lt;br /&gt;    seq.nextval,&lt;br /&gt;    SYSDATE,&lt;br /&gt;    SYSDATE,&lt;br /&gt;    'A',&lt;br /&gt;    'SOMETHING',&lt;br /&gt;    'SOMETHING',&lt;br /&gt;    'SOMETHING',&lt;br /&gt;    'SOMETHING',&lt;br /&gt;    'SOMETHING',&lt;br /&gt;    'SOMETHING',&lt;br /&gt;    'SOMETHING',&lt;br /&gt;    'SOMETHING',&lt;br /&gt;    'SOMETHING',&lt;br /&gt;    'SOMETHING',&lt;br /&gt;    'SOMETHING',&lt;br /&gt;    'SOMETHING',&lt;br /&gt;    'SOMETHING' );&lt;/pre&gt;Wouldn't it be cool if you could do something like this though?&lt;pre class="code"&gt;INSERT INTO my_table&lt;br /&gt;  ( id =&gt; seq.nexval,&lt;br /&gt;    create_date =&gt; SYSDATE,&lt;br /&gt;    update_date =&gt; SYSDATE, &lt;br /&gt;    col1 =&gt; 'A',&lt;br /&gt;    col2 =&gt; 'SOMETHING',&lt;br /&gt;    col3 =&gt; 'SOMETHING',&lt;br /&gt;    col4 =&gt; 'SOMETHING',&lt;br /&gt;    col5 =&gt; 'SOMETHING',&lt;br /&gt;    col6 =&gt; 'SOMETHING',&lt;br /&gt;    col7 =&gt; 'SOMETHING',&lt;br /&gt;    col8 =&gt; 'SOMETHING',&lt;br /&gt;    col9 =&gt; 'SOMETHING',&lt;br /&gt;    col10 =&gt; 'SOMETHING',&lt;br /&gt;    col11 =&gt; 'SOMETHING',&lt;br /&gt;    col12 =&gt; 'SOMETHING',&lt;br /&gt;    col13 =&gt; 'SOMETHING',&lt;br /&gt;    col14 =&gt; 'SOMETHING' );&lt;/pre&gt;1.  You'd save space.&lt;br /&gt;2.  It would be easier to read and&lt;br /&gt;3.  It would be easier to debug&lt;br /&gt;&lt;br /&gt;Thoughts?&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;b&gt;update:&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;I did solve my problem, I was missing the opening parenthesis in the VALUES clause.&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-3853911845992923";
/* atom feed */
google_ad_slot = "1428191201";
google_ad_width = 728;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8884584404576003487-1098861547573688607?l=www.oraclenerd.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/BvkCnWnlFYfSKF56BfHvxFJn2JU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/BvkCnWnlFYfSKF56BfHvxFJn2JU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/BvkCnWnlFYfSKF56BfHvxFJn2JU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/BvkCnWnlFYfSKF56BfHvxFJn2JU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/1098861547573688607/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8884584404576003487&amp;postID=1098861547573688607" title="7 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/1098861547573688607" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/1098861547573688607" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/oraclenerd/RahJ/~3/H5p32Q5UiKo/oracles-new-insert-syntax.html" title="Oracle's New INSERT Syntax" /><author><name>oraclenerd</name><uri>http://www.blogger.com/profile/12412013306950057961</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="03223434293565733241" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/_rhCtHYLiamQ/SjffCNh-_AI/AAAAAAAAEe8/Pxs3IRJfcx0/s72-c/excel.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">7</thr:total><feedburner:origLink>http://www.oraclenerd.com/2009/06/oracles-new-insert-syntax.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-8884584404576003487.post-5293341332825804986</id><published>2009-06-16T00:01:00.004-04:00</published><updated>2009-06-16T00:18:03.320-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="plsql" /><category scheme="http://www.blogger.com/atom/ns#" term="howto" /><title type="text">PL/SQL:  Split URL Parameters</title><content type="html">I've always had this phobia of anything to do with strings.  Might be because I find it hard to think that way...and by "that way" I have no idea what I'm talking about.&lt;br /&gt;&lt;br /&gt;Whenever I come across this problem, my first instinct is to go through every character and build a string, something like this:&lt;pre class="code"&gt;DECLARE&lt;br /&gt;  l_string VARCHAR2(100) := 'THIS_LITTLE_STRING';&lt;br /&gt;  l_character VARCHAR2(1);&lt;br /&gt;BEGIN&lt;br /&gt;  FOR i IN 1..LENGTH( l_string ) LOOP&lt;br /&gt;    l_character := l_character || SUBSTR( l_string, i, 1 );&lt;br /&gt;  END LOOP;&lt;br /&gt;END;&lt;br /&gt;/&lt;/pre&gt;Of course that means I &lt;i&gt;have&lt;/i&gt; to go through the loop at least 18 times.  How could I loop less?&lt;br /&gt;&lt;br /&gt;Well, I would need to know the delimiter first, in this case, it will be the underscore character:&lt;pre class="code"&gt;DECLARE&lt;br /&gt;  l_string VARCHAR2(100) := 'THIS_LITTLE_STRING';&lt;br /&gt;  l_character VARCHAR2(1);&lt;br /&gt;  l_delimiter VARCHAR2(1) := '_';&lt;br /&gt;BEGIN&lt;br /&gt;...&lt;/pre&gt;OK, that helps.  So what can I do with that?&lt;pre class="code"&gt;DECLARE&lt;br /&gt;  l_string VARCHAR2(100) := 'THIS_LITTLE_STRING';&lt;br /&gt;  l_new_string VARCHAR2(100) := l_string;&lt;br /&gt;  l_token VARCHAR2(30);&lt;br /&gt;  l_character VARCHAR2(1);&lt;br /&gt;  l_delimiter VARCHAR2(1) := '_';&lt;br /&gt;BEGIN&lt;br /&gt;  LOOP&lt;br /&gt;    EXIT WHEN l_new_string IS NULL;&lt;br /&gt;    l_token := SUBSTR( l_new_string, 1, INSTR( l_new_string, '_', 1 ) );&lt;br /&gt;...&lt;/pre&gt;OK, now I remember what I always get confused.  There seems to be this endless stream of SUBSTR and INSTR involved.  It's difficult to follow...for me anyway.  So here's what I've come up with for now.  I am aware of regular expressions and the &lt;a href="http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_util.htm#i1002468"&gt;DBMS_UTILITY.COMMA_TO_TABLE&lt;/a&gt; procedures, but for some reason, I like to reinvent the wheel.  No, not really, I just find it challenging.  More challenging would be for me to start using regular expressions...Anyway, here goes my attempt at splitting a URL string:&lt;pre class="code"&gt;DECLARE&lt;br /&gt;  TYPE my_table IS TABLE OF VARCHAR2(100);&lt;br /&gt;  l_table MY_TABLE := MY_TABLE();&lt;br /&gt;  l_string VARCHAR2(1000) := 'TESTING=YES&amp;&amp;BOLLOCKS=SOMETHING&amp;&amp;&amp;testing=DF';&lt;br /&gt;  l_keyvalue VARCHAR2(100);&lt;br /&gt;  l_delimiter VARCHAR2(5) := '&amp;&amp;';&lt;br /&gt;  l_delimiter_length INTEGER := LENGTH( l_delimiter );&lt;br /&gt;  l_counter INTEGER := 0;&lt;br /&gt;  l_new VARCHAR2(4000);&lt;br /&gt;  l_start INTEGER := 1;&lt;br /&gt;  l_end INTEGER := 0;&lt;br /&gt;BEGIN&lt;br /&gt;  IF SUBSTR( l_string, -1, 1 ) &lt;&gt; l_delimiter THEN&lt;br /&gt;    l_string := l_string || l_delimiter;&lt;br /&gt;  END IF;&lt;br /&gt;&lt;br /&gt;  l_new := l_string;&lt;br /&gt;&lt;br /&gt;  LOOP&lt;br /&gt;    l_counter := l_counter + 1;&lt;br /&gt;    l_end := INSTR( l_new, l_delimiter, 1 );&lt;br /&gt;    l_keyvalue := SUBSTR( l_new, 1, l_end - 1 );&lt;br /&gt;    EXIT WHEN l_keyvalue IS NULL;&lt;br /&gt;    l_table.EXTEND(1);&lt;br /&gt;    l_table(l_counter) := l_keyvalue;&lt;br /&gt;    l_start := l_start + ( l_end + ( l_delimiter_length - 1 ) );&lt;br /&gt;    l_new := SUBSTR( l_string, l_start );&lt;br /&gt;  END LOOP;&lt;br /&gt;  p( 'table counter:  ' || l_table.COUNT );&lt;br /&gt;  FOR I IN 1..l_table.COUNT LOOP&lt;br /&gt;    p( 'string:  ' || l_table(i) );&lt;br /&gt;  END LOOP;&lt;br /&gt;END;&lt;br /&gt;/&lt;br /&gt;&lt;br /&gt;CJUSTICE@TESTING&gt;@T&lt;br /&gt;table counter:  3&lt;br /&gt;string:  TESTING=YES&lt;br /&gt;string:  BOLLOCKS=SOMETHING&lt;br /&gt;string:  &amp;testing=DF&lt;br /&gt;&lt;br /&gt;PL/SQL procedure successfully completed.&lt;br /&gt;&lt;br /&gt;Elapsed: 00:00:00.03&lt;/pre&gt;Voila!  My own URL String Tokenizer.&lt;br /&gt;&lt;br /&gt;Now I just have to write something that will split up the key/value pairs...&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-3853911845992923";
/* atom feed */
google_ad_slot = "1428191201";
google_ad_width = 728;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8884584404576003487-5293341332825804986?l=www.oraclenerd.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/03ph8xdDqjIxLarMKOFoL5lsRMU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/03ph8xdDqjIxLarMKOFoL5lsRMU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/03ph8xdDqjIxLarMKOFoL5lsRMU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/03ph8xdDqjIxLarMKOFoL5lsRMU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/5293341332825804986/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8884584404576003487&amp;postID=5293341332825804986" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/5293341332825804986" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/5293341332825804986" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/oraclenerd/RahJ/~3/XhBJxmKU4gg/plsql-split-url-parameters.html" title="PL/SQL:  Split URL Parameters" /><author><name>oraclenerd</name><uri>http://www.blogger.com/profile/12412013306950057961</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="03223434293565733241" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://www.oraclenerd.com/2009/06/plsql-split-url-parameters.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-8884584404576003487.post-3449844552294164332</id><published>2009-06-11T22:24:00.003-04:00</published><updated>2009-06-11T23:03:05.238-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="sqlunit" /><category scheme="http://www.blogger.com/atom/ns#" term="testing" /><title type="text">SQLUnit:  Database Unit Testing</title><content type="html">What feels like a thousand years ago I used SQLUnit to do create and perform unit tests on database stored procedures. Lots of them.  To the point where that's almost all I was doing.  I both hated it and loved it.  Hated it because it was boring, tedious, mind-numbing work.  Loved it because it gave me confidence in the code I was writing and, once all the tedium was done, could be done quickly.  A small change could be immediately tested to see it's effect.&lt;br /&gt;&lt;br /&gt;Something else happened too, I began to write code thinking about the tests.  Every single line of code was a potential test.  If I do this, how will I test it?  If I do that, how will I test it?  Where do the tests end?  You could theoretically test forever...and then I would inevitably fall down &lt;i&gt;that&lt;/i&gt; rabbit hole.&lt;br /&gt;&lt;br /&gt;Like I was saying, it changed the way I wrote code.  &lt;a href="http://en.wikipedia.org/wiki/Test-driven_development"&gt;Test Driven Development&lt;/a&gt; without writing the tests first (which I can hardly stand).  That was a good thing because I began to anticipate certain errors.  On an INSERT statement with a sequence generated Primary Key, should I trap the exception in code and give it my own error number?  Or just let the ORA-00001 propagate up?  I just let the Oracle error come up, no need to create my own for that.  There's something seriously wrong if you get an error in that case and the whole world should know about it.&lt;br /&gt;&lt;br /&gt;Speaking of exceptions, use them, throw them, don't trap them (mostly) and do something else.  Log it and then RAISE it.  I think it's good for every single developer to know when something is messed up.  I've spent far too much time trying to debug something because all the errors are being trapped and processing just continues.  I've been lucky on some occasions to have error logging, &lt;i&gt;at least&lt;/i&gt;...&lt;br /&gt;&lt;br /&gt;What is &lt;a href="http://sqlunit.sourceforge.net/"&gt;SQLUnit&lt;/a&gt;?&lt;blockquote&gt;SQLUnit is a regression and unit testing harness for testing database stored procedures. An SQLUnit test suite would be written as an XML file. The SQLUnit harness, which is written in Java, uses the JUnit unit testing framework to convert the XML test specifications to JDBC calls and compare the results generated from the calls with the specified results.&lt;/blockquote&gt;Unfortunately it has not been worked on in almost 3 years, but I'd say it's in pretty good shape.  There's support for Procedures, Functions, Ref Cursors and User Defined Types (though I haven't tried this out yet).  The current version is 5.0.  The last version I worked on consistently was 1.3 I believe.  A colleague (who now works for Oracle) from my early days of SQLUnit testing even contributed some Oracle specific items.  &lt;br /&gt;&lt;br /&gt;I used it to build the database for CABEZE, my first, unsuccessful, try at my own business.  It was nice because I was building it from scratch, so I could build all the test data along with it (no testing with production data...though there wasn't really much of that anyway), set up the database (create test data), run the tests and then tear it down back to it's original state (empty).  Unfortunately the systems I've worked on since weren't empty and testing with production, or semi-production (cleansed) data was the only viable alternative.&lt;br /&gt;&lt;br /&gt;Which brings me to now.  I'm trying to reacquaint myself with the tool and writing test cases for various procedures.  I ran into an issue create test cases because all of our credit card numbers were scrambled.  Everything failed with an Invalid Card Number.  Barnacles.  &lt;br /&gt;&lt;br /&gt;Why not create a routine that would generate "real" credit card numbers, more specifically, numbers of the appropriate length that had a check digit?  So credit cards use the &lt;a href="http://en.wikipedia.org/wiki/Luhn_algorithm"&gt;Luhn formula&lt;/a&gt; which is supposed to prevent certain transposition errors.&lt;blockquote&gt;The Luhn algorithm will detect any single-digit error, as well as almost all transpositions of adjacent digits. It will not, however, detect transposition of the two-digit sequence 09 to 90 (or vice versa). It will detect 7 of the 10 possible twin errors (it will not detect 22 ↔ 55, 33 ↔ 66 or 44 ↔ 77).&lt;/blockquote&gt;With CABEZE, I had written my own PL/SQL card number generator (and validator), but I didn't blog at the time and seem to have lost that code.  So I tried writing it again.&lt;br /&gt;&lt;br /&gt;Since I'm using SQLUnit, what a great way to demonstrate the power of the tool.  It's a somewhat complex (to me anyway) formula, so writing up tests for it should help me to figure it out.  Here's the code to create a check digit based on the Luhn formula.&lt;pre class="code"&gt;CREATE OR REPLACE&lt;br /&gt;FUNCTION create_check_digit( p_card_number IN NUMBER ) RETURN NUMBER&lt;br /&gt;IS&lt;br /&gt;  TYPE t_digits IS TABLE OF INTEGER;&lt;br /&gt;  l_table T_DIGITS := T_DIGITS();&lt;br /&gt;  l_count INTEGER := 0;&lt;br /&gt;  l_num INTEGER;&lt;br /&gt;  l_digit INTEGER;&lt;br /&gt;  l_odd INTEGER := 0;&lt;br /&gt;  l_even INTEGER := 0;&lt;br /&gt;  l_sum INTEGER := 0;&lt;br /&gt;  l_check_digit INTEGER;&lt;br /&gt;BEGIN&lt;br /&gt;  IF p_card_number IS NULL THEN&lt;br /&gt;    raise_application_error( -20001, 'you must provide a card number' );&lt;br /&gt;  END IF;&lt;br /&gt;&lt;br /&gt;  FOR i IN REVERSE 1..LENGTH( p_card_number ) LOOP&lt;br /&gt;    l_count := l_count + 1;&lt;br /&gt;    l_table.EXTEND(1);&lt;br /&gt;    l_table( l_count ) := SUBSTR( p_card_number, i, 1 );&lt;br /&gt;  END LOOP;&lt;br /&gt;&lt;br /&gt;  FOR i IN 1..l_table.COUNT LOOP&lt;br /&gt;    l_digit := l_table(i);&lt;br /&gt;    IF MOD( i, 2 ) &gt; 0 THEN&lt;br /&gt;      l_num := l_digit * 2;&lt;br /&gt;      IF l_num &gt; 9 THEN&lt;br /&gt;        FOR i IN 1..LENGTH( l_num ) LOOP&lt;br /&gt;          l_odd := l_odd + SUBSTR( l_num, i, 1 );&lt;br /&gt;        END LOOP;&lt;br /&gt;      ELSE&lt;br /&gt;        l_odd := l_num;&lt;br /&gt;      END IF;&lt;br /&gt;      p( 'odd:  ' || l_odd );&lt;br /&gt;    ELSE&lt;br /&gt;      l_even := l_digit;&lt;br /&gt;    END IF;&lt;br /&gt;    l_sum := l_sum + l_odd + l_even;&lt;br /&gt;    p( 'l_sum:  ' || l_sum );&lt;br /&gt;    l_odd := 0;&lt;br /&gt;    l_even := 0;&lt;br /&gt;  END LOOP;&lt;br /&gt;  l_check_digit := ABS( ( CEIL( MOD( l_sum / 10, 10 ) ) * 10 ) - l_sum );&lt;br /&gt;  p( 'check digit:  ' || l_check_digit );&lt;br /&gt;  p( 'l_sum:  ' || l_sum );&lt;br /&gt;  p( p_card_number || l_check_digit );&lt;br /&gt;  RETURN l_check_digit;&lt;br /&gt;END create_check_digit;&lt;br /&gt;/&lt;/pre&gt;I have no doubt it could be done easier, specifically using regular expressions.  This is just my first go at it...so don't give me a hard time...any other solutions are welcome in the comments.  ;)&lt;br /&gt;&lt;br /&gt;Here's the output of my final test run:&lt;pre class="code"&gt;[sqlunit] *** Running SQLUnit file: p_cc.xml&lt;br /&gt;[sqlunit] Getting connection(DEFAULT)&lt;br /&gt;[sqlunit] Setting up test...&lt;br /&gt;[sqlunit] Running test[1]: PASSING NULL (125ms)&lt;br /&gt;[sqlunit] Running test[2]: VALID CARD NUMBER (4992739871) (15ms)&lt;br /&gt;[sqlunit] Running test[3]: VALID CARD NUMBER (4012888888881881) (16ms)&lt;br /&gt;[sqlunit] Running test[4]: VALID CARD NUMBER (4111111111111111) (0ms)&lt;br /&gt;[sqlunit] Running test[5]: VALID CARD NUMBER (4222222222222) (15ms)&lt;br /&gt;[sqlunit] Running test[6]: RANDOM (1) NUMBER (5) (0ms)&lt;br /&gt;[sqlunit] Running test[7]: RANDOM (2) NUMBER (55) (0ms)&lt;br /&gt;[sqlunit] Running test[8]: RANDOM (3) NUMBER (557) (16ms)&lt;br /&gt;[sqlunit] Running test[9]: RANDOM (4) NUMBER (5579) (0ms)&lt;br /&gt;[sqlunit] Running test[10]: RANDOM (5) NUMBER (65579) (0ms)&lt;br /&gt;[sqlunit] Running test[11]: RANDOM (14) NUMBER (12345678965579) (16ms)&lt;br /&gt;[sqlunit] Running test[12]: RANDOM NUMBER (5498975) (0ms)&lt;br /&gt;[sqlunit] Tearing down test...&lt;/pre&gt;I was able to run a variety of different tests in seconds.  A previous test run looked like this:&lt;pre class="code"&gt;[sqlunit] *** Running SQLUnit file: p_cc.xml&lt;br /&gt;[sqlunit] Getting connection(DEFAULT)&lt;br /&gt;[sqlunit] Setting up test...&lt;br /&gt;[sqlunit] Running test[1]: PASSING NULL (109ms)&lt;br /&gt;[sqlunit] Running test[2]: VALID CARD NUMBER (4992739871) (109ms)&lt;br /&gt;[sqlunit] Assertion "outparams-equal" failed (6(NUMERIC) != 1(NUMERIC) at outparams[0])&lt;br /&gt;[sqlunit] *** expected:&lt;br /&gt;[sqlunit] &lt;result&gt;&lt;br /&gt;[sqlunit]   &lt;outparam id="1" type="NUMERIC"&gt;6&lt;/outparam&gt;&lt;br /&gt;[sqlunit] &lt;/result&gt;&lt;br /&gt;[sqlunit] *** but got:&lt;br /&gt;[sqlunit] &lt;result&gt;&lt;br /&gt;[sqlunit]   &lt;outparam id="1" type="NUMERIC"&gt;1&lt;/outparam&gt;&lt;br /&gt;[sqlunit] &lt;/result&gt;&lt;br /&gt;[sqlunit]&lt;br /&gt;[sqlunit] Running test[3]: VALID CARD NUMBER (4012888888881881) (0ms)&lt;br /&gt;[sqlunit] Running test[4]: VALID CARD NUMBER (4111111111111111) (0ms)&lt;br /&gt;[sqlunit] Running test[5]: VALID CARD NUMBER (4222222222222) (0ms)&lt;br /&gt;[sqlunit] Assertion "outparams-equal" failed (2(NUMERIC) != 0(NUMERIC) at outparams[0])&lt;br /&gt;[sqlunit] *** expected:&lt;br /&gt;[sqlunit] &lt;result&gt;&lt;br /&gt;[sqlunit]   &lt;outparam id="1" type="NUMERIC"&gt;2&lt;/outparam&gt;&lt;br /&gt;[sqlunit] &lt;/result&gt;&lt;br /&gt;[sqlunit] *** but got:&lt;br /&gt;[sqlunit] &lt;result&gt;&lt;br /&gt;[sqlunit]   &lt;outparam id="1" type="NUMERIC"&gt;0&lt;/outparam&gt;&lt;br /&gt;[sqlunit] &lt;/result&gt;&lt;br /&gt;[sqlunit]&lt;br /&gt;[sqlunit] Running test[6]: RANDOM NUMBER (5498975) (0ms)&lt;br /&gt;[sqlunit] Tearing down test...&lt;br /&gt;[sqlunit] sqlunit-ant: SQLUnit Tests Failed: In file: p_cc.xml, tests: 6, failures: 2, errors = 0&lt;br /&gt;[sqlunit] SQLUnit Tests Failed: In file: p_cc.xml, tests: 6, failures: 2, errors = 0&lt;/pre&gt;I could then identify the problem, fix it, and run the tests within seconds.  How cool is that?&lt;br /&gt;&lt;br /&gt;That particular run helped me realize that if I passed in a string of numbers that was even, it would give me the wrong result.  If you look at Visa for instance, it's typically 16 digits long with the final digit being the check digit.  You start at the rightmost digit before the check digit and go backwards.  That was the impetus behind putting the digits into the PL/SQL TABLE OF INTEGERS up above.&lt;br /&gt;&lt;br /&gt;I'll post more on creating validly formatted credit card numbers later, I just wanted to use it as an example for SQLUnit.&lt;br /&gt;&lt;br /&gt;Try it.  Use it.  Let me know how it goes.  Maybe we can get some Java guy to get it started up again.&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-3853911845992923";
/* atom feed */
google_ad_slot = "1428191201";
google_ad_width = 728;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8884584404576003487-3449844552294164332?l=www.oraclenerd.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/uRhtLj7y8Se9lEFSMpXA9Kk-Qxo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/uRhtLj7y8Se9lEFSMpXA9Kk-Qxo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/uRhtLj7y8Se9lEFSMpXA9Kk-Qxo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/uRhtLj7y8Se9lEFSMpXA9Kk-Qxo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/3449844552294164332/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8884584404576003487&amp;postID=3449844552294164332" title="8 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/3449844552294164332" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/3449844552294164332" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/oraclenerd/RahJ/~3/yHy53F9u1Nc/sqlunit-database-unit-testing.html" title="SQLUnit:  Database Unit Testing" /><author><name>oraclenerd</name><uri>http://www.blogger.com/profile/12412013306950057961</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="03223434293565733241" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">8</thr:total><feedburner:origLink>http://www.oraclenerd.com/2009/06/sqlunit-database-unit-testing.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-8884584404576003487.post-3960366254410731652</id><published>2009-06-08T00:25:00.003-04:00</published><updated>2009-06-08T01:01:03.290-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="design" /><category scheme="http://www.blogger.com/atom/ns#" term="database" /><title type="text">UPDATEs in OLTP:  A Design Flaw?</title><content type="html">This one has been on my mind for the past year or so...&lt;br /&gt;&lt;br /&gt;Should you do UPDATEs in an OLTP environment?&lt;br /&gt;&lt;br /&gt;The answer is maybe, or it depends, of course.  &lt;br /&gt;&lt;br /&gt;When I ask this question I ask it in relation to INSERTs.  There is a difference between creating a record and updating a record.  I think it comes down to a design decision.&lt;br /&gt;&lt;br /&gt;For instance, I once used a table to track sessions (web sessions, using Application Context in the database to "reconnect"), it was defined something like the following:&lt;br /&gt;&lt;br /&gt;&lt;table style="width:auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="http://picasaweb.google.com/lh/photo/Pll8cON0-YeCXgwhesEzZQ?feat=embedwebsite"&gt;&lt;img src="http://lh4.ggpht.com/_rhCtHYLiamQ/SiyULrntnzI/AAAAAAAAEeE/-2pEUxrVGeg/s800/sessions.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;b&gt;An Acceptable Time to use UPDATE&lt;/b&gt;&lt;br /&gt;A session defaulted was created with a 30 minute window.  Each page the user would hit would update the END_TIME to SYSDATE + 30 Minutes.  If they had no activity for 30 minutes, the END_TIME would be less then the current time (SYSDATE) and they would be logged out.  This table did exactly what I needed, UPDATEs worked perfectly here.&lt;br /&gt;&lt;br /&gt;What if I wanted to track page hits though?  Could I do that with the current table?  I could possibly add PAGE_ID or something I suppose, but then I would have to write this "complicated" query to find the first START_TIME and then compare that with the last END_TIME.  Kind of changes the meaning of the table right?&lt;br /&gt;&lt;br /&gt;&lt;b&gt;An &lt;i&gt;Unacceptable&lt;/i&gt; Time to use UPDATE&lt;/b&gt;&lt;br /&gt;You have a table of scheduled transactions or some sort of recurring billing.&lt;br /&gt;&lt;br /&gt;&lt;table style="width:auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="http://picasaweb.google.com/lh/photo/8iXw_eqQGWZ1cR5mTZsUdQ?feat=embedwebsite"&gt;&lt;img src="http://lh3.ggpht.com/_rhCtHYLiamQ/SiyWQFaO2JI/AAAAAAAAEeI/0-H-E_HpXGA/s800/scheduled_transactions.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;You use this table by having a job that looks at the DATE_TO_POST, takes those and attempts to post them.  If there is a problem, you update the DATE_TO_POST column to the next date/time (based on rules somewhere) and you increment the TIMES_POSTED counter.  That doesn't sound so bad right?  If you don't have any processing or billing failures, it's not.  But if you do, you lose some valuable data, in my opinion.&lt;br /&gt;&lt;br /&gt;First, get rid of the TIMES_POSTED column.  You don't need it.  Create a record for every single transaction you have posted.  This obviously changes the meaning of the table and will force you to change your code.  &lt;br /&gt;&lt;br /&gt;Here's why it's good though (to remove the UPDATE):  You now have a single record for every attempt.  Your reporting off of this becomes much easier and is performed with SQL.  With the UPDATE, you have to maintain some PL/SQL code ( TIMES_POSTED + 1).  With the INSERT, you don't perform a calculation at all.&lt;br /&gt;&lt;br /&gt;A slightly different example and one that may be more familiar to everyone:&lt;br /&gt;&lt;br /&gt;&lt;table style="width:auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="http://picasaweb.google.com/lh/photo/G8Gg3d6aMAnrOfDtxFLslA?feat=embedwebsite"&gt;&lt;img src="http://lh3.ggpht.com/_rhCtHYLiamQ/SiyZJPsmKSI/AAAAAAAAEeM/HjEHcIArz10/s800/settlement.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;This kind of structure is more suited for a data warehouse.  The columns have been pivoted to make reporting easier.  In an ideal environment, this wouldn't exist on the OLTP server.  However we don't all work in ideal environments and this type of structure is often employed.  I pretty much hate it (in OLTP, not DW).  The volume and complexity of code needed to maintain this type of table is large.  There are all sorts of computations that must be performed and then someone, like me, has to come in and maintain it.  I always vote for scrapping it in favor of the following type structure(s):&lt;br /&gt;&lt;br /&gt;&lt;table style="width:auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="http://picasaweb.google.com/lh/photo/5etPrFm9YS4O2PjqOxd-ww?feat=embedwebsite"&gt;&lt;img src="http://lh3.ggpht.com/_rhCtHYLiamQ/SiyalmbcIKI/AAAAAAAAEeY/Bq7vx1pUfso/s800/settlement_code.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;Now you have INSERT statements as opposed to one or more UPDATE statements.  Reporting tools can then handle the pivoting or whatever else you want to do to the data.&lt;br /&gt;&lt;br /&gt;UPDATEs in an OLTP are not a flaw, but when about to write one, think of the implications.  Is that what you really want to do?  Wouldn't you rather just do an INSERT and be done with it?&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-3853911845992923";
/* atom feed */
google_ad_slot = "1428191201";
google_ad_width = 728;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8884584404576003487-3960366254410731652?l=www.oraclenerd.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/yulmfbmgslmtqGrDuhXELfJpJC8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/yulmfbmgslmtqGrDuhXELfJpJC8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/yulmfbmgslmtqGrDuhXELfJpJC8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/yulmfbmgslmtqGrDuhXELfJpJC8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/3960366254410731652/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8884584404576003487&amp;postID=3960366254410731652" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/3960366254410731652" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/3960366254410731652" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/oraclenerd/RahJ/~3/Xz7QZ4K2RL8/updates-in-oltp-design-flaw.html" title="UPDATEs in OLTP:  A Design Flaw?" /><author><name>oraclenerd</name><uri>http://www.blogger.com/profile/12412013306950057961</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="03223434293565733241" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/_rhCtHYLiamQ/SiyULrntnzI/AAAAAAAAEeE/-2pEUxrVGeg/s72-c/sessions.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://www.oraclenerd.com/2009/06/updates-in-oltp-design-flaw.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-8884584404576003487.post-4096481145850962164</id><published>2009-06-03T21:16:00.003-04:00</published><updated>2009-06-03T21:50:09.873-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="social media" /><category scheme="http://www.blogger.com/atom/ns#" term="blogging" /><title type="text">Am I a New Media Douchebag?</title><content type="html">I'll continue after you've viewed the video...&lt;br /&gt;&lt;br /&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/zSP8xm_gaK4&amp;hl=en&amp;fs=1&amp;"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/zSP8xm_gaK4&amp;hl=en&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;Someone called me a New Media Douchebag today...jokingly of course.  (I hope...)&lt;br /&gt;&lt;br /&gt;I posted the video to Twitter and &lt;a href="http://twitter.com/krisrice"&gt;Kris Rice&lt;/a&gt; didn't think I complained enough to meet the 3rd requirement.  I suggested that I'd be the Susy Sunshine of the New Media Douchebags...or something like that.&lt;br /&gt;&lt;br /&gt;I've definitely embraced the idea of the New Media or Social Media or whatever you want to call it.  It seems kind of natural to me.  I've always been the social butterfly at work, the "nice" IT guy and I love to talk.  My old &lt;a href="http://www.oraclenerd.com/2007/09/good-manager.html"&gt;manager&lt;/a&gt; struggled with whether this was good or bad.  He saw the good of building solid relationships with business types but also the amount of time.  I'm sure he wasn't the first manager to be concerned about my talking.&lt;br /&gt;&lt;br /&gt;I've become an advocate of the New Media as well.  &lt;br /&gt;&lt;br /&gt;I think everyone and their mother should &lt;a href="http://www.oraclenerd.com/2009/05/why-you-should-blog.html"&gt;blog&lt;/a&gt;.  &lt;br /&gt;&lt;br /&gt;I think everyone should use Twitter.  &lt;br /&gt;&lt;br /&gt;I created a group on LinkedIn for &lt;a href="http://www.linkedin.com/groups?about=&amp;gid=1893573&amp;trk=anet_ug_grppro"&gt;ORACLENERD&lt;/a&gt;(s).&lt;br /&gt;&lt;br /&gt;I scored a &lt;a href="http://www.oraclenerd.com/2009/03/collaborate-09-oaug-forum.html"&gt;pass&lt;/a&gt; to COLLABORATE 09.&lt;br /&gt;&lt;br /&gt;I received detailed &lt;a href="http://www.oraclenerd.com/2009/03/obiee-how-to-migrate-your-rpd.html"&gt;instructions&lt;/a&gt; on migrating my rpd (OBIEE) file to production from &lt;a href="http://hekatonkheires.blogspot.com/"&gt;Christian Berg&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I'm sure there are others, but I can't think of them right now.&lt;br /&gt;&lt;br /&gt;This write about this crap all the time now.&lt;br /&gt;&lt;br /&gt;I've even &lt;a href="http://theappslab.com/2009/05/04/follow-collaborate-09-with-the-oraclenerd/"&gt;discussed&lt;/a&gt; doing some sort of presentation on the value of New/Social media.&lt;br /&gt;&lt;br /&gt;Am I a New Media Douchebag?  Should I relinquish ORACLENERD to someone more deserving?  Tell me what you think.  Some guy at work said I come off as "Extreme" (I think he meant as a future Exadata team member) in my database ramblings...so I can take it.&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-3853911845992923";
/* atom feed */
google_ad_slot = "1428191201";
google_ad_width = 728;
google_ad_height = 15;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8884584404576003487-4096481145850962164?l=www.oraclenerd.com'/&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/E3MEGCaWbBOUoX8MGQ6D0iGmB-c/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/E3MEGCaWbBOUoX8MGQ6D0iGmB-c/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/E3MEGCaWbBOUoX8MGQ6D0iGmB-c/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/E3MEGCaWbBOUoX8MGQ6D0iGmB-c/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/4096481145850962164/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=8884584404576003487&amp;postID=4096481145850962164" title="11 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/4096481145850962164" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8884584404576003487/posts/default/4096481145850962164" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/oraclenerd/RahJ/~3/cYfriXUp-XE/am-i-new-media-douchebag.html" title="Am I a New Media Douchebag?" /><author><name>oraclenerd</name><uri>http://www.blogger.com/profile/12412013306950057961</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="03223434293565733241" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">11</thr:total><feedburner:origLink>http://www.oraclenerd.com/2009/06/am-i-new-media-douchebag.html</feedburner:origLink></entry></feed>
