<?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/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Systems Engineering and RDBMS &#187; DB2 LUW</title>
	<atom:link href="http://decipherinfosys.wordpress.com/category/db2-luw/feed/" rel="self" type="application/rss+xml" />
	<link>http://decipherinfosys.wordpress.com</link>
	<description></description>
	<lastBuildDate>Mon, 14 Dec 2009 23:42:14 +0000</lastBuildDate>
	<generator>http://wordpress.com/</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<cloud domain='decipherinfosys.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://www.gravatar.com/blavatar/a1338244b8e44d57d83b1634936133f5?s=96&#038;d=http://s.wordpress.com/i/buttonw-com.png</url>
		<title>Systems Engineering and RDBMS &#187; DB2 LUW</title>
		<link>http://decipherinfosys.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://decipherinfosys.wordpress.com/osd.xml" title="Systems Engineering and RDBMS" />
		<item>
		<title>Do not use &#8220;Select *&#8221;</title>
		<link>http://decipherinfosys.wordpress.com/2009/06/12/do-not-use-select/</link>
		<comments>http://decipherinfosys.wordpress.com/2009/06/12/do-not-use-select/#comments</comments>
		<pubDate>Fri, 12 Jun 2009 22:56:43 +0000</pubDate>
		<dc:creator>decipherinfosys</dc:creator>
				<category><![CDATA[DB2 LUW]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://decipherinfosys.wordpress.com/?p=2278</guid>
		<description><![CDATA[How many times have you seen code where a &#8220;select *&#8221; is being used?  Chances are that if you have been in the industry for some time, you must have seen code that has a &#8220;select *&#8221; in it (either application code or DB code).  It is not a good choice for a variety of [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=decipherinfosys.wordpress.com&blog=691282&post=2278&subd=decipherinfosys&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>How many times have you seen code where a &#8220;select *&#8221; is being used?  Chances are that if you have been in the industry for some time, you must have seen code that has a &#8220;select *&#8221; in it (either application code or DB code).  It is not a good choice for a variety of reasons -</p>
<p><strong>Reason #1</strong>: Performance:</p>
<p>Consider these 2 queries:</p>
<p>Query 1: select * from tableA where colx = 5</p>
<p>vs say using</p>
<p>Query 2: Select Col1, Col2 from tableA where colx = 5</p>
<p>If there was a covered index on col5, col1 and col2, then in the case of the second query, it can just retrieve all the data from the index itself while the select * query will need to go to the data pages as well.  Since the intention is only to return Col1 and Col2, specifically mention which columns you need.</p>
<p>In addition to this performance issue, the un-necessary data transfer is another performance issue.  Just get the data that you need&#8230;nothing more, nothing less.</p>
<p><strong>Reason #2</strong>: Plain simple code maintenance issue:</p>
<p>Say you have inherited a stored procedure which defines a table variable or a temp table (SQL Server lingo) and then does an &#8220;insert into #temp select * from&#8230;&#8221;.  If you add a new column that changes that then makes that select * to return an extra column, then this insert statement will fail.  In this case also, be explicit &#8211; mention which columns you are going to be inserting and where those columns are coming from.</p>
<p><strong>Reason # 3</strong>: When using it in an EXISTS/NOT EXISTS condition:</p>
<p>Read Conor Cunningham&#8217;s post here.  You will see that when using an EXISTS/NOT EXISTS  condition, there is an advantage to use a &#8220;select 1&#8243; vs using a &#8220;select *&#8221;.  The reasons are well explained in Connor&#8217;s post.</p>
<p><strong>Reason # 4</strong>: Column Dependency in Oracle 11g:</p>
<p>In Oracle 11g, the dependency mechanism has been extended down to the column level&#8230;so, what does that mean in relation to this post?  This means that if you are using explicit column names in your code, then the chances of the code getting invalidated and recompiled is less.</p>
<p>So, run through your code as a sanity check and see where all you have a &#8220;select *&#8221; in the code and then work on fixing it.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/decipherinfosys.wordpress.com/2278/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/decipherinfosys.wordpress.com/2278/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/decipherinfosys.wordpress.com/2278/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/decipherinfosys.wordpress.com/2278/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/decipherinfosys.wordpress.com/2278/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/decipherinfosys.wordpress.com/2278/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/decipherinfosys.wordpress.com/2278/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/decipherinfosys.wordpress.com/2278/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/decipherinfosys.wordpress.com/2278/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/decipherinfosys.wordpress.com/2278/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=decipherinfosys.wordpress.com&blog=691282&post=2278&subd=decipherinfosys&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://decipherinfosys.wordpress.com/2009/06/12/do-not-use-select/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0409e90c82255ecb867b436a97e4f779?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">decipherinfosys</media:title>
		</media:content>
	</item>
		<item>
		<title>Supporting a higher version of the RDBMS</title>
		<link>http://decipherinfosys.wordpress.com/2009/05/18/supporting-a-higher-version-of-the-rdbms/</link>
		<comments>http://decipherinfosys.wordpress.com/2009/05/18/supporting-a-higher-version-of-the-rdbms/#comments</comments>
		<pubDate>Mon, 18 May 2009 16:56:16 +0000</pubDate>
		<dc:creator>decipherinfosys</dc:creator>
				<category><![CDATA[DB2 LUW]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://decipherinfosys.wordpress.com/?p=2215</guid>
		<description><![CDATA[We have seen this happen too many times &#8211; a vendor would state in their presentation or marketing material that their product &#8220;supports&#8221; a newer version of the RDBMS.  A lot of times we have seen that the vendor just makes sure that their product does not break when running on a newer version of [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=decipherinfosys.wordpress.com&blog=691282&post=2215&subd=decipherinfosys&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>We have seen this happen too many times &#8211; a vendor would state in their presentation or marketing material that their product &#8220;supports&#8221; a newer version of the RDBMS.  A lot of times we have seen that the vendor just makes sure that their product does not break when running on a newer version of the RDBMS.  They do not take advantage of any of the new features of that RDBMS but since their product&#8217;s regression test went through fine after making connection changes and any other trivial changes that they needed to make, it makes it&#8217;s way into the marketing material.</p>
<p>That is mis-representation of the truth.  One should be clear in their message whether they really support a newer version of the RDBMS or have they just made sure that their product will run on it but will not take advantage of any of the new features till they come up with a subsequent release.  One of our clients bought a product from a vendor based on that claim only to find out that all the DB code was still using features from 2 releases ago &#8211; because of backward compatibility, it was still working but that defeats the purpose.  A proper due diligence should be done if you want to ensure that you get what you want else you might still end up buying and then implementing &amp; supporting a product built on legacy codebase.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/decipherinfosys.wordpress.com/2215/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/decipherinfosys.wordpress.com/2215/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/decipherinfosys.wordpress.com/2215/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/decipherinfosys.wordpress.com/2215/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/decipherinfosys.wordpress.com/2215/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/decipherinfosys.wordpress.com/2215/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/decipherinfosys.wordpress.com/2215/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/decipherinfosys.wordpress.com/2215/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/decipherinfosys.wordpress.com/2215/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/decipherinfosys.wordpress.com/2215/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=decipherinfosys.wordpress.com&blog=691282&post=2215&subd=decipherinfosys&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://decipherinfosys.wordpress.com/2009/05/18/supporting-a-higher-version-of-the-rdbms/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0409e90c82255ecb867b436a97e4f779?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">decipherinfosys</media:title>
		</media:content>
	</item>
		<item>
		<title>Too many sub-selects</title>
		<link>http://decipherinfosys.wordpress.com/2009/04/28/too-many-sub-selects/</link>
		<comments>http://decipherinfosys.wordpress.com/2009/04/28/too-many-sub-selects/#comments</comments>
		<pubDate>Tue, 28 Apr 2009 21:19:28 +0000</pubDate>
		<dc:creator>decipherinfosys</dc:creator>
				<category><![CDATA[DB2 LUW]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://decipherinfosys.wordpress.com/?p=2149</guid>
		<description><![CDATA[While tuning some of the reports at a client site, we noticed that almost all of their reports were using too many sub-selects within their queries in the select part of the queries i.e. select statements within a select statement, example:
select col1, col2,
(select max(col3) from x where x.col4 = t.col1),
(select avg(col5) from y where y.col3 [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=decipherinfosys.wordpress.com&blog=691282&post=2149&subd=decipherinfosys&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>While tuning some of the reports at a client site, we noticed that almost all of their reports were using too many sub-selects within their queries in the select part of the queries i.e. select statements within a select statement, example:</p>
<p>select col1, col2,<br />
(select max(col3) from x where x.col4 = t.col1),<br />
(select avg(col5) from y where y.col3 = t.col1)</p>
<p>from t<br />
where t.col7 &lt; 90;</p>
<p>There were also too many derived tables (SQL Server lingo) &#8211; also called as inline views (Oracle)&#8230;this is when the select statement is a part of the from clause, example:</p>
<p>select col1, col2,<br />
(select max(col3) from x where x.col4 = t.col1),<br />
(select avg(col5) from x where col3 = t.col1)</p>
<p>from (select t.col1, t.col2, t2.col3 from t inner join t2 on t.col1 = t2.col5) as t<br />
where t.col7 &lt; 90;</p>
<p>Inline views/Derived tables have their usefulness and we will cover those in a future blog post.  Back to the sub-selects now&#8230;the scalar sub-selects can sometimes be ok to use &#8211; especially when the aim is to return top x number of records &amp; the logic is pretty complex which warrants the need for a sub-select.  However, if the data set is large, then since these sub-selects get executed per row returned by the main query, these can be a real drain on the resources.  In a majority of the cases, usage of sub-selects is not an efficient way of writing the SQL queries.</p>
<p>We had a similar situation at the client site and were able to re-write those report SQLs by either:</p>
<p>a) Re-writing the query by making use of joins rather than sub-selects, or<br />
b) Making use of analytic functions to by-pass the reason why the complex sub-selects were written, or<br />
c) By using CTE or by making use of the derived tables.</p>
<p><strong>Resources</strong>:</p>
<ul>
<li>Great discussion on Tom Kyte&#8217;s site on the same topic &#8211; <a href="http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:1594885400346999596">here</a>.</li>
<li>Another example &#8211; <a href="http://stackoverflow.com/questions/558316/how-do-i-condense-this-sql-of-multiple-sub-selects-into-something-more-sane">here</a>.</li>
</ul>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/decipherinfosys.wordpress.com/2149/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/decipherinfosys.wordpress.com/2149/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/decipherinfosys.wordpress.com/2149/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/decipherinfosys.wordpress.com/2149/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/decipherinfosys.wordpress.com/2149/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/decipherinfosys.wordpress.com/2149/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/decipherinfosys.wordpress.com/2149/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/decipherinfosys.wordpress.com/2149/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/decipherinfosys.wordpress.com/2149/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/decipherinfosys.wordpress.com/2149/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=decipherinfosys.wordpress.com&blog=691282&post=2149&subd=decipherinfosys&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://decipherinfosys.wordpress.com/2009/04/28/too-many-sub-selects/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0409e90c82255ecb867b436a97e4f779?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">decipherinfosys</media:title>
		</media:content>
	</item>
		<item>
		<title>UnIndexed Foreign Keys &#8211; II</title>
		<link>http://decipherinfosys.wordpress.com/2008/12/03/unindexed-foreign-keys-ii/</link>
		<comments>http://decipherinfosys.wordpress.com/2008/12/03/unindexed-foreign-keys-ii/#comments</comments>
		<pubDate>Wed, 03 Dec 2008 00:06:31 +0000</pubDate>
		<dc:creator>decipherinfosys</dc:creator>
				<category><![CDATA[DB2 LUW]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://decipherinfosys.wordpress.com/?p=1489</guid>
		<description><![CDATA[In some of our previous posts, we have covered the issues that unindexed foreign keys can cause.  You can read these posts to get more information on those:

Back to the Basics: Foreign Keys
Un-Indexed Foreign Keys
Blocking on Foreign Keys

A reader asked us whether it is always required to index the FKs or are there some [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=decipherinfosys.wordpress.com&blog=691282&post=1489&subd=decipherinfosys&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>In some of our previous posts, we have covered the issues that unindexed foreign keys can cause.  You can read these posts to get more information on those:</p>
<ol>
<li><a href="http://decipherinfosys.wordpress.com/2007/06/09/back-to-the-basics-foreign-keys/">Back to the Basics: Foreign Keys</a></li>
<li><a href="http://decipherinfosys.wordpress.com/2007/05/23/un-indexed-foreign-keys/">Un-Indexed Foreign Keys</a></li>
<li><a href="http://decipherinfosys.wordpress.com/2007/02/01/blocking-on-foreign-keys-in-sql-server/">Blocking on Foreign Keys</a></li>
</ol>
<p>A reader asked us whether it is always required to index the FKs or are there some guidelines that can be given in order to not do it under certain scenarios?  There are some scenarios under which you do not need to have indexes on the FKs:</p>
<p>a) When you do not delete records from the parent table especially when you do not have the &#8220;ON DELETE CASCADE&#8221; rule set.</p>
<p>b) When you do not join from the parent table to the child table.</p>
<p>c) When you do not update the unique key (primary key in most cases) in the parent table.  This is not done mostly since it would mean a bad selection of the Primary Key column.</p>
<p>d) And if you never query that table directly based on that FK column(s).</p>
<p>e) The child table is a small table and is used only for lookups.</p>
<p>So, if all these conditions above are met in your environment, then there is no need to index those FK columns but else it is usually a good idea to index your foreign keys.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/decipherinfosys.wordpress.com/1489/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/decipherinfosys.wordpress.com/1489/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/decipherinfosys.wordpress.com/1489/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/decipherinfosys.wordpress.com/1489/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/decipherinfosys.wordpress.com/1489/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/decipherinfosys.wordpress.com/1489/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/decipherinfosys.wordpress.com/1489/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/decipherinfosys.wordpress.com/1489/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/decipherinfosys.wordpress.com/1489/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/decipherinfosys.wordpress.com/1489/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=decipherinfosys.wordpress.com&blog=691282&post=1489&subd=decipherinfosys&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://decipherinfosys.wordpress.com/2008/12/03/unindexed-foreign-keys-ii/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0409e90c82255ecb867b436a97e4f779?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">decipherinfosys</media:title>
		</media:content>
	</item>
		<item>
		<title>Using DISTINCT &#8230; just because</title>
		<link>http://decipherinfosys.wordpress.com/2008/11/21/using-distinct-just-because/</link>
		<comments>http://decipherinfosys.wordpress.com/2008/11/21/using-distinct-just-because/#comments</comments>
		<pubDate>Fri, 21 Nov 2008 16:58:25 +0000</pubDate>
		<dc:creator>decipherinfosys</dc:creator>
				<category><![CDATA[DB2 LUW]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://decipherinfosys.wordpress.com/?p=1438</guid>
		<description><![CDATA[We have blogged about the DISTINCT clause in the past (common mis-conceptions about the DISTINCT clause) and what it does and how it gets mis-used at times.  This is one of the common issues that we have seen in some of the queries written by junior folks or even at times by senior folks [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=decipherinfosys.wordpress.com&blog=691282&post=1438&subd=decipherinfosys&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>We have blogged about the DISTINCT clause in the past (<a href="http://decipherinfosys.wordpress.com/2007/12/22/some-common-mis-conceptions-about-distinct/">common mis-conceptions about the DISTINCT clause</a>) and what it does and how it gets mis-used at times.  This is one of the common issues that we have seen in some of the queries written by junior folks or even at times by senior folks not well versed with SQL.  They add the DISTINCT clause to the Select list just to make sure that &#8220;in case&#8221; there are duplicates, it will all be taken care of by this wonderful clause.  Most of the time, the reason why they get duplicates is because of join conditions or because they did not write the query in different ways like for example: If you have a 3 table join and say tableA : tableB :: 1:N (1 to many relationship) and tableB:tableC::1:N (again a 1 to many relationship) and the 3 joins are together but one is only selecting the data from tableA and tableB and that set of columns provides unique set of data, however the developer also adds tableC in the join because there is a filter condition (where clause) on it.  That would result into duplicates when there are many records being returned from tableC for a record in tableB because of the 1:N relationship.  In that case, the developer ends up adding a DISTINCT clause in the select list to get the distinct set of data.  The developer instead could have chosen to just use an EXISTS clause like this:</p>
<p>select &#8230;&lt;columns from tableA and tableB&gt;&#8230;</p>
<p>from tableA</p>
<p>inner join table B</p>
<p>on tableA.col1 = tableB.col2</p>
<p>where &#8230;&lt;criteria on tableA and tableB &#8211; if being used based on the business logic&gt;&#8230;</p>
<p>and exists (select 1 from tableC where col3 = tableB.col4)</p>
<p>and this will negate the usage of the DISTINCT clause.  There are many other such scenarios as well.  The problem with using DISTINCT un-necessarily is that the code will then incur sorting costs un-necessarily since the DISTINCT clause requires that the resultset is sorted and the duplicates are eliminated from the result set.</p>
<p>We have seen even bigger issues when people start using distinct aggregates even when they are not needed or when there are better ways to write the query&#8230;by distinct aggregates, we mean, clauses like:</p>
<p>count(distinct invoice_nbr) or sum(distinct sales_qty) etc.</p>
<p>The problem exacerbates when there are a lot of mixing of such distinct aggregates with non-distinct aggregates, example:</p>
<p>select<br />
count(distinct invoice_nbr),<br />
sum(distinct sales_qty),<br />
count(ship_date),<br />
Avg(sales_price),</p>
<p>&#8230;etc.</p>
<p>Mixing of these distinct aggregates and non distinct aggregates in the same SQL statement&#8217;s select list leads to spooling and involves several re-reads of the intermediate results which is very expensive &#8211; even more expensive than computing those separately in separate queries.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/decipherinfosys.wordpress.com/1438/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/decipherinfosys.wordpress.com/1438/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/decipherinfosys.wordpress.com/1438/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/decipherinfosys.wordpress.com/1438/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/decipherinfosys.wordpress.com/1438/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/decipherinfosys.wordpress.com/1438/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/decipherinfosys.wordpress.com/1438/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/decipherinfosys.wordpress.com/1438/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/decipherinfosys.wordpress.com/1438/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/decipherinfosys.wordpress.com/1438/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=decipherinfosys.wordpress.com&blog=691282&post=1438&subd=decipherinfosys&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://decipherinfosys.wordpress.com/2008/11/21/using-distinct-just-because/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0409e90c82255ecb867b436a97e4f779?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">decipherinfosys</media:title>
		</media:content>
	</item>
		<item>
		<title>Back to the Basics: Understanding the BETWEEN Operator</title>
		<link>http://decipherinfosys.wordpress.com/2008/11/07/back-to-the-basics-understanding-the-between-operator/</link>
		<comments>http://decipherinfosys.wordpress.com/2008/11/07/back-to-the-basics-understanding-the-between-operator/#comments</comments>
		<pubDate>Fri, 07 Nov 2008 14:06:41 +0000</pubDate>
		<dc:creator>decipherinfosys</dc:creator>
				<category><![CDATA[DB2 LUW]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://decipherinfosys.wordpress.com/?p=1390</guid>
		<description><![CDATA[At one of the client sites, a junior developer asked this question which is worth posting over here.  The question was pertaining to the BETWEEN operator.  As you know, this operator is used to test the existence of the values between two expressions.  Here is the entry from BOL for the syntax:
test_expression [ NOT ] [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=decipherinfosys.wordpress.com&blog=691282&post=1390&subd=decipherinfosys&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>At one of the client sites, a junior developer asked this question which is worth posting over here.  The question was pertaining to the BETWEEN operator.  As you know, this operator is used to test the existence of the values between two expressions.  Here is the entry from BOL for the syntax:</p>
<pre><em>test_expression</em> [ NOT ] BETWEEN <em>begin_expression</em> AND<em> end_expression

</em></pre>
<p>The key to understanding is this section (from BOL):</p>
<p><em>BETWEEN returns <strong>TRUE</strong> if the value of </em><em>test_expression  is greater than or equal to the value of </em><em>begin_expression and less than  or equal to the value of </em><em>end_expression.</em></p>
<p><em>NOT BETWEEN returns <strong>TRUE</strong> if the value of </em><em>test_expression is less than the value of </em><em>begin_expression or  greater than the value of </em><em>end_expression.</em></p>
<p>What the developer was trying to do was &#8211; use the criteria in any order &#8230; so, if we have this query against the AdventureWorks database:</p>
<p>select * from Production.Product where SellStartDate between &#8216;2001-06-29&#8242; and &#8216;2001-07-02&#8242;</p>
<p>It will return 72 records.  If the values are swapped:</p>
<p>select * from Production.Product where SellStartDate between &#8216;2001-07-02&#8242; and &#8216;2001-06-29&#8242;</p>
<p>it will return zero records and the reason is that internally the query (as mentioned by BOL and the ANSI SQL Standards as well) gets translated to:</p>
<p>select * from Production.Product where SellStartDate <strong>&gt;= @first_value</strong> and SellStartDate <strong>&lt;= @last_value</strong></p>
<p>So, in the event of the second query, you will never find an intersection set of the data.  Please do note that the equality ( = ) is also included when you use the BETWEEN clause.</p>
<p>It would have been perfectly fine if one wanted to avoid all the records where the dates were falling between those 2 ranges &#8211; in that case, one then needs to use the &#8220;NOT BETWEEN&#8221; operator:</p>
<p>select * from Production.Product where SellStartDate <strong>not between</strong> &#8216;2001-07-02&#8242; and &#8216;2001-06-29&#8242;</p>
<p>Which returns 504 records.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/decipherinfosys.wordpress.com/1390/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/decipherinfosys.wordpress.com/1390/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/decipherinfosys.wordpress.com/1390/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/decipherinfosys.wordpress.com/1390/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/decipherinfosys.wordpress.com/1390/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/decipherinfosys.wordpress.com/1390/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/decipherinfosys.wordpress.com/1390/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/decipherinfosys.wordpress.com/1390/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/decipherinfosys.wordpress.com/1390/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/decipherinfosys.wordpress.com/1390/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=decipherinfosys.wordpress.com&blog=691282&post=1390&subd=decipherinfosys&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://decipherinfosys.wordpress.com/2008/11/07/back-to-the-basics-understanding-the-between-operator/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0409e90c82255ecb867b436a97e4f779?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">decipherinfosys</media:title>
		</media:content>
	</item>
		<item>
		<title>Design issue and a SQL Solution</title>
		<link>http://decipherinfosys.wordpress.com/2008/11/06/design-issue-and-a-sql-solution/</link>
		<comments>http://decipherinfosys.wordpress.com/2008/11/06/design-issue-and-a-sql-solution/#comments</comments>
		<pubDate>Thu, 06 Nov 2008 20:36:26 +0000</pubDate>
		<dc:creator>decipherinfosys</dc:creator>
				<category><![CDATA[DB2 LUW]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://decipherinfosys.wordpress.com/?p=1388</guid>
		<description><![CDATA[How many times have you ended up in a scenario where the design of the schema was not optimal and were told that you have to fix the issue without changing the schema?  And the resistance to changing the schema is still there despite telling folks about the performance implications of patching up bad [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=decipherinfosys.wordpress.com&blog=691282&post=1388&subd=decipherinfosys&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>How many times have you ended up in a scenario where the design of the schema was not optimal and were told that you have to fix the issue without changing the schema?  And the resistance to changing the schema is still there despite telling folks about the performance implications of patching up bad design with code that should not be needed.  We have highlighted such design issues off and on in our blog posts in the past.</p>
<p>Today also we will look at another such 2 issues:</p>
<p><span style="text-decoration:underline;"><strong>Issue #1</strong></span>: In an OLTP system, keeping the aggregated quantity at the header level i.e. there is a HDR table and a DTL table and the quantity is at the DTL level.  However, the system maintains an AGG_QTY column in the HDR table which needs to be updated anytime an insert/update/delete happens for the detail records.  To make matters worse, at times we have seen different applications writing against that schema and not keeping it up to date which makes an inventory mis-match.  Relational design for transactional applications should be done such that doing an easy join and aggregation should be a READ operation and not a WRITE operation.  In this case, there was no need to store the aggregated information at the HDR level.  Well, can&#8217;t change the design.  Need a solution to fix the issue.  What would you do?  Trigger?  Yup.  Another alternative, if the client is ok with it is to have a view that presents the roll up information but then again, it will be a code change to read that information from the view instead of the table.</p>
<p><span style="text-decoration:underline;"><strong>Issue #2</strong></span>: Kind of the same scenario but with a &#8220;twist&#8221;.  There is a table say TABLEA which has say three columns: COL1, COL2 and COL3 which together make up the alternate key for that table.  For a given combination of COL1 and COL2, the client wanted at the most 3 enteries.  So:</p>
<p>COL1    COL2    COL3<br />
A1        B1        10<br />
A1        B1        20<br />
A1        B1        30</p>
<p>If we try to create another record with:</p>
<p>COL1    COL2    COL3<br />
A1        B1        40</p>
<p>It should give an error even though the alternate key (by design) allows it.  There are many ways of achieving this &#8211; trigger is an obvious one&#8230;in the case of Oracle, one can do this via a materialized view as well and then creating a check constraint on it.  Example:</p>
<p>SQL&gt;<br />
SQL&gt; create materialized view log on TABLEA with rowid(COL1, COL2) including new values;</p>
<p>SQL&gt; create materialized view MV_TEST<br />
2  refresh fast<br />
3  on commit<br />
4  as<br />
5  select COL1, COL2, count(*) CNT<br />
6    from TABLEA<br />
7   group by COL1, COL2<br />
8  /</p>
<p>SQL&gt; alter table MV_TEST add constraint check_val_3 check(CNT&lt;=3);</p>
<p>And here is a simple trigger definition for this (SQL Server Syntax):</p>
<p>CREATE TABLE TABLEA (COL1 NVARCHAR(10), COL2 NVARCHAR(10), COL3 INT);<br />
CREATE UNIQUE INDEX TABLEA_IND_1 ON TABLEA (COL1, COL2, COL3);<br />
INSERT INTO TABLEA VALUES (&#8216;A1&#8242;, &#8216;B1&#8242;, 10);<br />
INSERT INTO TABLEA VALUES (&#8216;A1&#8242;, &#8216;B1&#8242;, 20);<br />
INSERT INTO TABLEA VALUES (&#8216;A1&#8242;, &#8216;B1&#8242;, 30);</p>
<p>/*Trigger Definition*/<br />
create trigger dbo.test_allow_unique<br />
on TABLEA<br />
for insert, update<br />
AS<br />
set nocount on</p>
<p>IF EXISTS(select 1<br />
from   inserted as i<br />
inner join dbo.TABLEA as tu<br />
on i.col1 = tu.col1<br />
and i.col2 = tu.col2<br />
group  by tu.col1, tu.col2<br />
having count(*) &gt; 3)<br />
BEGIN<br />
ROLLBACK<br />
RAISERROR(&#8216;Uniqueness Criteria violated.&#8217;, 16, 1)<br />
END<br />
GO</p>
<p>Now, when you try to insert another value:</p>
<p>INSERT INTO TABLEA VALUES (&#8216;A1&#8242;, &#8216;B1&#8242;, 40);</p>
<p>You will get the error:</p>
<p><span style="color:#ff0000;"><em>Msg 50000, Level 16, State 1, Procedure test_allow_unique, Line 18<br />
Uniqueness Criteria violated.<br />
Msg 3609, Level 16, State 1, Line 1<br />
The transaction ended in the trigger. The batch has been aborted.</em><br />
</span></p>
<p>Or if you are using SQL Server 2008, you can use <a href="http://decipherinfosys.wordpress.com/2008/03/20/filtered-indexes-and-statistics-in-sql-server-2008/">filtered indexes</a> as well.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/decipherinfosys.wordpress.com/1388/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/decipherinfosys.wordpress.com/1388/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/decipherinfosys.wordpress.com/1388/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/decipherinfosys.wordpress.com/1388/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/decipherinfosys.wordpress.com/1388/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/decipherinfosys.wordpress.com/1388/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/decipherinfosys.wordpress.com/1388/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/decipherinfosys.wordpress.com/1388/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/decipherinfosys.wordpress.com/1388/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/decipherinfosys.wordpress.com/1388/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=decipherinfosys.wordpress.com&blog=691282&post=1388&subd=decipherinfosys&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://decipherinfosys.wordpress.com/2008/11/06/design-issue-and-a-sql-solution/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0409e90c82255ecb867b436a97e4f779?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">decipherinfosys</media:title>
		</media:content>
	</item>
		<item>
		<title>A simple query</title>
		<link>http://decipherinfosys.wordpress.com/2008/11/05/a-simple-query/</link>
		<comments>http://decipherinfosys.wordpress.com/2008/11/05/a-simple-query/#comments</comments>
		<pubDate>Wed, 05 Nov 2008 17:53:06 +0000</pubDate>
		<dc:creator>decipherinfosys</dc:creator>
				<category><![CDATA[DB2 LUW]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://decipherinfosys.wordpress.com/?p=1384</guid>
		<description><![CDATA[Yesterday, a good friend of mine asked this question pertaining to an issue that he saw at the client site.  The query was being fired off by a UI screen in the application and the query that was being formed as part of the SQLBuilder (custom built ORM by the vendor) was not building [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=decipherinfosys.wordpress.com&blog=691282&post=1384&subd=decipherinfosys&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Yesterday, a good friend of mine asked this question pertaining to an issue that he saw at the client site.  The query was being fired off by a UI screen in the application and the query that was being formed as part of the SQLBuilder (custom built ORM by the vendor) was not building up the query properly leading to very poor performance.  The RDBMS that this client was using was Oracle however the same sets of issues apply to any RDBMS.</p>
<p>The query had 5 tables involved :</p>
<p>SELECT * FROM<br />
(SELECT ROWNUM ROW_NUM, A.* FROM<br />
(SELECT DISTINCT<br />
PKT_HDR_INTRNL.PKT_CTRL_NBR AS A255, PKT_HDR.CO AS A3, PKT_HDR.DIV AS A4,<br />
PKT_HDR.PKT_NBR AS A5, PKT_HDR.PKT_SFX AS A6, PKT_HDR.SHIPTO_NAME AS A11,<br />
PKT_HDR.START_SHIP_DATE AS A60, PKT_HDR.STOP_SHIP_DATE AS A61,<br />
PKT_HDR.SHIP_VIA AS A49, PKT_HDR_INTRNL.TOTAL_NBR_OF_UNITS AS A266,<br />
PKT_HDR_INTRNL.STAT_CODE AS A262, PKT_HDR_INTRNL.VAS_INDIC  AS A339,<br />
PKT_HDR.WHSE AS A2, PKT_HDR_INTRNL.MAJOR_MINOR_PKT AS A275,<br />
PKT_HDR.PACK_SLIP_TYPE AS A123, PKT_HDR.PKT_TYPE AS A82,<br />
PKT_HDR.PKT_GENRTN_DATE_TIME AS A59, PKT_HDR.ORD_NBR AS A7,<br />
PKT_HDR_INTRNL.PICK_WAVE_NBR AS A256, CHUTE_MASTER.CHUTE_ID AS A378,<br />
PKT_HDR_INTRNL.WAVE_STAT_CODE AS A258, PKT_HDR.PKT_CTRL_NBR AS A1, &#8221;  AS<br />
A419, ITEM_MASTER.SKU_ID AS A307, ITEM_MASTER.DIV AS A309,<br />
PKT_DTL.CANCEL_QTY AS A159<br />
FROM <strong>PKT_DTL, ITEM_MASTER, CHUTE_MASTER, PKT_HDR, PKT_HDR_INTRNL</strong><br />
WHERE<br />
PKT_HDR.PKT_CTRL_NBR=PKT_HDR_INTRNL.PKT_CTRL_NBR AND<br />
PKT_HDR.PKT_CTRL_NBR=PKT_DTL.PKT_CTRL_NBR(+) AND<br />
PKT_DTL.SKU_ID=ITEM_MASTER.SKU_ID AND<br />
PKT_HDR_INTRNL.CHUTE_ID=CHUTE_MASTER.CHUTE_ID(+) AND<br />
PKT_HDR.WHSE = &#8216;02&#8242; AND<br />
PKT_HDR_INTRNL.STAT_CODE &gt;= 10 AND<br />
PKT_HDR_INTRNL.STAT_CODE &lt;= 60 AND<br />
PKT_HDR.DIV = &#8216;64&#8242; AND<br />
PKT_HDR.CO = &#8216;88&#8242; AND<br />
ITEM_MASTER.CO = &#8216;88&#8242; AND<br />
ITEM_MASTER.DIV = &#8216;64&#8242;<br />
ORDER BY PKT_HDR_INTRNL.PKT_CTRL_NBR ASC ) A<br />
WHERE ROWNUM &lt; 21 )<br />
WHERE ROW_NUM &gt;= 1</p>
<p><span style="text-decoration:underline;"><strong>And here are the relationships</strong></span>:</p>
<p>PKT_HDR : PKT_HDR_INTRNL :: 1:1 (hard one to one because of the number of columns in each table, it was split up into two tables)</p>
<p>PKT_HDR : PKT_DTL :: 1:N (for every header, there can be 1 &#8211; N details)</p>
<p>ITEM_MASTER : PKT_DTL :: 1:N (every PKT_DTL will be associated with one and only one ITEM_MASTER record)</p>
<p>CHUTE_MASTER : PKT_HDR_INTRNL :: 1:N (0-N) (One chute can belong to more than one PKT record)</p>
<p>What my friend noticed was that the query was doing a FTS on PKT_DTL as soon as the column PKT_DTL.CANCEL_QTY was introduced in the Select list.  It was not doing that if that column was omitted from the selection list.  That is how this query got noticed. First thing to notice is the pagination logic in the query &#8211; we have discussed that before &#8211; the <a href="http://decipherinfosys.wordpress.com/2007/08/09/paging-and-countstopkey-optimization/">count stop key optimization</a>.</p>
<p>It does have some functional flaws though before we get into the performance tuning side of things:</p>
<p><strong>1) </strong>The query is doing a left outer join between PKT_HDR and PKT_DTL and then it is doing an INNER JOIN between PKT_DTL and ITEM_MASTER??</p>
<p>So, for records in the PKT_HDR table for which there are no details, when that INNER JOIN is done, those records will be filtered out.  Either the join between PKT_HDR and PKT_DTL needs to be changed to an inner join or the join between PKT_DTL and ITEM_MASTER and the subsequent filters on ITEM_MASTER need to be in an outer join condition.</p>
<p>So, that is a functional issue.</p>
<p><strong>2)</strong> Older join syntax of Oracle has been followed which is not an issue &#8211; just that it is not ANSI and many times leads to issues for Developers/DBAs who are not familiar with it.  It is what probably lead to the issue mentioned in #1 above.</p>
<p><strong>3) </strong>CHUTE_ID is the only column that is being displayed from that table.  Since it is in an outer join condition with no filter condition, that join can be completely omitted and the CHUTE_ID from the child table itself can be used.</p>
<p><strong>4) </strong>The DISTINCT is causing SORT and the distinct is needed only because the PKT_DTL join has been added to the query and no columns from the PKT_DTL table are being selected.  Note that the PKT_DTL.CANCEL_QTY column was not always present &#8211; that was a modification done by the end user.</p>
<p>When he talked to the business folks, it turned out that the OUTER JOIN with PKT_DTL was not needed and they really needed to restrict based on the data from the detail records and then the ITEM_MASTER table.  Once those changes were made, the execution plan was fine and went through the primary key join condition&#8217;s index for the filter criteria specified.  This can still result into issues down the line since the client is using FIRST_ROWS_N optimization for fast retrieval of the records but the filter criteria values are dynamic and so it can happen that based on the status code values, they can end up qualifying for more than 40% of the PKT_DTL table.  So, besides the changes from above, depending upon the flow, they needed to make sure that the selective criteria is passed in as well.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/decipherinfosys.wordpress.com/1384/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/decipherinfosys.wordpress.com/1384/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/decipherinfosys.wordpress.com/1384/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/decipherinfosys.wordpress.com/1384/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/decipherinfosys.wordpress.com/1384/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/decipherinfosys.wordpress.com/1384/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/decipherinfosys.wordpress.com/1384/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/decipherinfosys.wordpress.com/1384/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/decipherinfosys.wordpress.com/1384/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/decipherinfosys.wordpress.com/1384/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=decipherinfosys.wordpress.com&blog=691282&post=1384&subd=decipherinfosys&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://decipherinfosys.wordpress.com/2008/11/05/a-simple-query/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0409e90c82255ecb867b436a97e4f779?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">decipherinfosys</media:title>
		</media:content>
	</item>
		<item>
		<title>Returning a record set from a Function in Oracle, SQL Server and DB2</title>
		<link>http://decipherinfosys.wordpress.com/2008/10/27/returning-a-record-set-from-a-function-in-oracle-sql-server-and-db2/</link>
		<comments>http://decipherinfosys.wordpress.com/2008/10/27/returning-a-record-set-from-a-function-in-oracle-sql-server-and-db2/#comments</comments>
		<pubDate>Mon, 27 Oct 2008 01:24:29 +0000</pubDate>
		<dc:creator>decipherinfosys</dc:creator>
				<category><![CDATA[DB2 LUW]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://decipherinfosys.wordpress.com/?p=1346</guid>
		<description><![CDATA[In one of our previous posts, we had covered how to return record sets from a stored procedure in the case of Oracle, SQL Server and DB2 LUW.  One of the readers recently asked how to do the same with a User Defined Function.  We will demonstrate that in this blog post.
In Oracle, [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=decipherinfosys.wordpress.com&blog=691282&post=1346&subd=decipherinfosys&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>In one of our previous posts, we had covered how to <a href="http://decipherinfosys.wordpress.com/2008/05/19/returning-a-record-set-from-a-stored-procedure/">return record sets from a stored procedure</a> in the case of Oracle, SQL Server and DB2 LUW.  One of the readers recently asked how to do the same with a User Defined Function.  We will demonstrate that in this blog post.</p>
<p class="MsoNormal"><span style="font-family:Verdana;font-size:x-small;"><strong>In Oracle</strong>, function which returns record set,  requires an object type with attributes to be created first. Once object Type is  created, we have to create named table type of the object type. In function we  can use named table type as return type. We will show you in code snippet, how  to do it but first let us create a table and populate it with some data. If you  already have table with the same name, change all the occurrences of the table  name with some other name.</span><span style="font-family:Verdana;"><span style="font-size:x-small;"></p>
<p></span></span><span style="font-size:x-small;"><span style="font-family:Courier New;">CREATE TABLE Test<br />
(<br />
Test_ID      NUMBER(9) NOT NULL,<br />
Test_Desc    VARCHAR(30),<br />
Test_DATE    DATE,<br />
CONSTRAINT PK_TEST PRIMARY KEY(Test_ID)<br />
)<br />
&#8211; TABLESPACE Clause<br />
/</p>
<p>INSERT INTO Test(Test_Id, Test_Desc, Test_Date)<br />
SELECT rownum, table_name, sysdate<br />
FROM user_tables<br />
WHERE rownum &lt;= 5<br />
/<br />
</span><span style="font-family:Verdana;"><br />
</span></span><span style="font-family:Verdana;font-size:x-small;">Here is the data in the table.</span><span style="font-family:&quot;"><span style="font-size:x-small;"></p>
<p></span></span> <span style="font-size:x-small;"><span style="font-family:Courier New;">SQL&gt; select * from test;</p>
<p>TEST_ID TEST_DESC                      TEST_DATE<br />
&#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;<br />
1 DEPT                           20-FEB-07<br />
2 EMP                            20-FEB-07<br />
3 BONUS                          20-FEB-07<br />
4 SALGRADE                       20-FEB-07<br />
5 TEST                           20-FEB-07</span><span style="font-family:&quot;"></p>
<p></span> </span><span style="font-family:Verdana;font-size:x-small;">Now let us assume, we want to return test_id and test_desc to calling  application using function. First of all we will create an object type. Make  sure that proper privileges are assigned to the user.</span><span style="font-family:&quot;"><span style="font-size:x-small;"></p>
<p></span></span><span style="font-size:x-small;"><span style="font-family:Courier New;">CREATE OR REPLACE TYPE TEST_OBJ_TYPE IS OBJECT<br />
(<br />
TEST_ID   NUMBER(9),<br />
TEST_DESC VARCHAR(30)<br />
)<br />
/<br />
</span><span style="font-family:&quot;"><br />
</span></span><span style="font-family:Verdana;font-size:x-small;">Once object type is created, we will create named table type of above  object type.</span><span style="font-family:&quot;"><span style="font-size:x-small;"></p>
<p></span></span><span style="font-size:x-small;"><span style="font-family:Courier New;">CREATE OR REPLACE TYPE TEST_TABTYPE AS TABLE OF TEST_OBJ_TYPE<br />
/<br />
</span><span style="font-family:&quot;"><br />
</span></span><span style="font-family:Verdana;font-size:x-small;">Now let us write function code to return the result set. </span> <span style="font-family:&quot;"><span style="font-size:x-small;"></p>
<p></span></span><span style="font-size:x-small;"><span style="font-family:Courier New;">CREATE OR REPLACE FUNCTION FN_GET_ROWS<br />
RETURN TEST_TABTYPE<br />
AS<br />
V_Test_Tabtype Test_TabType;<br />
BEGIN<br />
SELECT TEST_OBJ_TYPE(A.Test_Id, A.Test_Desc)<br />
BULK COLLECT INTO V_Test_TabType<br />
FROM<br />
(SELECT Test_Id, Test_Desc<br />
FROM Test<br />
) A;<br />
RETURN V_Test_TabType;</p>
<p>EXCEPTION<br />
WHEN OTHERS THEN<br />
v_Test_TabType.DELETE;<br />
RETURN v_Test_TabType;<br />
END;<br />
/<br />
</span> <span style="font-family:&quot;"><br />
</span></span><span style="font-family:Verdana;font-size:x-small;">Create above mentioned function and then run following SQL to execute it.  Below is the SQL followed by result.</span><span style="font-size:x-small;"><span style="font-family:&quot;"></p>
<p></span><span style="font-family:Courier New;">SQL&gt; SELECT * FROM TABLE(FN_</span></span><span style="font-family:Courier New;font-size:x-small;">GET_ROWS</span><span style="font-family:Courier New;font-size:x-small;">);</span><span style="font-size:x-small;"><span style="font-family:Courier New;"></p>
<p>TEST_ID TEST_DESC<br />
&#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
1 DEPT<br />
2 EMP<br />
3 BONUS<br />
4 SALGRADE<br />
5 TEST<br />
</span><span style="font-family:&quot;"><br />
</span></span><span style="font-family:Verdana;font-size:x-small;">Here we have shown one example of returning record set from function.  There are other ways of doing this in function also by initializing named table  type and then allocating space using .extend as required.<br />
</span></p>
<p><span style="font-family:Verdana;font-size:x-small;"><strong>SQLServer </strong>supports scalar  functions, inline table-valued functions and multi statement table-valued  functions. Here we will see how we can use multi statement table-valued function  to return record set. First let us create table and populate it with sample  data.</span><span style="font-family:Verdana;"><span style="font-size:x-small;"></p>
<p></span></span><span style="font-size:x-small;"><span style="font-family:Courier New;">CREATE TABLE Test<br />
(<br />
Test_ID      INT IDENTITY(1,1) NOT NULL,<br />
Test_Desc    VARCHAR(30),<br />
Test_DATE    DATETIME,<br />
CONSTRAINT PK_TEST PRIMARY KEY(Test_ID)<br />
)<br />
&#8211; FILEGROUP Clause<br />
GO</p>
<p>INSERT INTO Test(Test_Desc, Test_Date)<br />
SELECT TOP 5 table_name, getDate()<br />
FROM information_Schema.tables<br />
GO<br />
</span><span style="font-family:Verdana;"><br />
</span></span><span style="font-family:Verdana;font-size:x-small;">Following is the data in the table. You may have different set of data.</span><span style="font-family:&quot;"><span style="font-size:x-small;"></p>
<p></span></span><span style="font-size:x-small;"><span style="font-family:Courier New;">Test_Id              Test_Desc     Test_Date<br />
&#8212;&#8212;-              &#8212;&#8212;&#8212;     &#8212;&#8212;&#8212;-<br />
1                    syssegments   2007-02-21 23:19:11.717<br />
2                    sysconstraints2007-02-21 23:19:11.717<br />
3                    Invoice       2007-02-21 23:19:11.717<br />
4                    TEMP_Invoice  2007-02-21 23:19:11.717<br />
5                    Test          2007-02-21 23:19:11.717</span><span style="font-family:&quot;"></p>
<p></span></span><span style="font-family:Verdana;font-size:x-small;">Let us create function. You can run following code snippet from query  analyzer.</span><span style="font-family:&quot;"><span style="font-size:x-small;"></p>
<p></span></span><span style="font-size:x-small;"><span style="font-family:Courier New;">CREATE FUNCTION  DBO.FN_GET_ROWS()<br />
RETURNS @TABLE TABLE<br />
(<br />
TEST_ID INT,<br />
TEST_DESC VARCHAR(30)<br />
)<br />
AS<br />
BEGIN<br />
INSERT @TABLE<br />
SELECT TEST_ID, TEST_DESC<br />
FROM DBO.TEST<br />
RETURN<br />
END<br />
GO<br />
</span><span style="font-family:&quot;"><br />
</span></span><span style="font-family:Verdana;font-size:x-small;">Once function is created successfully. Execute it using following sql. It  is followed by the data returned by the function.</span><span style="font-size:x-small;"><span style="font-family:&quot;"></p>
<p></span><span style="font-family:Courier New;">SELECT * FROM DBO.FN_</span></span><span style="font-family:Courier New;font-size:x-small;">GET_ROWS</span><span style="font-family:Courier New;font-size:x-small;">()</span><span style="font-size:x-small;"><span style="font-family:Courier New;"><br />
GO</p>
<p>Test_Id              Test_Desc<br />
&#8212;&#8212;-              &#8212;&#8212;&#8212;<br />
1             syssegments<br />
2             sysconstraints<br />
3             Invoice<br />
4             TEMP_Invoice<br />
5             Test </span><span style="font-family:&quot;"></p>
<p></span></span><span style="font-family:Verdana;font-size:x-small;">Table-valued functions can be used in join conditions also.<strong></p>
<p>DB2 </strong>does not support multi statement table-valued function. It supports only  inline table-valued function so we don’t have much flexibility in case of DB2.  But we will see how we can get data using inline table-valued functions in DB2.</p>
<p>First we will create an empty table. Please make sure that statement terminator  is defined as @.</span><span style="font-size:x-small;"><span style="font-family:&quot;"></p>
<p></span> <span style="font-family:Courier New;">CREATE TABLE Test<br />
(<br />
Test_ID      INT NOT NULL  GENERATED BY DEFAULT AS<br />
IDENTITY (START WITH +1, INCREMENT BY +1, CACHE 1000),<br />
Test_Desc    VARCHAR(30),<br />
Test_DATE    TIMESTAMP,<br />
CONSTRAINT PK_TEST PRIMARY KEY(Test_ID)<br />
)@</p>
<p></span></span><span style="font-family:Courier New;font-size:x-small;">Let us create some data now.</span><span style="font-size:x-small;"><span style="font-family:Courier New;"></p>
<p>INSERT INTO Test(Test_Desc, Test_Date)<br />
SELECT table_name, current timestamp<br />
FROM syscat.tables<br />
FETCH FIRST 5 ROWS ONLY<br />
@<br />
</span><span style="font-family:Verdana;"><br />
</span></span><span style="font-family:Verdana;font-size:x-small;">Following is the data in the table. You may have different set of data.</span><span style="font-family:&quot;"><span style="font-size:x-small;"></p>
<p></span></span><span style="font-size:x-small;"><span style="font-family:Courier New;">Test_Id       Test_Desc                   Test_Date<br />
&#8212;&#8212;-       &#8212;&#8212;&#8212;                   &#8212;&#8212;&#8212;-<br />
1             TEST                        2007-02-22 21:53:13.237<br />
2             ATTRIBUTES                  2007-02-22 21:53:13.237<br />
3             BUFFERPOOLDBPARTITIONS      2007-02-22 21:53:13.237<br />
4             BUFFERPOOLNODES             2007-02-22 21:53:13.237<br />
5             BUFFERPOOLS                 2007-02-22 21:53:13.237</span><span style="font-family:&quot;"></p>
<p></span></span><span style="font-family:Verdana;font-size:x-small;">Let us create function. You can run following code snippet from command  center or from command line editor.</span><span style="font-size:x-small;"><span style="font-family:&quot;"></p>
<p></span><span style="font-family:Courier New;">CREATE FUNCTION FN_</span></span><span style="font-family:Courier New;font-size:x-small;">GET_ROWS</span><span style="font-family:Courier New;font-size:x-small;">()</span><span style="font-size:x-small;"><span style="font-family:Courier New;"><br />
RETURNS TABLE<br />
(<br />
TEST_ID INT,<br />
TEST_DATE TIMESTAMP<br />
)<br />
LANGUAGE SQL<br />
READS SQL DATA<br />
CALLED ON NULL INPUT<br />
NO EXTERNAL ACTION<br />
BEGIN ATOMIC<br />
RETURN<br />
SELECT TEST_ID, TEST_DATE<br />
FROM TEST;<br />
END@<br />
</span><span style="font-family:&quot;"><br />
</span> </span><span style="font-family:Verdana;font-size:x-small;">Once function is created in the database, execute it using following SQL.  Again SQL is followed by record set it returns.</span><span style="font-size:x-small;"><span style="font-family:&quot;"></p>
<p></span><span style="font-family:Courier New;">&#8211; This is how we call table function in DB2. T is an alias.<br />
SELECT * FROM TABLE(FN_</span></span><span style="font-family:Courier New;font-size:x-small;">GET_ROWS</span><span style="font-family:Courier New;font-size:x-small;">())  AS T@</span><span style="font-family:&quot;"><span style="font-size:x-small;"></p>
<p>Test_Id       Test_Desc<br />
&#8212;&#8212;-       &#8212;&#8212;&#8212;<br />
1             TEST<br />
2             ATTRIBUTES<br />
3             BUFFERPOOLDBPARTITIONS<br />
4             BUFFERPOOLNODES<br />
5             BUFFERPOOLS </span></span></p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/decipherinfosys.wordpress.com/1346/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/decipherinfosys.wordpress.com/1346/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/decipherinfosys.wordpress.com/1346/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/decipherinfosys.wordpress.com/1346/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/decipherinfosys.wordpress.com/1346/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/decipherinfosys.wordpress.com/1346/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/decipherinfosys.wordpress.com/1346/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/decipherinfosys.wordpress.com/1346/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/decipherinfosys.wordpress.com/1346/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/decipherinfosys.wordpress.com/1346/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=decipherinfosys.wordpress.com&blog=691282&post=1346&subd=decipherinfosys&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://decipherinfosys.wordpress.com/2008/10/27/returning-a-record-set-from-a-function-in-oracle-sql-server-and-db2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0409e90c82255ecb867b436a97e4f779?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">decipherinfosys</media:title>
		</media:content>
	</item>
		<item>
		<title>Generating XSD from a XML file</title>
		<link>http://decipherinfosys.wordpress.com/2008/10/14/generating-xsd-from-a-xml-file/</link>
		<comments>http://decipherinfosys.wordpress.com/2008/10/14/generating-xsd-from-a-xml-file/#comments</comments>
		<pubDate>Tue, 14 Oct 2008 10:58:18 +0000</pubDate>
		<dc:creator>decipherinfosys</dc:creator>
				<category><![CDATA[DB2 LUW]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://decipherinfosys.wordpress.com/?p=1323</guid>
		<description><![CDATA[When working with XML data, we have a need to have the XSD prepared as well.  It can be used in many ways when doing integration between the systems &#8211; first and foremost, both the parties involved in the integration need the XSD to get an idea of the schema, secondly, one can then [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=decipherinfosys.wordpress.com&blog=691282&post=1323&subd=decipherinfosys&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>When working with XML data, we have a need to have the XSD prepared as well.  It can be used in many ways when doing integration between the systems &#8211; first and foremost, both the parties involved in the integration need the XSD to get an idea of the schema, secondly, one can then enforce the <a href="http://decipherinfosys.wordpress.com/2007/09/09/typed-vs-untyped-xml/">XML schema collection</a> at their end to ensure that the schema that they are getting is proper &#8211; this prevents any surprises down the road when we are processing the data.</p>
<p>Generating a XSD manually is an error prone and a very cumbersome process.  There are a lot of tools out there that allow you to do so in a graphical user interface.  MSFT also has a utility which is called XSD.exe: XML Schema Definition Tool.  It can be used for quite a few operations:</p>
<p>a) XML to XSD which is what we are discussing in this post,</p>
<p>b) XDR to XSD: I doubt that people use it for this functionality though,</p>
<p>c) XSD to Classes: To generate runtime classes from XSD schema file,</p>
<p>d) Classes to XSD: The reverse of the above, and</p>
<p>e) XSD to DataSet: This generates the common language runtime DataSet classes from an XSD schema file.</p>
<p>You can read more on XSD.exe from this MSDN post <a href="http://msdn.microsoft.com/en-us/library/x6c1kb0s(VS.80).aspx">here</a>.  If you look at yesterday&#8217;s post in which we provided a sample of the XML file, we can use XSD.exe on it to generate a XSD for us. <em> </em></p>
<p><em>C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin&gt;xsd.exe C:\IF_XML.xml<br />
Microsoft (R) Xml Schemas/DataTypes support utility<br />
[Microsoft (R) .NET Framework, Version 2.0.50727.42]<br />
Copyright (C) Microsoft Corporation. All rights reserved.<br />
Writing file &#8216;C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\IF_XML.xsd</em></p>
<p>I could have specified an output directory as well to get the output in a different location.  If you just do xsd.exe /?  you will get all the supported flag options.  The generated file looks like <a href="http://www.decipherinfosys.com/XML_SAMPLE.xsd">this</a>.  And there is a GUI version of this utility as well which is called VisualXSD &#8211; pretty self explanatory &#8211; see the screenshot below:</p>
<p><a href="http://decipherinfosys.files.wordpress.com/2008/10/xml_sample.jpg"><img class="alignnone size-thumbnail wp-image-1326" title="xml_sample" src="http://decipherinfosys.files.wordpress.com/2008/10/xml_sample.jpg?w=104&#038;h=96" alt="" width="104" height="96" /></a></p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/decipherinfosys.wordpress.com/1323/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/decipherinfosys.wordpress.com/1323/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/decipherinfosys.wordpress.com/1323/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/decipherinfosys.wordpress.com/1323/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/decipherinfosys.wordpress.com/1323/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/decipherinfosys.wordpress.com/1323/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/decipherinfosys.wordpress.com/1323/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/decipherinfosys.wordpress.com/1323/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/decipherinfosys.wordpress.com/1323/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/decipherinfosys.wordpress.com/1323/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=decipherinfosys.wordpress.com&blog=691282&post=1323&subd=decipherinfosys&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://decipherinfosys.wordpress.com/2008/10/14/generating-xsd-from-a-xml-file/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0409e90c82255ecb867b436a97e4f779?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">decipherinfosys</media:title>
		</media:content>

		<media:content url="http://decipherinfosys.files.wordpress.com/2008/10/xml_sample.jpg?w=104" medium="image">
			<media:title type="html">xml_sample</media:title>
		</media:content>
	</item>
	</channel>
</rss>