<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	>

<channel>
	<title>Bar Solutions WebLog</title>
	<atom:link href="http://bar-solutions.com/weblog/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://bar-solutions.com/weblog</link>
	<description>The beginning of knowledge is the discovery of something we do not understand. [Frank Herbert]</description>
	<pubDate>Wed, 25 Aug 2010 05:39:41 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.7.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>OPP 2010</title>
		<link>http://bar-solutions.com/weblog/?p=477</link>
		<comments>http://bar-solutions.com/weblog/?p=477#comments</comments>
		<pubDate>Wed, 25 Aug 2010 05:39:41 +0000</pubDate>
		<dc:creator>Patch</dc:creator>
		
		<category><![CDATA[APEX]]></category>

		<category><![CDATA[Common]]></category>

		<category><![CDATA[Oracle]]></category>

		<category><![CDATA[PL/SQL]]></category>

		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://bar-solutions.com/weblog/?p=477</guid>
		<description><![CDATA[On October 27th and 28th the combined OPP (Oracle PL/SQL Programming) and APEXposed conference is coming to Europe. To Brussels to be exact. I have had the privilege to attend these conferences since the first one in 2005. The nice thing about this conference is that it is the only conference (at least that I [...]]]></description>
			<content:encoded><![CDATA[<p>On October 27th and 28th the combined <a href="http://www.odtugopp.com/">OPP</a> (Oracle PL/SQL Programming) and <a href="http://www.odtugapextraining.com/">APEXposed</a> conference is coming to Europe. To Brussels to be exact. I have had the privilege to attend these conferences since the first one in 2005. The nice thing about this conference is that it is the only conference (at least that I know of) that is totally focused on PL/SQL. Three tracks with all kinds of ideas of what you can do in PL/SQL. From using <a href="http://download.oracle.com/docs/cd/E11882_01/server.112/e10713/srvrside.htm#CNCPT1786">collections</a> (been around since Oracle 7) to <a href="http://download.oracle.com/docs/cd/E11882_01/server.112/e10595/general010.htm#ADMIN13167">Edition Based Redefinition</a> (Oracle 11Gr2).<br />
If there is a slot in the agenda that has nothing you like, you are welcome to switch to the APEXposed conference to see if there is something you like.<br />
I know I am a big fan of PL/SQL since it has nothing to do with building a front-end but more with getting the job done, using as less resources as possible and applying the best techniques available in the version I am working with.<br />
I am not much of a visual developer. But using <a href="http://apex.oracle.com/">APEX</a>, even I can make nice applications that are easy to build and even look nice.<br />
Shameless plug: I will also be doing a presentation on my favorite tool <a href="http://www.allroundautomations.com/plsqldev.html">PL/SQL Developer</a>. If you attend the conference, I hope you will come and see this.</p>
]]></content:encoded>
			<wfw:commentRss>http://bar-solutions.com/weblog/?feed=rss2&amp;p=477</wfw:commentRss>
		</item>
		<item>
		<title>Where Am I…</title>
		<link>http://bar-solutions.com/weblog/?p=475</link>
		<comments>http://bar-solutions.com/weblog/?p=475#comments</comments>
		<pubDate>Sun, 27 Jun 2010 11:12:57 +0000</pubDate>
		<dc:creator>Patch</dc:creator>
		
		<category><![CDATA[Oracle]]></category>

		<category><![CDATA[PL/SQL]]></category>

		<guid isPermaLink="false">http://bar-solutions.com/weblog/?p=475</guid>
		<description><![CDATA[
.code, .code pre
{
	font-size: small;
	color: #00007F;
	font-family: &#8220;Courier New&#8221;
                    Courier
                    monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.code pre { margin: 0em; }
.code .rem [...]]]></description>
			<content:encoded><![CDATA[<style type="text/css">
<p>.code, .code pre
{
	font-size: small;
	color: #00007F;
	font-family: &#8220;Courier New&#8221;
                    Courier
                    monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.code pre { margin: 0em; }
.code .rem { color: #008000; }
.code .kwrd { color: #007F7F; }
.code .comm { color: #ff0000; }
.code .str { color: #006080; }
.code .op { color: #0000c0; }
.code .preproc { color: #cc6633; }
.code .asp { background-color: #ffff00; }
.code .html { color: #800000; }
.code .attr { color: #ff0000; }
.code .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.code .lnum { color: #606060; }</style>
<p align="left">On my new job we wanted to provide some logging. Especially about what program is currently running. Of course it would be easy enough to add a line at the start of the program with the name of that program and one at the end. But, as things go during development, names (and types) of programs tend to change and we would have to change those lines accordingly. Something that can (and will) be easily forgotten.</p>
<p align="left">Why not have the code tell us where we are. That way we wouldn’t have to change our code if the program name changes. But unfortunately there is no such thing as a function to tell me where I am.</p>
<p><span id="more-475"></span></p>
<p align="left">So, I decided to write one of my own. In the old days, using Novell network software, there was a function called <strong>WhoAmI</strong>, so I decided to name my function <strong>WhereAmI</strong>. What does <a href="http://www.oracle.com" target="_blank">Oracle</a> offer me to tell me where I am. There is such a thing as <strong>DBMS_UTILITY.FORMAT_CALL_STACK</strong>. This provides a nice call stack of all the programs called in sequence like this:</p>
<div class="code">
<p><pre class="alt"><span class="lnum">   1:  </span>----- PL/SQL Call Stack -----</pre>
<pre><span class="lnum">   2:  </span>  object      line  object</pre>
<pre class="alt"><span class="lnum">   3:  </span>  handle    number  name</pre>
<pre><span class="lnum">   4:  </span>287562CC         7  function UTIL.WHEREAMI</pre>
<pre class="alt"><span class="lnum">   5:  </span>29DEBFF8         7  anonymous block</pre>
</p>
</div>
<p>The first three line are header information. The fourth line is where we are when this function is being called, being our function, so the first line of interest to us is the fifth line:</p>
<div class="code">
<p><pre class="alt"><span class="lnum">   1:  </span>29DEBFF8         7  anonymous block</pre>
</p>
</div>
<p>Actually we only need the text in the third column. That tells us exactly where we are. Using string searching capabilities we remove everything we don’t need. First of all, we search for the position of the first space, then we copy the rest of the string and by using the trim functionality we remove any (leading and trailing) spaces from it. Now we have:</p>
<div class="code">
<p><pre class="alt"><span class="lnum">   1:  </span>7  anonymous block</pre>
</p>
</div>
<p>If we execute this trick again we are left with the information we are interested in:</p>
<div class="code">
<p><pre class="alt"><span class="lnum">   1:  </span>anonymous block</pre>
</p>
</div>
<p>Using this function at the start and end of our programs where to see the exact name of the program we are entering or exiting no matter what the type is, or if it is packaged or not. Only thing it doesn’t show me is whether it’s a private program or a local program.</p>
<p>The complete code for the function is like this:</p>
<div class="code">
<p><pre class="alt"><span class="lnum">   1:  </span><span class="kwrd">FUNCTION</span> whereami <span class="kwrd">RETURN VARCHAR2 IS</span></pre>
<pre><span class="lnum">   2:  </span>  l_callstack   <span class="kwrd">VARCHAR2</span>(2000);</pre>
<pre class="alt"><span class="lnum">   3:  </span>  l_returnvalue <span class="kwrd">VARCHAR2</span>(100);</pre>
<pre><span class="lnum">   4:  </span><span class="kwrd">BEGIN</span></pre>
<pre class="alt"><span class="lnum">   5:  </span>    &lt;&lt;code&gt;&gt;</pre>
<pre><span class="lnum">   6  </span>  <span class="comm">-- Get the current callstack</span></pre>
<pre class="alt"><span class="lnum">   7:  </span>  l_callstack := dbms_utility.format_call_stack;</pre>
<pre><span class="lnum">   8:  </span> <span class="comm">-- The line of interest is the fourth line.</span></pre>
<pre class="alt"><span class="lnum">   9:  </span>  l_returnvalue := substr(l_callstack</pre>
<pre><span class="lnum">  10:  </span>                         ,instr(l_callstack, chr(10), 1, 4) + 1</pre>
<pre class="alt"><span class="lnum">  11:  </span>                         ,(instr(l_callstack, chr(10), 1, 5) - instr(l_callstack, chr(10), 1, 4)));</pre>
<pre><span class="lnum">  12:  </span>  <span class="comm">-- All we are interested in is the type and the name of the program.</span></pre>
<pre class="alt"><span class="lnum">  13:  </span>  l_returnvalue := <span class="kwrd">TRIM</span>(substr(l_returnvalue, instr(l_returnvalue, ' ', 1)));</pre>
<pre><span class="lnum">  14  </span>   l_returnvalue := <span class="kwrd">TRIM</span>(substr(l_returnvalue, instr(l_returnvalue, ' ', 1)));</pre>
<pre class="alt"><span class="lnum">  15:  </span>  <span class="kwrd">RETURN</span> l_returnvalue;</pre>
<pre><span class="lnum">  16  </span><span class="kwrd">END</span> whereami;</pre>
</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://bar-solutions.com/weblog/?feed=rss2&amp;p=475</wfw:commentRss>
		</item>
		<item>
		<title>Report in APEX</title>
		<link>http://bar-solutions.com/weblog/?p=472</link>
		<comments>http://bar-solutions.com/weblog/?p=472#comments</comments>
		<pubDate>Wed, 31 Dec 1969 19:00:00 +0000</pubDate>
		<dc:creator>Patch</dc:creator>
		
		<category><![CDATA[APEX]]></category>

		<category><![CDATA[Oracle]]></category>

		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://bar-solutions.com/weblog/?p=472</guid>
		<description><![CDATA[The other day someone at a customer had a question about displaying a report. The different options are in a table so he could easily use a report to display the options. But he wanted to display three columns of options. That is, if there are 10 options, he would want to display 3 rows [...]]]></description>
			<content:encoded><![CDATA[<p>The other day someone at a customer had a question about displaying a report. The different options are in a table so he could easily use a report to display the options. But he wanted to display three columns of options. That is, if there are 10 options, he would want to display 3 rows of 3 options and a single row of 1 option.</p>
<table border="1" cellspacing="1" cellpadding="1" width="60">
<tbody>
<tr>
<td valign="top" width="58">option 1</td>
</tr>
<tr>
<td valign="top" width="58">option 2</td>
</tr>
<tr>
<td valign="top" width="58">option 3</td>
</tr>
<tr>
<td valign="top" width="58">option 4</td>
</tr>
<tr>
<td valign="top" width="58">option 5</td>
</tr>
<tr>
<td valign="top" width="58">option 6</td>
</tr>
<tr>
<td valign="top" width="58">option 7</td>
</tr>
<tr>
<td valign="top" width="58">option 8</td>
</tr>
<tr>
<td valign="top" width="58">option 9</td>
</tr>
<tr>
<td valign="top" width="58">option 10</td>
</tr>
</tbody>
</table>
<p>should be displayed as:</p>
<table border="1" cellspacing="1" cellpadding="1" width="164">
<tbody>
<tr>
<td valign="top" width="58">option 1</td>
<td valign="top" width="54">option 2</td>
<td valign="top" width="50">option 3</td>
</tr>
<tr>
<td valign="top" width="58">option 4</td>
<td valign="top" width="54">option 5</td>
<td valign="top" width="50">option 6</td>
</tr>
<tr>
<td valign="top" width="58">option 7</td>
<td valign="top" width="54">option 8</td>
<td valign="top" width="50">option 9</td>
</tr>
<tr>
<td valign="top" width="58">option 10</td>
<td valign="top" width="54">&#160;</td>
<td valign="top" width="50">&#160;</td>
</tr>
</tbody>
</table>
<p>How can this be done. The answer is in the query.</p>
<p><span id="more-472"></span></p>
<p>I decided to try some stuff and came up with the solution. First I need about 10 records.<br />
  <br /><font size="2" face="Courier New">SELECT rownum rn FROM user_source WHERE rownum &lt; 11;</font></p>
<table border="1" cellspacing="1" cellpadding="1" width="12">
<tbody>
<tr>
<td valign="top" width="10">1</td>
</tr>
<tr>
<td valign="top" width="10">2</td>
</tr>
<tr>
<td valign="top" width="10">3</td>
</tr>
<tr>
<td valign="top" width="10">4</td>
</tr>
<tr>
<td valign="top" width="10">5</td>
</tr>
<tr>
<td valign="top" width="10">6</td>
</tr>
<tr>
<td valign="top" width="10">7</td>
</tr>
<tr>
<td valign="top" width="10">8</td>
</tr>
<tr>
<td valign="top" width="10">9</td>
</tr>
<tr>
<td valign="top" width="10">10</td>
</tr>
</tbody>
</table>
<p>Using subquery factoring helps me build the query step by step. Next, I need to split the results into three groups. Using the MOD function I can tell in which group a record should reside.</p>
<p><font size="2" face="Courier New">WITH t AS<br />
    <br /> (SELECT rownum rn FROM user_source WHERE rownum &lt; 11)<br />
    <br />select MOD(rn,3) rn2<br />
    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,rn from t;</font></p>
<table border="1" cellspacing="1" cellpadding="1" width="22">
<tbody>
<tr>
<td valign="top" width="10">1</td>
<td valign="top" width="10">1</td>
</tr>
<tr>
<td valign="top" width="10">2</td>
<td valign="top" width="10">2</td>
</tr>
<tr>
<td valign="top" width="10">0</td>
<td valign="top" width="10">3</td>
</tr>
<tr>
<td valign="top" width="10">1</td>
<td valign="top" width="10">4</td>
</tr>
<tr>
<td valign="top" width="10">2</td>
<td valign="top" width="10">5</td>
</tr>
<tr>
<td valign="top" width="10">0</td>
<td valign="top" width="10">6</td>
</tr>
<tr>
<td valign="top" width="10">1</td>
<td valign="top" width="10">7</td>
</tr>
<tr>
<td valign="top" width="10">2</td>
<td valign="top" width="10">8</td>
</tr>
<tr>
<td valign="top" width="10">0</td>
<td valign="top" width="10">9</td>
</tr>
<tr>
<td valign="top" width="10">1</td>
<td valign="top" width="10">10</td>
</tr>
</tbody>
</table>
<p>Now I want to split the results into different sets. Let’s begin by creating a set of the first records.</p>
<p><font size="2" face="Courier New">WITH t AS<br />
    <br /> (SELECT rownum rn FROM user_source WHERE rownum &lt; 11),</p>
<p>x AS</p>
<p> (SELECT MOD(rn</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,3) rn2</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,rn</p>
<p>&#160;&#160;&#160; FROM t)</p>
<p> SELECT rn&#160;&#160;&#160;&#160; v1</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,rownum r1</p>
<p>&#160;&#160;&#160; FROM x</p>
<p>&#160;&#160; WHERE rn2 = 1</font>;</p>
<table border="1" cellspacing="1" cellpadding="1" width="26">
<tbody>
<tr>
<td valign="top" width="10">1</td>
<td valign="top" width="14">1</td>
</tr>
<tr>
<td valign="top" width="10">4</td>
<td valign="top" width="14">2</td>
</tr>
<tr>
<td valign="top" width="10">7</td>
<td valign="top" width="14">3</td>
</tr>
<tr>
<td valign="top" width="10">10</td>
<td valign="top" width="14">4</td>
</tr>
</tbody>
</table>
<p>If I create three set of data (unique) then I can join them again</p>
<p><font size="2" face="Courier New">WITH t AS<br />
    <br /> (SELECT rownum rn FROM user_source WHERE rownum &lt; 11),</p>
<p>x AS</p>
<p> (SELECT MOD(rn,3) rn2</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,rn</p>
<p>&#160;&#160;&#160; FROM t),</p>
<p>all1 AS</p>
<p> (SELECT rn&#160;&#160;&#160;&#160; v1</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,rownum r1</p>
<p>&#160;&#160;&#160; FROM x</p>
<p>&#160;&#160; WHERE rn2 = 1),</p>
<p>all2 AS</p>
<p> (SELECT rn&#160;&#160;&#160;&#160; v2</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,rownum r2</p>
<p>&#160;&#160;&#160; FROM x</p>
<p>&#160;&#160; WHERE rn2 = 2),</p>
<p>all3 AS</p>
<p> (SELECT rn&#160;&#160;&#160;&#160; v3</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,rownum r3</p>
<p>&#160;&#160;&#160; FROM x</p>
<p>&#160;&#160; WHERE rn2 = 0)</p>
<p>SELECT v1</p>
<p>&#160;&#160;&#160;&#160;&#160; ,v2</p>
<p>&#160;&#160;&#160;&#160;&#160; ,v3</p>
<p>&#160; FROM all1</p>
<p>&#160; JOIN all2 ON (r1 = r2)</p>
<p>&#160; JOIN all3 ON (r2 = r3);</font></p>
<table border="1" cellspacing="1" cellpadding="1" width="32">
<tbody>
<tr>
<td valign="top" width="10">1</td>
<td valign="top" width="10">2</td>
<td valign="top" width="10">3</td>
</tr>
<tr>
<td valign="top" width="10">4</td>
<td valign="top" width="10">5</td>
<td valign="top" width="10">6</td>
</tr>
<tr>
<td valign="top" width="10">7</td>
<td valign="top" width="10">8</td>
<td valign="top" width="10">9</td>
</tr>
</tbody>
</table>
<p>What happened to number 10? The records don’t always exist in the second and third set, so I have to use an outer join to see all the records available.</p>
<p><font size="2" face="Courier New">WITH t AS<br />
    <br /> (SELECT rownum rn FROM user_source WHERE rownum &lt; 11),</p>
<p>x AS</p>
<p> (SELECT MOD(rn,3) rn2</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,rn</p>
<p>&#160;&#160;&#160; FROM t),</p>
<p>all1 AS</p>
<p> (SELECT rn&#160;&#160;&#160;&#160; v1</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,rownum r1</p>
<p>&#160;&#160;&#160; FROM x</p>
<p>&#160;&#160; WHERE rn2 = 1),</p>
<p>all2 AS</p>
<p> (SELECT rn&#160;&#160;&#160;&#160; v2</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,rownum r2</p>
<p>&#160;&#160;&#160; FROM x</p>
<p>&#160;&#160; WHERE rn2 = 2),</p>
<p>all3 AS</p>
<p> (SELECT rn&#160;&#160;&#160;&#160; v3</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; ,rownum r3</p>
<p>&#160;&#160;&#160; FROM x</p>
<p>&#160;&#160; WHERE rn2 = 0)</p>
<p>SELECT v1</p>
<p>&#160;&#160;&#160;&#160;&#160; ,v2</p>
<p>&#160;&#160;&#160;&#160;&#160; ,v3</p>
<p>&#160; FROM all1</p>
<p>&#160; LEFT OUTER JOIN all2 ON (r1 = r2)</p>
<p>&#160; LEFT OUTER JOIN all3 ON (r2 = r3);</font></p>
<table border="1" cellspacing="1" cellpadding="1" width="34">
<tbody>
<tr>
<td valign="top" width="10">1</td>
<td valign="top" width="12">2</td>
<td valign="top" width="10">3</td>
</tr>
<tr>
<td valign="top" width="10">4</td>
<td valign="top" width="12">5</td>
<td valign="top" width="10">6</td>
</tr>
<tr>
<td valign="top" width="10">7</td>
<td valign="top" width="12">8</td>
<td valign="top" width="10">9</td>
</tr>
<tr>
<td valign="top" width="10">10</td>
<td valign="top" width="12">&#160;</td>
<td valign="top" width="10">&#160;</td>
</tr>
</tbody>
</table>
<p>Now the result is exactly the way I (or actually the customer) wanted. All that needs to be done now is adapt this query so that it uses the real data. But the idea is in place.</p>
]]></content:encoded>
			<wfw:commentRss>http://bar-solutions.com/weblog/?feed=rss2&amp;p=472</wfw:commentRss>
		</item>
		<item>
		<title>CodeGen and APEX.</title>
		<link>http://bar-solutions.com/weblog/?p=464</link>
		<comments>http://bar-solutions.com/weblog/?p=464#comments</comments>
		<pubDate>Sun, 28 Mar 2010 14:17:20 +0000</pubDate>
		<dc:creator>Patch</dc:creator>
		
		<category><![CDATA[APEX]]></category>

		<category><![CDATA[CodeGen]]></category>

		<category><![CDATA[Oracle]]></category>

		<guid isPermaLink="false">http://bar-solutions.com/weblog/?p=464</guid>
		<description><![CDATA[When building code to support your APEX application, it is always nice to be able to generate large parts of that code. I am really fond of creating code using the QDA. The only trouble is that you need to create all the packages separately. What I have found works for me is to create [...]]]></description>
			<content:encoded><![CDATA[<p>When building code to support your APEX application, it is always nice to be able to generate large parts of that code. I am really fond of creating code using the QDA. The only trouble is that you need to create all the packages separately. What I have found works for me is to create a single script for the sequence, all the packages and the trigger creation. This is something that had to be done by hand because QNXO generates separate files for the different parts of the Table API.<span id="more-464"></span><br />
I could create a new script and just copy in all the lines in the other scripts, but what would happen if one was to change? I would have to make that change in multiple places. Something I would rather not do. So instead of creating a new script with copies of the current code I decided to copy the &#8216;install&#8217; script and adapt that to create the complete install script. Instead of calling a different file using the @@ option in SQL*Plus (or PL/SQL Developer of course), I [INCLUDE]d the scripts I needed. This way I am using the exact same script which is being used when creating the QDA scripts &#8216;the old way&#8217;. I had a bit of a problem generating the sequence and the triggers. I appeared that some setup scripts were not run.<br />
In the existing &#8216;tree&#8217; these scripts were run at different levels of the hierarchy. I could of course create a similar hierarchy, but I don&#8217;t want that. I don&#8217;t like to be constrained to a special way to work. CodeGen supplies the possibility to run setup scripts prior to the actual script. There is my way out. I want to run some setup scripts prior to my actual script.<br />
The setup scripts that need to be executed:<br />
<strong>NAMING-CONVENTIONS-FOR:&#8221;QCGU Development Architecture for PL/SQL&#8221;</strong><br />
<strong>QDA_flags_for_table_processing</strong><br />
The actual script:<br />
<code>REM One full install script for the QDA code<br />
REM Based on the existing scripts.<br />
REM SPOD: Single Point Of Definition<br />
REM (c) 2010: Bar Solutions<br />
[include]primary_key_generation_controls<br />
#<br />
# Remove any lines that aren&#8217;t relevant.<br />
#<br />
REM Remove any lines you don&#8217;t need or don&#8217;t apply to your situtation.</p>
<p># 1.4 Do not always include this line.<br />
[IF]{qda_generating_pky}[EQ]{qda_true}[AND]{pkycoldatatype_sql}[IN]INTEGER,NUMBER<br />
CREATE SEQUENCE {sequence_name:[objname/a]};</p>
<p>[ENDIF]<br />
[INCLUDE]Types Package Specification<br />
SHOW ERRORS<br />
[INCLUDE]Query Package Specification<br />
SHOW ERRORS<br />
[INCLUDE]Change Package Specification<br />
SHOW ERRORS<br />
[IF]{include_utility_packages}[EQ]{qda_true}<br />
[INCLUDE]Utilities package specification<br />
SHOW ERRORS<br />
[ENDIF]<br />
[INCLUDE]Query Package Body<br />
SHOW ERRORS<br />
[INCLUDE]Change Package Body<br />
SHOW ERRORS<br />
[IF]{include_utility_packages}[EQ]{qda_true}<br />
[INCLUDE]Utilities package body<br />
SHOW ERRORS<br />
[ENDIF]<br />
#<br />
# 1.4 Apply logic here from the audit trigger script<br />
[SETALIAS]l_pky_gen[TO]{qda_false}<br />
[IF]{qda_generating_pky}[EQ]{qda_true}[AND]onepkycol<br />
  [SETALIAS]l_pky_gen[TO]{qda_true}<br />
[ENDIF]<br />
[IF]{l_pky_gen}[EQ]{qda_true}[OR][-]<br />
    {grp_int_table}[EQ]{qda_true}[OR][-]<br />
    {have_audit_columns}[EQ]{qda_true}<br />
[INCLUDE]Audit triggers<br />
[ENDIF]</code><br />
And of course I need to copy the arguments from the scripts that are executed when I run the entire script group.<br />
And there it is, a single script to install the packages for the QDA.</p>
]]></content:encoded>
			<wfw:commentRss>http://bar-solutions.com/weblog/?feed=rss2&amp;p=464</wfw:commentRss>
		</item>
		<item>
		<title>Custom Authentication Scheme In APEX</title>
		<link>http://bar-solutions.com/weblog/?p=462</link>
		<comments>http://bar-solutions.com/weblog/?p=462#comments</comments>
		<pubDate>Wed, 31 Dec 1969 19:00:00 +0000</pubDate>
		<dc:creator>Patch</dc:creator>
		
		<category><![CDATA[APEX]]></category>

		<category><![CDATA[Oracle]]></category>

		<category><![CDATA[PL/SQL]]></category>

		<guid isPermaLink="false">http://bar-solutions.com/weblog/?p=462</guid>
		<description><![CDATA[I have been playing around with Apex 4.0 on http://tryapexnow.com.  When playing around with some ideas I have for application I decided to use the logging mechanism I created a while ago, to see what’s going on in the custom code.
Since this is a hosted environment it is not too easy to check the [...]]]></description>
			<content:encoded><![CDATA[<p>I have been playing around with <a title="Oracle Application Express" href="http://apex.oracle.com/" target="_blank" rel="nofollow">Apex</a> 4.0 on <a href="http://tryapexnow.com">http://tryapexnow.com</a>.  When playing around with some ideas I have for application I decided to use the logging mechanism I created a while ago, to see what’s going on in the custom code.<br />
Since this is a hosted environment it is not too easy to check the records in the log. There were a couple of queries needed to check the log. I usually run these from my IDE, but the is not possible now. They can be easily run using the SQL Workshop, but I have APEX at my disposal. So why not create a simple application to display the information in the log table. But if I create an application and start using it, it becomes publicly available and everybody can see what’s being logged (including the values of parameters). I need some sort of authentication here.<br />
<span id="more-462"></span><br />
Luckily APEX provides the possibility to add your own authentication schemes. Since I am running this on a hosted environment I cannot use ‘Database’ or ‘Database Account’. So I need to create my own, custom authentication. This is described in detail in the book Pro Oracle Application Express especially in chapter 3 . So I decided to follow the steps here.</p>
<p>The steps include examples of creating a user table and a custom authorization function in a package. It also includes some pointers on how to handle passwords. I did everything exactly as described in the book, changed the authorization scheme to the newly created one and tried to log in to my application. But it failed. Even with the correct credentials. What is going on here? Must be something I did wrong. Let’s try to create the schema again (dispose of the ‘old’ one) and now follow all the steps in the wizard.<br />
In the book they said to create the scheme from here (with minimal information) and then change the properties later. But I want to go through the entire wizard so I decided to click the ‘Next>’ button.<br />
The 6th page of the wizard is where the real action takes place. I want to use my own custom function to authenticate the session.<br />
The function should return a boolean and take username and password as input.<br />
The function is declared in the package as follows:</p>
<p>FUNCTION authenticate(p_username IN VARCHAR2<br />
                     ,p_password IN VARCHAR2) RETURN BOOLEAN;Now it’s time to test the new scheme. Change the current authorization scheme to the one just created.<br />
Then try to run the application again.<br />
Login with some faulty credentials and notice that I am not authenticated.<br />
When trying to login with correct credentials I am allowed access to the application.</p>
<p>Now what is the difference between this authorization scheme and the one I created earlier. I think it has something to do with the session not valid part of the authentication. When I created it by filling in just the name and the description of the scheme it used the –BUILTIN- ‘Not Valid URL’. In my new scheme it says here to use the login page instead. It seems that did the trick. Checking the Application Express scheme shows me roughly the same settings. I think I nailed this one. It took me a lot of time and I want to thank my friends <a title="Jornica" href="http://jornica.blogspot.com" rel="nofollow" target="_blank">Jorrit</a> and <a title="Notes on Oracle" href="http://nuijten.blogspot.com" rel="nofollow" target="_blank">Alex</a> for helping me where they could (although they had not needed this yet) especially where to look or provide me with more documentation.</p>
]]></content:encoded>
			<wfw:commentRss>http://bar-solutions.com/weblog/?feed=rss2&amp;p=462</wfw:commentRss>
		</item>
		<item>
		<title>Fun with APEX&#8230;</title>
		<link>http://bar-solutions.com/weblog/?p=403</link>
		<comments>http://bar-solutions.com/weblog/?p=403#comments</comments>
		<pubDate>Sun, 27 Dec 2009 15:14:07 +0000</pubDate>
		<dc:creator>Patch</dc:creator>
		
		<category><![CDATA[Oracle]]></category>

		<category><![CDATA[PL/SQL]]></category>

		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://bar-solutions.com/weblog/?p=403</guid>
		<description><![CDATA[ During the last couple of days I have been playing around with the new, hosted version of APEX. I know I haven’t been using all the features available in APEX and I have mostly been using my mod_plsql skills, because I don’t know how to do certain things in APEX (yet).


I have been (and [...]]]></description>
			<content:encoded><![CDATA[<p align="left"><a href="http://bar-solutions.com/weblog/wp-content/img/FunwithAPEX_E490/favorite.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="favorite" border="0" alt="favorite" align="left" src="http://bar-solutions.com/weblog/wp-content/img/FunwithAPEX_E490/favorite_thumb.png" width="65" height="95" /></a> During the last couple of days I have been playing around with the new, hosted version of APEX. I know I haven’t been using all the features available in APEX and I have mostly been using my mod_plsql skills, because I don’t know how to do certain things in APEX (yet).</p>
<div align="left"></div>
<p><span id="more-403"></span>
<p align="left">I have been (and am still) rebuilding a webpage I have built using PHP and MySQL (<a title="http://bar-solutions.com/ezlinks" href="http://bar-solutions.com/ezlinks">http://bar-solutions.com/ezlinks</a>). I am pretty pleased with the result so far (<a title="http://tryapexnow.com/apex/f?p=2231" href="http://tryapexnow.com/apex/f?p=2231">http://tryapexnow.com/apex/f?p=2231</a> username/password: demo/demo)</p>
<p align="left">It is fun to build code (PL/SQL code of course) to have the pages do what I want them to. I have been using a nice <a title="Splitting a comma delimited string the RegExp way" href="http://nuijten.blogspot.com/2009/07/splitting-comma-delimited-string-regexp.html" rel="nofollow" target="_blank">regular expression</a> by <a title="Notes on Oracle" href="http://nuijten.blogspot.com/" rel="nofollow" target="_blank">Alex Nuijten</a> to split the defined tags into separate entries.</p>
<p align="left">If you have any issues, bugs etc, please don’t hesitate to mention them. Maybe I will solve it (if at all possible ;-))</p>
]]></content:encoded>
			<wfw:commentRss>http://bar-solutions.com/weblog/?feed=rss2&amp;p=403</wfw:commentRss>
		</item>
		<item>
		<title>Export APEX to the rescue&#8230;</title>
		<link>http://bar-solutions.com/weblog/?p=392</link>
		<comments>http://bar-solutions.com/weblog/?p=392#comments</comments>
		<pubDate>Mon, 23 Nov 2009 08:06:48 +0000</pubDate>
		<dc:creator>Patch</dc:creator>
		
		<category><![CDATA[Oracle]]></category>

		<guid isPermaLink="false">http://bar-solutions.com/weblog/?p=392</guid>
		<description><![CDATA[I had a good time in Atlanta at OPP doing my presentations. When I got back I had some issues regarding our APEX application that I needed to solve. But the guys at the office decided to drop all objects from the schema and create all the necessary objects again. This way we got rid [...]]]></description>
			<content:encoded><![CDATA[<p>I had a good time in Atlanta at <a href="http://www.odtugopp.com">OPP</a> doing my presentations. When I got back I had some issues regarding our <a href="http://apex.oracle.com">APEX</a> application that I needed to solve. But the guys at the office decided to drop all objects from the schema and create all the necessary objects again. This way we got rid of all the development code and all the rubbish gathered over the last couple of months. That is a good thing. Not so good was that the APEX application was also imported again and I created a script that creates a run-only version of the application.<span id="more-392"></span><br />
This is a good thing, because on the test, acceptance and definitely production database we don’t want the development to continue. We have a space for that and that is called, the development environment. Luckily I had a sandbox application in place that was still accessible. I decided to export this application twice, once as a RUN-ONLY application and once as a RUN-AND-BUILD application.</p>
<p>By comparing both the scripts that have been created I thought I could find the difference on how the application would be created.</p>
<p>It appeared that, besides from some time issues, the main difference lies in the way the application is being created. With a run-only application the call to create the application is like this:</p>
<p>&#8211;application/create_application<br />
begin<br />
wwv_flow_api.create_flow(<br />
&#8230;<br />
  p_build_status      => &#8216;RUN_ONLY&#8217;,<br />
&#8230;<br />
end;<br />
/</p>
<p>With a run-and-build application the call to create the application is like this:</p>
<p>&#8211;application/create_application<br />
begin<br />
wwv_flow_api.create_flow(<br />
&#8230;<br />
  p_build_status      => &#8216;RUN_AND_BUILD&#8217;,<br />
&#8230;<br />
);<br />
end;<br />
/<br />
Well, that looked promising. I decided that I had to change the current export script as this had the RUN_ONLY option in place. I couldn’t wreck it anymore than it already was.</p>
<p>I changed the script. ran it, and there it was. My application was available for editing again. Instead of finding out what table data to change and spending hours finding out where Oracle stores the way an application behaves, it took me just the time to export (twice), do the comparison, make the change en run the import. Less than an hours work. Thank Oracle for such an easy way to rescue my application and save me from hours, if not days, of recreating it.</p>
]]></content:encoded>
			<wfw:commentRss>http://bar-solutions.com/weblog/?feed=rss2&amp;p=392</wfw:commentRss>
		</item>
		<item>
		<title>Life after OPP&#8230;</title>
		<link>http://bar-solutions.com/weblog/?p=339</link>
		<comments>http://bar-solutions.com/weblog/?p=339#comments</comments>
		<pubDate>Sat, 14 Nov 2009 12:35:37 +0000</pubDate>
		<dc:creator>Patch</dc:creator>
		
		<category><![CDATA[Oracle]]></category>

		<category><![CDATA[PL/SQL]]></category>

		<category><![CDATA[Personal]]></category>

		<guid isPermaLink="false">http://bar-solutions.com/weblog/?p=339</guid>
		<description><![CDATA[As I am writing this I am on a plane ride back from Atlanta to Amsterdam. I had a great time in Atlanta during OPP. I also enjoyed doing the sessions I presented. One was on ‘Table Functions’ and another was on Collections and Bulk Operations. Both these session were scheduled in the same timeslot [...]]]></description>
			<content:encoded><![CDATA[<p align="left">As I am writing this I am on a plane ride back from Atlanta to Amsterdam. I had a great time in Atlanta during OPP. I also enjoyed doing the sessions I presented. One was on ‘Table Functions’ and another was on Collections and Bulk Operations. Both these session were scheduled in the same timeslot <a title="Steven Feuerstein" href="http://www.stevenfeuerstein.com" rel="nofollow" target="_blank">Steven Feuerstein</a> got, yet both times I have drawn a bigger audience than he did. Something I am really proud of.</p>
<p align="left">I also did a presentation in the tools track for <a title="Allround Automations" href="http://www.allroundautomations.com/" rel="nofollow" target="_blank">Allround Automations</a>’ product ‘PL/SQL Developer’. This audience was of course smaller, but it allowed this presentation to be more interactive. The guys from Allround were nice enough to sent out some shirts and books and the audience really enjoyed those. I could barely save one for myself ;-).</p>
<p align="left">I have been busy for months preparing for this seminar. Not full time of course, but it has taken up a lot of my thoughts over the last couple of months. Now what should I do with my time. Maybe prepare for OPP2010 ;-). Don’t even know when and if there will be one. Don’t even know if I will be invited as a presenter again. </p>
<p align="left">I know I learned a lot preparing for the sessions. I know how to use the stuff I was talking about, but I needed more in depth knowledge, which I got from reading documentation, blogs, books etc. So, until next year, I will be doing something different with my spare time. Maybe I can focus on becoming on OCP on PL/SQL.</p>
]]></content:encoded>
			<wfw:commentRss>http://bar-solutions.com/weblog/?feed=rss2&amp;p=339</wfw:commentRss>
		</item>
		<item>
		<title>OPP-Preview (partially Dutch)</title>
		<link>http://bar-solutions.com/weblog/?p=338</link>
		<comments>http://bar-solutions.com/weblog/?p=338#comments</comments>
		<pubDate>Tue, 13 Oct 2009 14:53:04 +0000</pubDate>
		<dc:creator>Patch</dc:creator>
		
		<category><![CDATA[Oracle]]></category>

		<guid isPermaLink="false">http://bar-solutions.com/weblog/?p=338</guid>
		<description><![CDATA[ De Oracle PL/SQL Programming conference vind dit jaar in Atlanta, Georgia plaats. Patrick Barel is daarbij om een drietal presentaties te geven. Voor degene die niet aanwezig zullen zijn in Atlanta vind deze OPP-Preview plaats.     Tijdens deze KC zal Patrick twee van deze presentaties geven.     Na [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.odtugopp.com"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="WebButton" border="0" alt="WebButton" align="right" src="http://bar-solutions.com/weblog/wp-content/WebButton1.jpg" width="141" height="264" /></a> De <strong>O</strong>racle <strong>P</strong>L/SQL <strong>P</strong>rogramming conference vind dit jaar in Atlanta, Georgia plaats. Patrick Barel is daarbij om een drietal presentaties te geven. Voor degene die niet aanwezig zullen zijn in Atlanta vind deze <a href="http://www.amis.nl/activiteiten.php?id=763" target="_blank">OPP-Preview</a> plaats.     <br />Tijdens deze KC zal Patrick twee van deze presentaties geven.     <br />Na het diner zal Alex een re-run geven van zijn ODTUG presentatie: &quot;SQL Holmes&quot;. </p>
<p>Het programma voor deze avond:    <br /><strong>16:30</strong><b>      <br /><strong>&quot;Pipelined table functions&quot; - Patrick Barel</strong>       <br /></b>Pipelined table functions offer an ideal convergence of the elegance and simplicity of PL/SQL with the performance of SQL. Complex data transformations are effortless to develop and support with PL/SQL, yet to achieve high-performance data processing, we often resort to set-based SQL solutions. Pipelined functions bridge the gap between the two methods effortlessly, but they also have some unique performance features of their own, making them a superb performance optimization tool.</p>
<p><strong>18:00</strong><b>      <br /><strong>diner: Chinees</strong></b></p>
<p><strong>Na diner (rond 19:00): </strong><b>     <br /><strong>&quot;SQL Holmes: The Case of the Missing Performance&quot; - Alex Nuijten</strong>       <br /></b>During this presentation, a case study is unfolded to reveal the true cause of a slow performing query. Did the database just &quot;have a bad day&quot;? Was the evil DBA to blame? The PL/SQL developer who didn&#8217;t get enough coffee? Or was it the application sending the &quot;wrong&quot; query in the first place?     <br />In this classic &quot;whodunnit&quot; you will take a tour past the crime scene. Investigate the query, use the tools of the trade and collect all the relevant information. Follow the trail to uncover the truth and nothing but the truth&#8230;</p>
<p><strong>20:00</strong><b>      <br /><strong>Ter afsluiting:</strong>       <br /><strong>&quot;Optimizing SQL with Collections&quot; - Patrick Barel</strong>       <br /></b>Collections (array-like structures in PL/SQL) are used in two of the most important performance features of PL/SQL: FORALL and BULK COLLECT. This session demonstrates the power of these features and offers in-depth guidance on how to apply them.</p>
]]></content:encoded>
			<wfw:commentRss>http://bar-solutions.com/weblog/?feed=rss2&amp;p=338</wfw:commentRss>
		</item>
		<item>
		<title>Reading values from a varchar2 indexed Associative Array</title>
		<link>http://bar-solutions.com/weblog/?p=336</link>
		<comments>http://bar-solutions.com/weblog/?p=336#comments</comments>
		<pubDate>Fri, 02 Oct 2009 14:33:16 +0000</pubDate>
		<dc:creator>Patch</dc:creator>
		
		<category><![CDATA[Oracle]]></category>

		<category><![CDATA[PL/SQL]]></category>

		<guid isPermaLink="false">http://bar-solutions.com/weblog/?p=336</guid>
		<description><![CDATA[Oracle has provided us with collections since Oracle 7. It is one of the most renamed features in the Oracle database. In Oracle 7 they were called ‘PL/SQL Tables’. In Oracle 8 they were renamed to ‘Index By Tables’ and since Oracle 9 they are called ‘Associative Arrays’. If you index by an integer value [...]]]></description>
			<content:encoded><![CDATA[<p align="left"><a href="http://bar-solutions.com/weblog/wp-content/logooracle.gif"><img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="logo-oracle" border="0" alt="logo-oracle" align="left" src="http://bar-solutions.com/weblog/wp-content/logooracle_thumb.gif" width="124" height="54" /></a><a href="http://www.oracle.com" target="_blank">Oracle</a> has provided us with collections since Oracle 7. It is one of the most renamed features in the Oracle database. In Oracle 7 they were called ‘PL/SQL Tables’. In Oracle 8 they were renamed to ‘Index By Tables’ and since Oracle 9 they are called ‘Associative Arrays’. If you index by an integer value then you can read the values by using an integer index variable. If the array is dense, that means all the indexes, from the first to the last, have a value associated to them you can even use a numeric for loop to get to the data. But what if you index by a string value, which is a possibility since Oracle 9i. </p>
<div align="left"></div>
<p><span id="more-336"></span>
<p align="left"><a href="http://bar-solutions.com/weblog/wp-content/9i.gif"><img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="9i" border="0" alt="9i" align="right" src="http://bar-solutions.com/weblog/wp-content/9i_thumb.gif" width="57" height="133" /></a>The solution is actually rather simple. Using a simple loop. First of all create an index variable of the same type you use to index the collection. It would be kind of silly to declare the collection using a varchar2(10) and then declare an index variable as a varchar2(5). If an index value would be ‘Patrick’ then this wouldn’t fit in the index variable resulting in a error.</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:c2f1561b-e301-4a9c-a68d-3f30bfdbc61a" class="wlWriterEditableSmartContent">
<pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;;font-family:Courier New;font-size:12"><span style="color: #000000;">ORA</span><span style="color: #808080;">-</span><span style="color: #800000; font-weight: bold;">06502</span><span style="color: #000000;">: PL</span><span style="color: #808080;">/</span><span style="color: #000000;">SQL: numeric </span><span style="color: #808080;">or</span><span style="color: #000000;"> value error: </span><span style="color: #0000FF;">character</span><span style="color: #000000;"> string buffer too small</span></pre>
<p><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --></div>
<p align="left">Then assign the index variable the value of the first index used. Now start the loop and do the stuff you want with the collection. At the end of the loop assign the next index value to the variable. If you try to read past the end of the collection, then the value of the index will be NULL, which is a great marker to exit the loop.</p>
<p align="left">If you put the exit clause as the first statement in the loop, then there is no reason to check for any items present in the collection. If you want to check how many items are present, then use &lt;collection&gt;.count.</p>
<p align="left">I have created a small script to demonstrate how it can be done:</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:b728b05e-3749-479b-8c21-11fa583a0b95" class="wlWriterEditableSmartContent">
<pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;;font-family:Courier New;font-size:12"><span style="color: #0000FF;">declare</span><span style="color: #000000;">
  subtype index_t </span><span style="color: #0000FF;">is</span><span style="color: #000000;"> </span><span style="color: #0000FF;">varchar2</span><span style="color: #000000;">(</span><span style="color: #800000; font-weight: bold;">10</span><span style="color: #000000;">);
  type  birthdates_tt </span><span style="color: #0000FF;">is</span><span style="color: #000000;"> </span><span style="color: #0000FF;">table</span><span style="color: #000000;"> </span><span style="color: #0000FF;">of</span><span style="color: #000000;"> date </span><span style="color: #0000FF;">index</span><span style="color: #000000;"> </span><span style="color: #0000FF;">by</span><span style="color: #000000;"> index_t;
  l_birthdates birthdates_tt;
  l_indx index_t;
</span><span style="color: #0000FF;">begin</span><span style="color: #000000;">
  </span><span style="color: #008080;">--</span><span style="color: #008080;"> Fill the table with the birthdates</span><span style="color: #008080;">
</span><span style="color: #000000;">  l_birthdates(</span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">Patrick</span><span style="color: #FF0000;">'</span><span style="color: #000000;">) :</span><span style="color: #808080;">=</span><span style="color: #000000;"> to_date(</span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">29-12-1972</span><span style="color: #FF0000;">'</span><span style="color: #000000;">,</span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">DD-MM-YYYY</span><span style="color: #FF0000;">'</span><span style="color: #000000;">);
  l_birthdates(</span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">Dana</span><span style="color: #FF0000;">'</span><span style="color: #000000;">) :</span><span style="color: #808080;">=</span><span style="color: #000000;"> to_date(</span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">06-03-1976</span><span style="color: #FF0000;">'</span><span style="color: #000000;">,</span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">DD-MM-YYYY</span><span style="color: #FF0000;">'</span><span style="color: #000000;">);
  l_birthdates(</span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">Quinty</span><span style="color: #FF0000;">'</span><span style="color: #000000;">) :</span><span style="color: #808080;">=</span><span style="color: #000000;"> to_date(</span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">18-12-1998</span><span style="color: #FF0000;">'</span><span style="color: #000000;">,</span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">DD-MM-YYYY</span><span style="color: #FF0000;">'</span><span style="color: #000000;">);
  l_birthdates(</span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">Kayleigh</span><span style="color: #FF0000;">'</span><span style="color: #000000;">) :</span><span style="color: #808080;">=</span><span style="color: #000000;"> to_date(</span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">19-11-2000</span><span style="color: #FF0000;">'</span><span style="color: #000000;">,</span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">DD-MM-YYYY</span><span style="color: #FF0000;">'</span><span style="color: #000000;">);
  l_birthdates(</span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">Mitchell</span><span style="color: #FF0000;">'</span><span style="color: #000000;">) :</span><span style="color: #808080;">=</span><span style="color: #000000;"> to_date(</span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">23-06-2003</span><span style="color: #FF0000;">'</span><span style="color: #000000;">,</span><span style="color: #FF0000;">'</span><span style="color: #FF0000;">DD-MM-YYYY</span><span style="color: #FF0000;">'</span><span style="color: #000000;">);

  </span><span style="color: #008080;">--</span><span style="color: #008080;"> make index variable the same as the first from the list</span><span style="color: #008080;">
</span><span style="color: #000000;">  l_indx :</span><span style="color: #808080;">=</span><span style="color: #000000;"> l_birthdates.first;
  </span><span style="color: #008080;">--</span><span style="color: #008080;"> start a simple loop</span><span style="color: #008080;">
</span><span style="color: #000000;">  loop
    </span><span style="color: #008080;">--</span><span style="color: #008080;"> exit the loop when we passed the end</span><span style="color: #008080;">
</span><span style="color: #000000;">    </span><span style="color: #0000FF;">exit</span><span style="color: #000000;"> </span><span style="color: #0000FF;">when</span><span style="color: #000000;"> l_indx </span><span style="color: #0000FF;">is</span><span style="color: #000000;"> </span><span style="color: #0000FF;">null</span><span style="color: #000000;">;
    </span><span style="color: #008080;">--</span><span style="color: #008080;"> write the value of the index and the value at index in the AA to screen</span><span style="color: #008080;">
</span><span style="color: #000000;">    dbms_output.put_line(l_indx </span><span style="color: #808080;">||</span><span style="color: #FF0000;">'</span><span style="color: #FF0000;"> =&gt; </span><span style="color: #FF0000;">'</span><span style="color: #808080;">||</span><span style="color: #000000;">l_birthdates(l_indx));
    </span><span style="color: #008080;">--</span><span style="color: #008080;"> select the next index value from the list</span><span style="color: #008080;">
</span><span style="color: #000000;">    l_indx :</span><span style="color: #808080;">=</span><span style="color: #000000;"> l_birthdates.</span><span style="color: #0000FF;">next</span><span style="color: #000000;">(l_indx);
  </span><span style="color: #0000FF;">end</span><span style="color: #000000;"> loop;
</span><span style="color: #0000FF;">end</span><span style="color: #000000;">;
</span><span style="color: #808080;">/</span></pre>
<p><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --></div>
<p align="left"><a href="http://bar-solutions.com/weblog/wp-content/WebButton.jpg"><img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="WebButton" border="0" alt="WebButton" align="right" src="http://bar-solutions.com/weblog/wp-content/WebButton_thumb.jpg" width="141" height="264" /></a>I hope this information helps in leveraging the power of collections. That is no need to know the index values upfront, because you can traverse the collection at runtime where you don’t know the values of the indexes used. Some of this behavior and more about collections will be part of my presentation about <a href="http://www.odtugopp.com/presentations.html#optimizingcollections">Optimizing SQL with Collections</a> at <a href="http://www.odtugopp.com" target="_blank">OPP2009</a>. </p>
]]></content:encoded>
			<wfw:commentRss>http://bar-solutions.com/weblog/?feed=rss2&amp;p=336</wfw:commentRss>
		</item>
	</channel>
</rss>
