<?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/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Alistair Lattimore &#187; Database</title>
	<atom:link href="http://www.lattimore.id.au/category/database/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.lattimore.id.au</link>
	<description>The day to day goings on of our family</description>
	<lastBuildDate>Mon, 30 Jan 2012 12:59:57 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>Are Daily Backups Really Sufficent?</title>
		<link>http://www.lattimore.id.au/2007/08/23/are-daily-backups-really-sufficent/</link>
		<comments>http://www.lattimore.id.au/2007/08/23/are-daily-backups-really-sufficent/#comments</comments>
		<pubDate>Wed, 22 Aug 2007 14:15:45 +0000</pubDate>
		<dc:creator>Al</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Hardware]]></category>
		<category><![CDATA[Work]]></category>

		<guid isPermaLink="false">http://www.lattimore.id.au/2007/08/23/are-daily-backups-really-sufficent/</guid>
		<description><![CDATA[Monday afternoon we had a critical failure of an Oracle database at work. Within a few minutes of the fault taking place, I started seeing block corruption errors whilst I was reviewing some information in the production environment. At this &#8230; <a href="http://www.lattimore.id.au/2007/08/23/are-daily-backups-really-sufficent/">Continue reading <span class="meta-nav">&#8594;</span></a>
Related posts:<ol>
<li><a href='http://www.lattimore.id.au/2008/02/04/wordpress-upgrade/' rel='bookmark' title='WordPress Upgrade'>WordPress Upgrade</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>Monday afternoon we had a critical failure of an Oracle database at work. Within a few minutes of the fault taking place, I started seeing block corruption errors whilst I was reviewing some information in the production environment. At this stage, I was thinking that we might have dropped a disk in the SAN but referred it onto our database administrator to rectify it.</p>
<p>As is quite common, our environment consists of multiple Oracle 10g RAC nodes connected into a shared data source. The shared data source in this instance is a SAN, where we have a whole bunch of disks configured in groups for redundancy and performance. As soon as the database administrator became involved, it became apparent that we didn&#8217;t drop a single disk but had in fact lost access to an entire group of disks within the SAN.</p>
<p>Due to the manner in which the SAN and Oracle are configured, we were not in a position where running in a RAID environment was going to help. If we had dropped a single disk or a subset of disks from any group within the SAN, everything would have been fine; unfortunately we dropped an entire disk group. The end result of this was that we were forced to roll back our database to the previous nights backup.</p>
<p>The following days have been spent recovering the lost days data through various checks and balances; but it takes a lot of time and energy from everyone involved to make this happen. We&#8217;ve been fortunate enough to trade for several years without <em>ever</em> needing to roll back our production database due to some sort of significant event; which I suppose we should be thankful for.</p>
<p>After three years without performing a production disaster recovery, had we become complacent about data restoration and recovery as haven&#8217;t really needed it before? I believe that since we haven&#8217;t had a requirement to perform a disaster recovery for some three years, that our previous data recovery guidelines have now become out of date. Whilst a daily backup may have been more than sufficient for this particular database two or three years ago, the business has undergone significant growth since that time. The daily changeset for this database is now significant enough that, whilst having a daily backup is critical &#8211; it requires significant amounts of work to recover all of the data in a moderate time frame.</p>
<p>As a direct result of this disaster, we&#8217;re going to be reviewing our data recovery policies shortly. The outcome of that discussion will most likely be that we require higher levels of redundancy in our environment to reduce the impact of a failure. Whilst it would be ideal to have an entire copy of our production hardware, it probably isn&#8217;t going to be a cost effective solution. I&#8217;m open to suggestions about what sort of data recovery we implement, however I think that having some sort of independent warm spare may win out.</p>
<p>What have we learned out of this whole event:</p>
<ul>
<li>daily backup of data is mandatory</li>
<li>daily backup of data may not be sufficient</li>
<li>verify that your backup sets are valid, invalid backup data isn&#8217;t worth the media it is stored on</li>
<li>be vigilant about keeping data recovery strategies in step with business growth and expectations</li>
</ul>
<p>Maybe periodic disasters are actually healthy for a business? Whilst every business strives to avoid any sort of down time, I expect that as a direct result of the typically high availability of certain systems that disaster recovery isn&#8217;t put through its paces often or rigorously enough; which may result in longer downtimes or complete loss of data when an actual disaster recovery is required.</p>
<p>Related posts:<ol>
<li><a href='http://www.lattimore.id.au/2008/02/04/wordpress-upgrade/' rel='bookmark' title='WordPress Upgrade'>WordPress Upgrade</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.lattimore.id.au/2007/08/23/are-daily-backups-really-sufficent/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Tech Ed 2007, Day 3 Wrap Up</title>
		<link>http://www.lattimore.id.au/2007/08/11/tech-ed-2007-day-3-wrap-up/</link>
		<comments>http://www.lattimore.id.au/2007/08/11/tech-ed-2007-day-3-wrap-up/#comments</comments>
		<pubDate>Sat, 11 Aug 2007 12:45:45 +0000</pubDate>
		<dc:creator>Al</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.lattimore.id.au/2007/08/11/tech-ed-2007-day-3-wrap-up/</guid>
		<description><![CDATA[Yesterday I looked into the building of Background Motion using the Composite Web Block, the Enterprise Library and putting all of the different .NET 3.x technologies together in a demonstration product named Dinner Now. Today was focused around SQL Server &#8230; <a href="http://www.lattimore.id.au/2007/08/11/tech-ed-2007-day-3-wrap-up/">Continue reading <span class="meta-nav">&#8594;</span></a>
Related posts:<ol>
<li><a href='http://www.lattimore.id.au/2007/08/09/tech-ed-2007-day-1-wrap-up/' rel='bookmark' title='Tech Ed 2007, Day 1 Wrap Up'>Tech Ed 2007, Day 1 Wrap Up</a></li>
<li><a href='http://www.lattimore.id.au/2007/08/10/tech-ed-2007-day-2-wrap-up/' rel='bookmark' title='Tech Ed 2007, Day 2 Wrap Up'>Tech Ed 2007, Day 2 Wrap Up</a></li>
<li><a href='http://www.lattimore.id.au/2006/06/03/iis-dropping-sessions/' rel='bookmark' title='IIS Dropping Sessions'>IIS Dropping Sessions</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><a href="/2007/08/10/tech-ed-2007-day-2-wrap-up/">Yesterday</a> I looked into the building of <a href="http://www.backgroundmotion.com/">Background Motion</a> using the Composite Web Block, the Enterprise Library and putting all of the different .NET 3.x technologies together in a demonstration product named Dinner Now. Today was focused around SQL Server 2005 performance, optimisation and scalability followed by .NET language pragmatics.</p>
<h2>Writing Applications That Make SQL Server 2005 Fly</h2>
<p>Shu Scott presented about writing applications that make SQL Server 2005 fly, however I don&#8217;t think that name reflected the presentation all that well. The talk would have been better titled &#8216;Understanding The Cost Based Optimiser To Make SQL Server 2005 Fly&#8217;. None the less, Shu raised a lot of great points in her presentation and some of them I thought interesting are below:</p>
<ul>
<li>Don&#8217;t use a function passing in a column as a parameter within a query, such as in a <code>WHERE</code> clause. SQL Server 2005 calculates statistics for a table per column, so as soon as you use a function on the column the statistics are unusable. The off shoot of this is that SQL Server 2005 can massively under or over estimate the selectivity of a table which on a complex-ish based query can dramatically change the query plan that SQL Server will choose.</li>
<li>Don&#8217;t alter an input parameter to a function or stored procedure after the procedure has started. Shu didn&#8217;t specify exactly why this is the case, however after investigating it further on the internet; it is related to the point below regarding parameter sniffing.</li>
<li>Avoid using local variables within a function or procedure in <code>WHERE</code> statements. During the presentation, I didn&#8217;t get a clear understanding of why this was sub-optimal, however after some research online it is caused by the cost based optimiser having to use a reduced quality estimate for the selectivity of the table. You can avoid this problem by supplying the <code>OPTION(RECOMPILE&gt;</code> hint, use a literal instead of a local variable if possible, parameterise the query an accept the value via an input parameter.</li>
<li>Use automatic statistics, if you have a requirement to not use it &#8211; disable it on a per table basis if possible as having quality statistics for your database is vital in the cost based optimiser doing its job.</li>
<li>Do parameterise your queries where they are common, with a lot of reuse and are hit often. Do not parameterise queries that are ad-hoc or long running. Presumably there is no gain in parameterising a long running query as the server is already going to be spending significant time processing the query, in which case the few milliseconds the server spends generating a query plan won&#8217;t be noticed.</li>
<li>Be aware of parameter sniffing, which is where SQL Server uses the values of the input values to a function/procedure to produce the query plan. This is normally a very good thing, however if the cached plan happens to represent an atypical set of input values &#8211; then it is likely that the performance of a typical query is going to be severely impacted.</li>
<li>Look to utilise the <code>INCLUDE</code> keyword when creating non-clustered indexes. The <code>INCLUDE</code> keyword allows you to extend past the 900 byte limit on the index key and also allows you to include previously disallowed column types within the index (ex: nvarchar(max)). This type of index is excellent for index coverage, as all columns identified are stored within the index in leaf nodes, however only the key columns enforce the index type.</li>
<li>If you are unable to edit an SQL statement for some reason, consider using the plan guides. A plan guide is essentially a set of option hints for the query, however you aren&#8217;t editing the query itself to apply them. You configure the plan guides for a stored procedure, function or an individual statement and when it is matched SQL Server 2005 will automatically apply the suggested guides to the statement.</li>
<li>In a similar fashion to the plan guide, there is a more complex option called <code>USE PLAN</code> which lets you supply an actual execution plan to the SQL statement, again without editing the SQL statement directly. Essentially, you extract the XML representation for the execution plan you would prefer to have execute and supply that to the SQL statement. If you have skewed data sets, this would be a good option to guarantee consistent access speed for a particular query. Using the skewed data sets as an example, it would be possible to have SQL Server cache a query plan which represents the atypical data and as such performs very poorly for the majority of the typical data. Supply the query plan to the SQL statement can avoid that happening. It is worth noting though, if you do supply a query plan you would need to revisit the stored plan periodically to make sure that it still reflects the most efficient access path for your particular data set.</li>
</ul>
<h2>Implementing Scale Out Solutions With SQL Server 2005</h2>
<p>This presentation was about scaling SQL Server 2005 out, such that you&#8217;re able to continue adding more and more servers to the mix to distribute the load across. I had previously read the majority of the information covered, however I learned about two features named the SQL Server Service Broker and Query Notifications.</p>
<ul>
<li>Linked servers let you move whole sections of a database onto another server and you tell the primary server where the other data resides. Linked servers are transactionally safe, however will perform only as fast as the slowest component within the linked server group.</li>
<li>Distributed Partitioned Views allows you to move subsets of a tables data across servers and uses linked servers behind the scenes to communicate between servers. A partition might be as simple as customers 1 through 100,000 in partition A and 100,001 through 200,000 in partition B and so on.</li>
<li>SQL Server Shared Database (SSD) allows you to attach many servers to a single read only copy of the database, which might be a great way of increasing performance for a heavily utilised reporting server with relatively static data. Unfortunately, the servers reading from the database need to be detached to refresh the database but this could be managed in an off peak period to reduce impact.</li>
<li>Snapshop Replication snapshots an entire database and replicates it into the subscribers. Snapshot replication isn&#8217;t used a lot as it&#8217;s data and resource intensive. It is most commonly used to set up a base system and then enable merge replication to bring it up to date with the publisher or to refresh an infrequently changing database periodically.</li>
<li>Merge Replication tracks the changes to the data on the publishers and bundles them together, only sending the net changes when appropriate. Merge replication supports bi-directional replication and it also implements conflict resolution as well, however there is no guarantee of consistency as the changes aren&#8217;t necessarily being replicated in a near real time environment.</li>
<li>Transaction Replication sends all changes to all subscribers and is transactionally safe. If there were a lot of DML taking place in a database, there would be considerable overhead for using transactional replication as a simple <code>UPDATE</code> statement which might effect 100 rows locally is sent to the subscribers as 100 independent SQL statements; in case some or all of the subscribes have additional data that the publisher does not.</li>
<li>Peer To Peer (P2P) Replication is a variation of transactional replication however it requires that each peer be the master of it&#8217;s own data so as to avoid key read/write problems across servers and consistency issues. As an example, all of the Brisbane office writes its changes into server A, while Sydney writes its changes into server B. By making sure that each server &#8216;owns&#8217; its respective block of data, it is then possible and safe to replicate data between all peers safely.</li>
<li>SQL Server Service Broker (SSB) provides a reliable asynchronous messaging system to SQL Server 2005, that allows you to pass messages between application either within the same database, same server or distributed over many servers and databases. The service broker doesn&#8217;t do the work for you, however it does provide the plumbing to make developing your system a whole lot simpler. Using the service broker, it would even be possible to send messages from one service into another service on a different machine; might be useful to help keep different pieces of information up to date in a vastly distributed database set up when replication doesn&#8217;t quite suit the purpose.</li>
<li>Query Notification, as it suggests is a notification system which is used to notify clients or caches that they need to update certain data. Once again, the query notification doesn&#8217;t do the updating &#8211; it merely provides the event to tell you do perform your own action. The Query Notification engine utilises the service broker under the hood.</li>
<li>Data Dependent Routing isn&#8217;t a SQL Server feature but more of an architectural design pattern. Using Data Dependent Routing, the client (whatever it is), knows a little bit about the storage system and optimistically seeks out the data store which is likely to return the best performance.</li>
</ul>
<h2>.NET Programming Language Pragmatics</h2>
<p>Joel Pobar presentated on .NET programming language pragmatics and contrasted some of the recent developments in that space. At the start of the talk, he pointed out that there are generally three types of programming languages &#8211; static, dynamic and functional. The original version of the .NET Common Language Runtime was based around a static environment and has recently been enhanced to support functional programming and more recently dynamic.</p>
<p>The dynamic programming languages are handled through a new component, the Dynamic Language Runtime which sits on top of the existing CLR. The new Dynamic Language Runtime has allowed people to build IronPython and IronRuby, which are implementations of those particular languages sitting over the top of the .NET CLR.</p>
<p>Outside of the fact that it means you&#8217;ll be able to run a Python script in the native Python runtime or inside of the .NET DLR, which is just plain cool; the biggest picture here is that the .NET CLR is being enhanced and soon we&#8217;ll have a new super language (LISP advocates, back in your boxes!) which will support all of the current types of programming languages at once.</p>
<p>The presentation was fantastic and it is exciting to hear Joel present as he is so passionate about the field. In fact, I would go as far to say that his enthusiasm for his work is infectious; it is hard to walk away from one of his presentations and not have at least some of his excitement and enthusiasm rubbed off on you.</p>
<p>I&#8217;ve heard on the grape vine that Joel might be able to present at the one of the next Gold Coast .NET User Groups, can&#8217;t wait if he does!</p>
<p>Related posts:<ol>
<li><a href='http://www.lattimore.id.au/2007/08/09/tech-ed-2007-day-1-wrap-up/' rel='bookmark' title='Tech Ed 2007, Day 1 Wrap Up'>Tech Ed 2007, Day 1 Wrap Up</a></li>
<li><a href='http://www.lattimore.id.au/2007/08/10/tech-ed-2007-day-2-wrap-up/' rel='bookmark' title='Tech Ed 2007, Day 2 Wrap Up'>Tech Ed 2007, Day 2 Wrap Up</a></li>
<li><a href='http://www.lattimore.id.au/2006/06/03/iis-dropping-sessions/' rel='bookmark' title='IIS Dropping Sessions'>IIS Dropping Sessions</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.lattimore.id.au/2007/08/11/tech-ed-2007-day-3-wrap-up/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Signs</title>
		<link>http://www.lattimore.id.au/2007/05/15/signs/</link>
		<comments>http://www.lattimore.id.au/2007/05/15/signs/#comments</comments>
		<pubDate>Mon, 14 May 2007 14:00:13 +0000</pubDate>
		<dc:creator>Al</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.lattimore.id.au/2007/05/15/signs/</guid>
		<description><![CDATA[It&#8217;s a sign you need either: more sleep; or more coffee when you find code committed into a source code repository that you don&#8217;t remember writing and realise when you find it that it was really handy that you wrote &#8230; <a href="http://www.lattimore.id.au/2007/05/15/signs/">Continue reading <span class="meta-nav">&#8594;</span></a>
Related posts:<ol>
<li><a href='http://www.lattimore.id.au/2006/05/17/oracle-coalesce-function/' rel='bookmark' title='Oracle COALESCE Function'>Oracle COALESCE Function</a></li>
<li><a href='http://www.lattimore.id.au/2006/04/17/oracle-decode-function/' rel='bookmark' title='Oracle DECODE Function'>Oracle DECODE Function</a></li>
<li><a href='http://www.lattimore.id.au/2005/07/01/select-option-disabled-and-the-javascript-solution/' rel='bookmark' title='Select, Option, Disabled And The JavaScript Solution'>Select, Option, Disabled And The JavaScript Solution</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s a sign you need either:</p>
<ol>
<li>more sleep; or</li>
<li>more coffee</li>
</ol>
<p>when you <em>find</em> code committed into a source code repository that you don&#8217;t remember writing and realise when you find it that it was really handy that you wrote that code at some obscure hour of the morning a week ago.</p>
<p>Related posts:<ol>
<li><a href='http://www.lattimore.id.au/2006/05/17/oracle-coalesce-function/' rel='bookmark' title='Oracle COALESCE Function'>Oracle COALESCE Function</a></li>
<li><a href='http://www.lattimore.id.au/2006/04/17/oracle-decode-function/' rel='bookmark' title='Oracle DECODE Function'>Oracle DECODE Function</a></li>
<li><a href='http://www.lattimore.id.au/2005/07/01/select-option-disabled-and-the-javascript-solution/' rel='bookmark' title='Select, Option, Disabled And The JavaScript Solution'>Select, Option, Disabled And The JavaScript Solution</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.lattimore.id.au/2007/05/15/signs/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Learning How To Scale An ASP.NET Application</title>
		<link>http://www.lattimore.id.au/2007/05/12/learning-how-to-scale-an-aspnet-application/</link>
		<comments>http://www.lattimore.id.au/2007/05/12/learning-how-to-scale-an-aspnet-application/#comments</comments>
		<pubDate>Fri, 11 May 2007 13:24:44 +0000</pubDate>
		<dc:creator>Al</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Work]]></category>

		<guid isPermaLink="false">http://www.lattimore.id.au/2007/05/12/learning-how-to-scale-an-aspnet-application/</guid>
		<description><![CDATA[For the last nine months, the development team at Stella Hospitality Group have been working on integrating a new piece of software into the enterprise. Throughout that process, we&#8217;ve come up against various stumbling blocks and subsequently learned how to &#8230; <a href="http://www.lattimore.id.au/2007/05/12/learning-how-to-scale-an-aspnet-application/">Continue reading <span class="meta-nav">&#8594;</span></a>
Related posts:<ol>
<li><a href='http://www.lattimore.id.au/2006/07/17/oracle-ora-04030-application-errors/' rel='bookmark' title='Oracle ORA-04030 Application Errors'>Oracle ORA-04030 Application Errors</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>For the last nine months, the development team at <a href="http://www.stellaresorts.com.au/">Stella Hospitality Group</a> have been working on integrating a new piece of software into the enterprise. Throughout that process, we&#8217;ve come up against various stumbling blocks and subsequently learned how to climb over them.</p>
<p>One of the interesting parts of this project involved learning how to scale an ASP.NET web application. Unlike most other pieces of development we&#8217;ve previously worked on, we didn&#8217;t have access to hardware and services that were capable of delivering smoking performance (read: Oracle 10g clustered using RAC). As a by product of the constraints which were placed on us, scaling the new web application proved a little harder than it first looked.</p>
<p>Over the course of the next few weeks, I&#8217;ll be posting about various steps which we&#8217;ve taken to scale our ASP.NET application. Some of the points are hinged in the physical world, others operational and of course technical as well. Items which come to mind immediately include:</p>
<ul>
<li>load balancers</li>
<li>clustering physical servers</li>
<li>clustering web servers</li>
<li>web gardens</li>
<li>user interface process control</li>
<li>session handling</li>
<li>web services &amp; XML</li>
<li>spike testing</li>
</ul>
<p>Related posts:<ol>
<li><a href='http://www.lattimore.id.au/2006/07/17/oracle-ora-04030-application-errors/' rel='bookmark' title='Oracle ORA-04030 Application Errors'>Oracle ORA-04030 Application Errors</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.lattimore.id.au/2007/05/12/learning-how-to-scale-an-aspnet-application/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Oracle Dynamic SQL Using The DECODE Function</title>
		<link>http://www.lattimore.id.au/2007/04/03/oracle-dynamic-sql-using-the-decode-function/</link>
		<comments>http://www.lattimore.id.au/2007/04/03/oracle-dynamic-sql-using-the-decode-function/#comments</comments>
		<pubDate>Mon, 02 Apr 2007 13:48:43 +0000</pubDate>
		<dc:creator>Al</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.lattimore.id.au/2007/04/03/oracle-dynamic-sql-using-the-decode-function/</guid>
		<description><![CDATA[When developing most applications, you end up having to interact with a database. If you&#8217;re application is large enough and warrants the design and effort, it will no doubt be tiered as well. If your application is tiered, one of &#8230; <a href="http://www.lattimore.id.au/2007/04/03/oracle-dynamic-sql-using-the-decode-function/">Continue reading <span class="meta-nav">&#8594;</span></a>
Related posts:<ol>
<li><a href='http://www.lattimore.id.au/2006/04/17/oracle-decode-function/' rel='bookmark' title='Oracle DECODE Function'>Oracle DECODE Function</a></li>
<li><a href='http://www.lattimore.id.au/2006/05/17/oracle-coalesce-function/' rel='bookmark' title='Oracle COALESCE Function'>Oracle COALESCE Function</a></li>
<li><a href='http://www.lattimore.id.au/2007/01/04/postgresql-dynamic-sql-quote_ident-gotchas/' rel='bookmark' title='PostgreSQL Dynamic SQL &amp; Quote_ident Gotchas'>PostgreSQL Dynamic SQL &#038; Quote_ident Gotchas</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>When developing most applications, you end up having to interact with a database. If you&#8217;re application is large enough and warrants the design and effort, it will no doubt be tiered as well. If your application is tiered, one of your layers will probably include a database API. A database API is used to restrict access to the database, a funnel which all requests from your application must pass through. Implementing this additional layer of abstraction normally yields in higher performance, increased security and easier maintenance.</p>
<p>In most cases, you&#8217;re application code will require a fairly standard interface into your database to retrieve information. A simple way to achieve that consistent interface is using the <code>DECODE</code> function in your PL/SQL procedures and functions. There are always cases where you need to do something special, and in those cases it is probably a perfect scenario for this methods counter-part &#8211; the string building technique.</p>
<p>For a simple but practical example, consider the following table definition:</p>
<ol>
<li><code>CREATE TABLE MyTable (</code></li>
<li><code> PrimaryKeyID NUMBER NOT NULL,</code></li>
<li><code> ForeignKeyID NUMBER NOT NULL,</code></li>
<li><code> Name VARCHAR2 (255) NOT NULL</code></li>
<li><code>)</code></li>
</ol>
<p>As I have mentioned before, the Oracle <a href="/2006/04/17/oracle-decode-function/">DECODE</a> function provides similar functionality to an <code>IF-THEN-ELSE</code> code block. Lets examine an example which relates to <code>MyTable</code> above.</p>
<ol class="code">
<li><code>PROCEDURE Get</code></li>
<li><code> (pDetails                    OUT grcDetails,</code></li>
<li><code> pPrimaryKeyID            IN MyTable.PrimaryKeyID%TYPE DEFAULT NULL,</code></li>
<li><code> pForeignKeyID            IN MyTable.ForeignKeyID%TYPE  DEFAULT NULL,</code></li>
<li><code> pName                      IN MyTable.Name%TYPE DEFAULT NULL)</code></li>
<li><code> IS</code></li>
<li><code> BEGIN</code></li>
<li><code> OPEN pDetails FOR</code></li>
<li><code> SELECT *</code></li>
<li><code> FROM MyTable</code></li>
<li><code> WHERE PrimaryKeyID = DECODE(pPrimaryKeyID, NULL, PrimaryKeyID, 0, PrimaryKeyID, pPrimaryKeyID)</code></li>
<li><code> AND ForeignKeyID = DECODE(pForeignKeyID, NULL, ForeignKeyID, 0, ForeignKeyID, pForeignKeyID)</code></li>
<li><code> AND LOWER(Name) LIKE DECODE(pName, NULL, LOWER(Name), '%'||LOWER(pName)||'%');</code></li>
<li><code> END;</code></li>
</ol>
<p>Working top down, the second line declares <code>pDetails</code> (the parameter name) as being an <code>OUT</code> parameter. As the name suggests, an <code>OUT</code> parameter is a way for you to pass information <em>out</em> of your procedure. In some aspects it would be similar to returning a value out of a typical programming function. The difference to an <code>OUT</code> parameter is that you can have many <code>OUT</code> parameters in a single procedure, where as a typical programming function can only return a single value at a time.</p>
<p>The next thing you&#8217;ve probably noticed is this weird thing in there, <code>grcDetails</code>. Just as the <code>IN</code> parameters below it, <code>grcDetails</code> is the <em>type</em> of the parameter. It would be akin to defining a paramter in a traditional function as accepting an integer or string type. In this case, <code>grcDetails</code> is declared in the package header:</p>
<ol class="code">
<li><code>TYPE grcDetails IS REF CURSOR RETURN MyTable%ROWTYPE;</code></li>
</ol>
<p>The important thing to notice about <code>grcDetails</code> is that it is a <code>REF CURSOR</code> and its <em>type</em> is the <code>ROWTYPE</code> of <code>MyTable</code>. The benefit of defining it as a <code>ROWTYPE</code> is that if tomorrow the definition of the table changed in some way, you don&#8217;t have to worry about changing any code to match the new table definition &#8211; it simply continues to work. This is the same reason why the <code>INPUT</code> parameters above have their type defined against the field that they represent. Of course, if you are passing in or out a value which isn&#8217;t based on a field &#8211; you would simply define it as a standard PL/SQL type.</p>
<p>Next, you have probably noticed that each <code>IN</code> parameter has a <code>DEFAULT</code> value. As with most programming languages, providing a <code>DEFAULT</code> value allows the programmer to optionally supply that parameter. For our example, this is a pivotal point as it simplifies the use of this method; more on that later.</p>
<p>Moving on to the actual SQL statement, the flexibility of the <code>DECODE</code> function starts to show. Since the <code>DECODE</code> function acts like an <code>IF-THEN-ELSE</code> block, you&#8217;re actually seeing an inline <code>IF-THEN-ELSE IF-ELSE</code> block per field. Lets take a practical example of that statement and assume we passed in <code>pPrimaryKeyID</code> with a value of 1, while the other two input parameter&#8217;s are not passed in (thus taking their default value of <code>NULL</code>). The SQL statement would be parsed and executed as follows:</p>
<ol class="code">
<li><code>SELECT *</code></li>
<li><code>FROM MyTable</code></li>
<li><code>WHERE PrimaryKeyID = 1</code></li>
<li><code> AND ForeignKeyID = ForeignKeyID</code></li>
<li><code> AND LOWER(Name) LIKE LOWER(Name);</code></li>
</ol>
<p>Of course, the net effect of that SQL statement is that the first <code>WHERE</code> condition is used, while the second and third conditions are nullified as the left and right half of each expression are equivalent. So by passing in a <code>NULL</code> value for the <code>pForeignKeyID</code> and <code>pName</code> parameters, they are effectively removed from the SQL statement by evaluating to themselves. Of course, you could also pass in two, three or none of the parameters to the procedure as well. In which case you would get either a restricted set from the statement or all records in the table.</p>
<p>As mentioned above, the <code>DEFAULT</code> value of each <code>IN</code> parameter is critical to this methods success. By providing a default value, the programmer no longer <em>needs</em> to call the procedure with all parameters; all, some or none are also perfectly valid combinations. Since the input parameter&#8217;s default value is <code>NULL</code>, the following <code>DECODE</code> function call is all that is required to negate the parameter in the <code>WHERE</code> clause:</p>
<ol>
<li><code>PrimaryKeyID = DECODE(pPrimaryKeyID, NULL, PrimaryKeyID, pPrimaryKeyID)</code></li>
</ol>
<p>By now, you have probably noticed some extra parameters in the example <code>GET</code> procedure listed above. The additional values are used to exclude any other &#8216;not important&#8217; values from the statement. In the example procedure, <code>NULL</code> and the value <code>0</code> are considered unimportant; whilst all other values are considered useful.</p>
<p>If you&#8217;re wondering why you&#8217;d want to exclude other values, it might be to make another section of your application simpler. Some programming languages don&#8217;t support nullable primitive types. If you use such a language and you intend to pass in all parameters to your procedure in all circumstances (this is the &#8216;simpler&#8217; above); then all values will have a value of some sort. In the case of a primitive such as an integer, you might find that its default uninitialised value is zero. If that is the case and you don&#8217;t require the ability to filter on a zero value, then excluding it within the <code>DECODE</code> function makes things simpler.</p>
<p>Don&#8217;t think you&#8217;re limited to using this method on <code>SELECT</code> statements, it will work a treat on <code>DELETE</code> too. Consider the following <code>DEL</code> procedure:</p>
<ol class="code">
<li><code> PROCEDURE Del</code></li>
<li><code> (pRowCount            OUT NUMBER,</code></li>
<li><code> pRoomTypeID          IN RoomTypes.ROOMTYPEID%TYPE DEFAULT NULL,</code></li>
<li><code> pBuildingID          IN RoomTypes.BUILDINGID%TYPE DEFAULT NULL)</code></li>
<li><code> IS</code></li>
<li><code> BEGIN</code></li>
<li><code> IF (pRoomTypeID IS NOT NULL OR pBuildingID IS NOT NULL) THEN</code></li>
<li><code> DELETE</code></li>
<li><code> FROM RoomTypes</code></li>
<li><code> WHERE RoomTypeID = DECODE(pRoomTypeID, NULL, RoomTypeID, 0, RoomTypeID, pRoomTypeID)</code></li>
<li><code> AND BuildingID = DECODE(pBuildingID, NULL, BuildingID, 0, BuildingID, pBuildingID);</code></li>
<li><code> ELSE</code></li>
<li><code> RAISE_APPLICATION_ERROR(-20001, 'At least one parameter must be supplied');</code></li>
<li><code> END IF;</code></li>
<li><code> pRowCount := SQL%ROWCOUNT;</code></li>
<li><code> END;</code></li>
</ol>
<p>There is a caveat to using this method for building dynamic SQL within Oracle, it cannot handle columns which are nullable. If you consider the use of the <code>DEFAULT</code> value on all of the input parameters, it will become clear. Within Orcale PL/SQL, it is not possible to use an equality (<code>=</code>) operator to compare a <code>NULL</code> value. As a simple example, take the two simple SQL statements:</p>
<ol class="code">
<li><code>SELECT * FROM DUAL</code></li>
<li><code>SELECT * FROM DUAL WHERE NULL = NULL</code></li>
</ol>
<p>The first SQL statement above will return the expected row from the <code>DUAL</code> table, while the second statement will return no results as you cannot compare the <code>NULL</code> value in that manner. If a comparison against a <code>NULL</code> is required, it must be handled using the <code>IS NULL</code> clause.</p>
<p>Other than not being able to use this method against columns which are nullable, its a really convenient way to write dynamic SQL  in Oracle. Next time you need a little flexibility and you don&#8217;t want to go down the string building path, try using the Oracle <code>DECODE</code> function to produce your <em>dynamic</em> SQL.</p>
<p>Related posts:<ol>
<li><a href='http://www.lattimore.id.au/2006/04/17/oracle-decode-function/' rel='bookmark' title='Oracle DECODE Function'>Oracle DECODE Function</a></li>
<li><a href='http://www.lattimore.id.au/2006/05/17/oracle-coalesce-function/' rel='bookmark' title='Oracle COALESCE Function'>Oracle COALESCE Function</a></li>
<li><a href='http://www.lattimore.id.au/2007/01/04/postgresql-dynamic-sql-quote_ident-gotchas/' rel='bookmark' title='PostgreSQL Dynamic SQL &amp; Quote_ident Gotchas'>PostgreSQL Dynamic SQL &#038; Quote_ident Gotchas</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.lattimore.id.au/2007/04/03/oracle-dynamic-sql-using-the-decode-function/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Storing Time Information In Oracle</title>
		<link>http://www.lattimore.id.au/2007/03/29/storing-time-information-in-oracle/</link>
		<comments>http://www.lattimore.id.au/2007/03/29/storing-time-information-in-oracle/#comments</comments>
		<pubDate>Wed, 28 Mar 2007 13:45:42 +0000</pubDate>
		<dc:creator>Al</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.lattimore.id.au/2007/03/29/storing-time-information-in-oracle/</guid>
		<description><![CDATA[I recently had a requirement to store a time within Oracle, not a timestamp or a date &#8211; just the time. As it turns out, storing just the time information in Oracle isn&#8217;t something you can do without a little &#8230; <a href="http://www.lattimore.id.au/2007/03/29/storing-time-information-in-oracle/">Continue reading <span class="meta-nav">&#8594;</span></a>
Related posts:<ol>
<li><a href='http://www.lattimore.id.au/2005/10/30/oracle-express-xe/' rel='bookmark' title='Oracle Express (XE)'>Oracle Express (XE)</a></li>
<li><a href='http://www.lattimore.id.au/2007/03/09/ora-06552-plsql-compilation-unit-analysis-terminated/' rel='bookmark' title='ORA-06552: PL/SQL: Compilation Unit Analysis Terminated'>ORA-06552: PL/SQL: Compilation Unit Analysis Terminated</a></li>
<li><a href='http://www.lattimore.id.au/2006/04/17/oracle-decode-function/' rel='bookmark' title='Oracle DECODE Function'>Oracle DECODE Function</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>I recently had a requirement to store a time within Oracle, not a timestamp or a date &#8211; just the <em>time</em>. As it turns out, storing just the time information in Oracle isn&#8217;t something you can do without a little bit of work.</p>
<p>Oracle provides you a few different data types for handling date and time:</p>
<ul>
<li><code>DATE</code></li>
<li><code>TIMESTAMP</code></li>
<li><code>INTERVAL</code></li>
</ul>
<p>Unfortunately, none of the supplied data types are an exact match for a time such as <code>10:30 AM</code>. The good news is that both a <code>DATE</code> and a <code>TIMESTAMP</code> data types contain time information &#8211; so it is possible to do what you want with a little slight of hand.</p>
<p>The slight of hand I mentioned has to do with the default behaviour of Oracle when inserting only a time component of a <code>DATE</code> or a <code>TIMESTAMP</code> data type. For the rest of this discussion, lets assume you have a simple table set up as follows:</p>
<ol class="code">
<li><code>CREATE TABLE Times (</code></li>
<li><code>id INT NOT NULL,</code></li>
<li><code>thedate DATE NOT NULL,</code></li>
<li><code>thetimestamp TIMESTAMP NOT NULL</code></li>
<li><code>);</code></li>
</ol>
<p>With the following three rows of data:</p>
<ol class="code">
<li><code>INSERT INTO Times (id, thedate, thetimestamp) VALUES (1, SYSDATE, SYSDATE);</code></li>
<li><code>INSERT INTO Times (id, thedate, thetimestamp) VALUES (2, TO_DATE('10:30 AM', 'HH:MI AM'), TO_DATE('10:30 AM', 'HH:MI AM'));</code></li>
<li><code>INSERT INTO Times (id, thedate, thetimestamp) VALUES (3, TO_DATE('0001-01-01 10:30 AM', 'YYYY-MM-DD HH:MI AM'), TO_DATE('0001-01-01 10:30 AM', 'YYYY-MM-DD HH:MI AM'));</code></li>
</ol>
<p>When selecting that grid of information out, you&#8217;ll receive:</p>
<table border="0">
<thead>
<tr>
<th>id</th>
<th>thedate</th>
<th>thetimestamp</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>28/03/2007 11:32:25 PM</td>
<td>28/03/2007 11:32:25.000000 PM</td>
</tr>
<tr>
<td>2</td>
<td>1/03/2007 10:30:00 AM</td>
<td>1/03/2007 10:30:00.000000 AM</td>
</tr>
<tr>
<td>3</td>
<td>1/01/0001 10:30:00 AM</td>
<td>1/01/0001 10:30:00.000000 AM</td>
</tr>
</tbody>
</table>
<p>There are more than one solution to this problem, as if you&#8217;re using any of the standard date/time data types &#8211; you can always store the time component. What may or may not be of interest to everyone is what Oracle does with the date component of a <code>DATE</code> or <code>TIMESTAMP</code> data type when you don&#8217;t provide the standard date components of a date/time data type.</p>
<p>If you take notice of row #1 returned, you&#8217;ll see that because the inserted values for <code>thedate</code> and <code>thetimetamp</code> was <code>SYSDATE</code>, it has stored the date component as you&#8217;d expect.</p>
<p>Compare that against row #2 and you&#8217;ll notice that the insert statement simply provided the time component and made no mention of the date. When Oracle returned that time value out, it has automatically substituted the first day of the current month into the date component.</p>
<p>When inserting row #3, an arbitrary date of 1 Jan 0001 was supplied. When reading that information back out of Oracle, it handles the date component in a similar fashion to how it was handled for row #1 using the <code>SYSDATE</code>; ie you get the expected result back.</p>
<p>Since you can return any number of rows from Oracle doing standard date/time arithmetic, it really comes down to preference. What option above has the most semantic meaning to a user or the data in the database when you&#8217;re required to store a <em>time</em> and not a timestamp?</p>
<p>For consistency reasons, my personal preference leans towards applying technique #3 and here are a couple of simple reasons why:</p>
<ul>
<li>When dealing with a <code>DATE</code> or <code>TIMESTAMP</code> value stored like that in PL/SQL, you&#8217;ll always know what value is stored in the date component of the value.</li>
<li>If you&#8217;re handling this information in an application language such as Microsoft .NET, Java or Python &#8211; you will always know what value to expect in the date component. Using technique #1, the date component will change for every row. Using #2, the date component of the value will change per row depending on what month the row was inserted</li>
</ul>
<p>Does anyone else have a hot tip for storing a straight time value in Oracle?</p>
<p>Related posts:<ol>
<li><a href='http://www.lattimore.id.au/2005/10/30/oracle-express-xe/' rel='bookmark' title='Oracle Express (XE)'>Oracle Express (XE)</a></li>
<li><a href='http://www.lattimore.id.au/2007/03/09/ora-06552-plsql-compilation-unit-analysis-terminated/' rel='bookmark' title='ORA-06552: PL/SQL: Compilation Unit Analysis Terminated'>ORA-06552: PL/SQL: Compilation Unit Analysis Terminated</a></li>
<li><a href='http://www.lattimore.id.au/2006/04/17/oracle-decode-function/' rel='bookmark' title='Oracle DECODE Function'>Oracle DECODE Function</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.lattimore.id.au/2007/03/29/storing-time-information-in-oracle/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>ORA-06552: PL/SQL: Compilation Unit Analysis Terminated</title>
		<link>http://www.lattimore.id.au/2007/03/09/ora-06552-plsql-compilation-unit-analysis-terminated/</link>
		<comments>http://www.lattimore.id.au/2007/03/09/ora-06552-plsql-compilation-unit-analysis-terminated/#comments</comments>
		<pubDate>Fri, 09 Mar 2007 00:27:47 +0000</pubDate>
		<dc:creator>Al</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.lattimore.id.au/2007/03/09/ora-06552-plsql-compilation-unit-analysis-terminated/</guid>
		<description><![CDATA[Today I received a strange error from Oracle, for what appeared to be no good reason: ORA-06552: PL/SQL: Compilation unit analysis terminated ORA-06553: PLS-320: The declaration of the type of this expression is incomplete or malformed I received the error &#8230; <a href="http://www.lattimore.id.au/2007/03/09/ora-06552-plsql-compilation-unit-analysis-terminated/">Continue reading <span class="meta-nav">&#8594;</span></a>
Related posts:<ol>
<li><a href='http://www.lattimore.id.au/2005/02/24/asp-error-0x80004005/' rel='bookmark' title='ASP Error &#8217;0&#215;80004005&#8242;'>ASP Error &#8217;0&#215;80004005&#8242;</a></li>
<li><a href='http://www.lattimore.id.au/2007/01/04/postgresql-dynamic-sql-quote_ident-gotchas/' rel='bookmark' title='PostgreSQL Dynamic SQL &amp; Quote_ident Gotchas'>PostgreSQL Dynamic SQL &#038; Quote_ident Gotchas</a></li>
<li><a href='http://www.lattimore.id.au/2006/05/30/oracle-derived-columns-in-select-statements/' rel='bookmark' title='Oracle Derived Columns In SELECT Statements'>Oracle Derived Columns In SELECT Statements</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>Today I received a strange error from Oracle, for what appeared to be no good reason:</p>
<ol class="code">
<li><code>ORA-06552: PL/SQL: Compilation unit analysis terminated</code></li>
<li><code>ORA-06553: PLS-320: The declaration of the type of this expression is incomplete or malformed</code></li>
</ol>
<p>I received the error when attempting to create a trigger on a newly created table. I could create triggers on other tables without any errors, however on the new table &#8211; it would error every time.</p>
<p>The table definition included a column named <code>timestamp</code> with the data type <code>timestamp</code>. Oracle was happy enough for me to create the table, however it refused to let me create a trigger on the table with a column name over lapping a reserved word.</p>
<p>The solution was simple, renamed the column in question to use a non-reserved word and everything continued as normal. I must say though, I think it is strange that it would let me create the table using the reserved word in the first place if it was going to complain about me using other standard Oracle features which would error as a by product of the reserved word.</p>
<p>Related posts:<ol>
<li><a href='http://www.lattimore.id.au/2005/02/24/asp-error-0x80004005/' rel='bookmark' title='ASP Error &#8217;0&#215;80004005&#8242;'>ASP Error &#8217;0&#215;80004005&#8242;</a></li>
<li><a href='http://www.lattimore.id.au/2007/01/04/postgresql-dynamic-sql-quote_ident-gotchas/' rel='bookmark' title='PostgreSQL Dynamic SQL &amp; Quote_ident Gotchas'>PostgreSQL Dynamic SQL &#038; Quote_ident Gotchas</a></li>
<li><a href='http://www.lattimore.id.au/2006/05/30/oracle-derived-columns-in-select-statements/' rel='bookmark' title='Oracle Derived Columns In SELECT Statements'>Oracle Derived Columns In SELECT Statements</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.lattimore.id.au/2007/03/09/ora-06552-plsql-compilation-unit-analysis-terminated/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>ORA-06502: PL/SQL: numeric or value error</title>
		<link>http://www.lattimore.id.au/2007/02/14/ora-06502-plsql-numeric-or-value-error/</link>
		<comments>http://www.lattimore.id.au/2007/02/14/ora-06502-plsql-numeric-or-value-error/#comments</comments>
		<pubDate>Tue, 13 Feb 2007 14:04:09 +0000</pubDate>
		<dc:creator>Al</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.lattimore.id.au/2007/02/14/ora-06502-plsql-numeric-or-value-error/</guid>
		<description><![CDATA[Today I came up against a very frustrating problem when writing some Oracle PL/SQL stored procedures and functions: ORA-06502: PL/SQL: numeric or value error When I first wrote the stored function in question, I was using VARCHAR2 types for storage &#8230; <a href="http://www.lattimore.id.au/2007/02/14/ora-06502-plsql-numeric-or-value-error/">Continue reading <span class="meta-nav">&#8594;</span></a>
Related posts:<ol>
<li><a href='http://www.lattimore.id.au/2005/03/01/more-asp-error-80020009/' rel='bookmark' title='More ASP Error &#8217;80020009&#8242;'>More ASP Error &#8217;80020009&#8242;</a></li>
<li><a href='http://www.lattimore.id.au/2006/03/22/oracle-data-provider-odpnet-data-provider-internal-error-3000-3001/' rel='bookmark' title='Oracle Data Provider (ODP.net): Data Provider Internal Error (-3000/-3001)'>Oracle Data Provider (ODP.net): Data Provider Internal Error (-3000/-3001)</a></li>
<li><a href='http://www.lattimore.id.au/2007/03/09/ora-06552-plsql-compilation-unit-analysis-terminated/' rel='bookmark' title='ORA-06552: PL/SQL: Compilation Unit Analysis Terminated'>ORA-06552: PL/SQL: Compilation Unit Analysis Terminated</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>Today I came up against a very frustrating problem when writing some Oracle PL/SQL stored procedures and functions:</p>
<ol class="code">
<li><code>ORA-06502: PL/SQL: numeric or value error</code></li>
</ol>
<p>When I first wrote the stored function in question, I was using <code>VARCHAR2</code> types for storage since it was the data type returned by an Oracle provided package. The function signature looked something like the following example:</p>
<ol class="code">
<li><code>FUNCTION MyFunction</code></li>
<li><code>(pData IN VARCHAR2)</code></li>
<li><code>RETURN VARCHAR2;</code></li>
</ol>
<p>The stored procedures and functions in question were being used with a lot of character information. Whilst running small sets of test data through the functions, everything was acting as expected. Unfortunately, as the test data sets increased in size I began to receive the ORA-06502 error.</p>
<p>As you may or may not be aware, within PL/SQL a <code>VARCHAR2</code> type can store a maximum of 32767 bytes of information. When the ORA-06502 exceptions where taking place, this limit was being exceeded.</p>
<p>The thing that was <strong>so</strong> frustrating about the error, was that it wasn&#8217;t helping me identify the problem. In this particular instance, I had refactored a significant amount of PL/SQL and during that process changed some variables from <code>VARCHAR2</code> into <code>CLOB</code> data types.</p>
<p>Oracle will allow you to pass a <code>CLOB</code> variable into a function that accepts a <code>VARCHAR2</code>, so long as the length of the <code>CLOB</code> is less than the maximum byte limit of the <code>VARCHAR2</code>. Since that wasn&#8217;t throwing a type conversion error in <em>normal</em> circumstances, it wasn&#8217;t something that I went looking into immediately as a possible problem when the Oracle ORA-06502 errors were thrown.</p>
<p>The solution to this particular problem is what you would expect, change the data types of all associated functions and procedures to use the <code>CLOB</code> data type:</p>
<ol class="code">
<li><code>FUNCTION MyFunction</code></li>
<li><code>(pData IN CLOB)</code></li>
<li><code>RETURN CLOB;</code></li>
</ol>
<p>After looking into the error in more depth, it can be thrown for virtually any generic constraint violation. The following simple examples would produce this error code:</p>
<ul>
<li>assign a <code>NULL</code> value to a variable defined as <code>NOT NULL</code></li>
<li>assign a value greater than 99 to a variable defined as <code>NUMBER(2)</code></li>
<li>assign a <code>CLOB</code> with a length greater than 32767 bytes to a <code>VARCHAR2</code> variable</li>
</ul>
<p>I think it would have been a little more useful to a developer for Oracle to throw some sort of a type conversion error in this instance.</p>
<p>Related posts:<ol>
<li><a href='http://www.lattimore.id.au/2005/03/01/more-asp-error-80020009/' rel='bookmark' title='More ASP Error &#8217;80020009&#8242;'>More ASP Error &#8217;80020009&#8242;</a></li>
<li><a href='http://www.lattimore.id.au/2006/03/22/oracle-data-provider-odpnet-data-provider-internal-error-3000-3001/' rel='bookmark' title='Oracle Data Provider (ODP.net): Data Provider Internal Error (-3000/-3001)'>Oracle Data Provider (ODP.net): Data Provider Internal Error (-3000/-3001)</a></li>
<li><a href='http://www.lattimore.id.au/2007/03/09/ora-06552-plsql-compilation-unit-analysis-terminated/' rel='bookmark' title='ORA-06552: PL/SQL: Compilation Unit Analysis Terminated'>ORA-06552: PL/SQL: Compilation Unit Analysis Terminated</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.lattimore.id.au/2007/02/14/ora-06502-plsql-numeric-or-value-error/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PostgreSQL Dynamic SQL &amp; Quote_ident Gotchas</title>
		<link>http://www.lattimore.id.au/2007/01/04/postgresql-dynamic-sql-quote_ident-gotchas/</link>
		<comments>http://www.lattimore.id.au/2007/01/04/postgresql-dynamic-sql-quote_ident-gotchas/#comments</comments>
		<pubDate>Wed, 03 Jan 2007 14:10:22 +0000</pubDate>
		<dc:creator>Al</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.lattimore.id.au/2007/01/04/postgresql-dynamic-sql-quote_ident-gotchas/</guid>
		<description><![CDATA[PostgreSQL provides two useful functions to aid in the safe development of dynamic SQL: quote_ident The quote_ident function accepts and returns a text type. Whatever text you pass into quote_ident will be suitably escaped such that you could safely use &#8230; <a href="http://www.lattimore.id.au/2007/01/04/postgresql-dynamic-sql-quote_ident-gotchas/">Continue reading <span class="meta-nav">&#8594;</span></a>
Related posts:<ol>
<li><a href='http://www.lattimore.id.au/2007/04/03/oracle-dynamic-sql-using-the-decode-function/' rel='bookmark' title='Oracle Dynamic SQL Using The DECODE Function'>Oracle Dynamic SQL Using The DECODE Function</a></li>
<li><a href='http://www.lattimore.id.au/2006/05/30/oracle-derived-columns-in-select-statements/' rel='bookmark' title='Oracle Derived Columns In SELECT Statements'>Oracle Derived Columns In SELECT Statements</a></li>
<li><a href='http://www.lattimore.id.au/2007/03/09/ora-06552-plsql-compilation-unit-analysis-terminated/' rel='bookmark' title='ORA-06552: PL/SQL: Compilation Unit Analysis Terminated'>ORA-06552: PL/SQL: Compilation Unit Analysis Terminated</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>PostgreSQL provides two useful functions to aid in the safe development of dynamic SQL:</p>
<dl>
<dt>quote_ident</dt>
<dd>The <code>quote_ident</code> function accepts and returns a <code>text</code> type. Whatever text you pass into <code>quote_ident</code> will be suitably escaped such that you could safely use it as an identifier within a dynamic SQL statement.</p>
<p>According to the documentation, you should always pass table and column identifiers into the <code>quote_ident</code> function for safety. Calling <code>quote_ident('mytable')</code> will return <code>mytable</code>, however calling <code>quote_ident('MyTable')</code> would return <code>"MyTable"</code>.</p>
</dd>
<dt>quote_literal</dt>
<dd>The <code>quote_literal</code> function accepts and returns a <code>text</code> type. Whatever text you pass into the <code>quote_literal</code> function will be escaped so that you can safely use them in dynamic SQL.</p>
<p>You should always pass values or literals into the <code>quote_literal</code> function. By doing so, all special characters such as quotes will be safely dealt with. Calling <code>quote_literal('mycolumn')</code> would return <code>'mycolumn'</code> whilst <code>quote_literal('my\'column')</code> would return <code>'my''column'</code>.</p>
</dd>
</dl>
<p>Both of these functions work a treat, however there is a caveat with the <code>quote_ident</code> function which isn&#8217;t well documented. When creating objects in PostgreSQL, they object names are automatically lowercased unless you create the object using double quotes. As a simple example:</p>
<ol class="code">
<li><code>CREATE TABLE MyTable (id integer, name varchar);</code> would result in an object <code>mytable</code> being created.</li>
<li><code>CREATE TABLE "MyTable" (id integer, name varchar);</code> would result in an object <code>MyTable</code> being created; note the casing.</li>
</ol>
<p>Now lets assume you wanted to create some dynamic SQL to fetch information out of the first example table above. If you issued <code>quote_ident('mytable')</code>, your dynamic SQL statement will execute because the value returned from <code>quote_ident</code> is lowercase which matches the table name. If you called <code>quote_ident('MyTable')</code>, your dynamic SQL statement will report an error stating that it cannot find the table or relation.</p>
<p>Creating dynamic SQL in PostgreSQL to fetch data out of the second example above, you would run into the reverse scenario. Issuing <code>quote_ident('mytable')</code> would produce an error, while <code>quote_ident('MyTable')</code> would execute without error.</p>
<p>If you create your database objects without using double quotes, then it&#8217;s important to remember to <strong>not</strong> pass capitalised parameters into <code>quote_ident</code>. The opposite is of course true as well, if you create your objects using double quotes then you <strong>must</strong> remember to pass in the same casing to <code>quote_ident</code>. If <code>quote_ident</code> applies double quotes (be it from capitised letters, spaces or special characters), the SQL engine within PostgreSQL will assume that an object exists with the explicit name matching the returned value of the <code>quote_ident</code> function.</p>
<p>Related posts:<ol>
<li><a href='http://www.lattimore.id.au/2007/04/03/oracle-dynamic-sql-using-the-decode-function/' rel='bookmark' title='Oracle Dynamic SQL Using The DECODE Function'>Oracle Dynamic SQL Using The DECODE Function</a></li>
<li><a href='http://www.lattimore.id.au/2006/05/30/oracle-derived-columns-in-select-statements/' rel='bookmark' title='Oracle Derived Columns In SELECT Statements'>Oracle Derived Columns In SELECT Statements</a></li>
<li><a href='http://www.lattimore.id.au/2007/03/09/ora-06552-plsql-compilation-unit-analysis-terminated/' rel='bookmark' title='ORA-06552: PL/SQL: Compilation Unit Analysis Terminated'>ORA-06552: PL/SQL: Compilation Unit Analysis Terminated</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.lattimore.id.au/2007/01/04/postgresql-dynamic-sql-quote_ident-gotchas/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WordPress Plugin: Kottke Style Archives</title>
		<link>http://www.lattimore.id.au/2006/11/20/wordpress-plugin-kottke-style-archives/</link>
		<comments>http://www.lattimore.id.au/2006/11/20/wordpress-plugin-kottke-style-archives/#comments</comments>
		<pubDate>Mon, 20 Nov 2006 12:56:27 +0000</pubDate>
		<dc:creator>Al</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.lattimore.id.au/2006/11/20/wordpress-plugin-kottke-style-archives/</guid>
		<description><![CDATA[Are you sick of seeing WordPress archives that stretch the length of your arm? If you are, then you might have just found the next best thing to sliced bread! The Kottke Style Archives plugin is a WordPress archives plugin &#8230; <a href="http://www.lattimore.id.au/2006/11/20/wordpress-plugin-kottke-style-archives/">Continue reading <span class="meta-nav">&#8594;</span></a>
Related posts:<ol>
<li><a href='http://www.lattimore.id.au/2006/10/10/wordpress-plugin-subtraction-style-archives/' rel='bookmark' title='WordPress Plugin: Subtraction Style Archives'>WordPress Plugin: Subtraction Style Archives</a></li>
<li><a href='http://www.lattimore.id.au/2006/12/05/kottke-style-archives-featured-in-wordpress-community-podcast/' rel='bookmark' title='Kottke Style Archives Featured In WordPress Community Podcast'>Kottke Style Archives Featured In WordPress Community Podcast</a></li>
<li><a href='http://www.lattimore.id.au/2006/04/27/wordpress-plugin-hicksdesign-style-archives/' rel='bookmark' title='WordPress Plugin: Hicksdesign Style Archives'>WordPress Plugin: Hicksdesign Style Archives</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><img class="alignright" src="/images/kottke-style-archives-thumb.jpg" alt="Kottke Style Archives, a WordPress archives plugin which emulates http://www.kottke.org/everfresh" width="300" height="90" />Are you sick of seeing WordPress archives that stretch the length of your arm? If you are, then you might have just found the next <a href="/projects/wordpress/plugins/kottke-style-archives/">best thing</a> to sliced bread! The Kottke Style Archives plugin is a WordPress archives plugin which will display your yearly <a href="http://www.kottke.org/everfresh">archives</a> in a similar format to <a href="http://www.kottke.org/">Jason Kottke</a>.</p>
<p>If you&#8217;re wondering why you might want your archive page looking like that, there are a couple of simple explanations:</p>
<ul>
<li>You don&#8217;t like having to scroll</li>
<li>You need or value your screen real estate</li>
<li>You want your site to be more accessible on mobile devices, see point #2</li>
<li>You want a change, after all &#8211; everyone has the same ol same ol archives page</li>
</ul>
<p>You can find out all about the Kottke Style Archives plugin at its <a href="/projects/wordpress/plugins/kottke-style-archives/">permanent home</a>. If you have any comments, problems or suggestions &#8211; feel free to drop them into this thread.</p>
<p>Related posts:<ol>
<li><a href='http://www.lattimore.id.au/2006/10/10/wordpress-plugin-subtraction-style-archives/' rel='bookmark' title='WordPress Plugin: Subtraction Style Archives'>WordPress Plugin: Subtraction Style Archives</a></li>
<li><a href='http://www.lattimore.id.au/2006/12/05/kottke-style-archives-featured-in-wordpress-community-podcast/' rel='bookmark' title='Kottke Style Archives Featured In WordPress Community Podcast'>Kottke Style Archives Featured In WordPress Community Podcast</a></li>
<li><a href='http://www.lattimore.id.au/2006/04/27/wordpress-plugin-hicksdesign-style-archives/' rel='bookmark' title='WordPress Plugin: Hicksdesign Style Archives'>WordPress Plugin: Hicksdesign Style Archives</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.lattimore.id.au/2006/11/20/wordpress-plugin-kottke-style-archives/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
	</channel>
</rss>

