<?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>techs@work</title>
	<atom:link href="http://techsatwork.com/blog/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://techsatwork.com/blog</link>
	<description>informing technology....</description>
	<lastBuildDate>Wed, 20 Feb 2013 15:01:43 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>Checking on HADR</title>
		<link>http://techsatwork.com/blog/?p=1409</link>
		<comments>http://techsatwork.com/blog/?p=1409#comments</comments>
		<pubDate>Wed, 20 Feb 2013 15:01:43 +0000</pubDate>
		<dc:creator>raju</dc:creator>
				<category><![CDATA[database]]></category>
		<category><![CDATA[db2]]></category>
		<category><![CDATA[how to]]></category>
		<category><![CDATA[check hadr]]></category>
		<category><![CDATA[db2 hadr]]></category>
		<category><![CDATA[db2 high availability]]></category>
		<category><![CDATA[db2pd]]></category>
		<category><![CDATA[hadr]]></category>
		<category><![CDATA[hadr status]]></category>

		<guid isPermaLink="false">http://techsatwork.com/blog/?p=1409</guid>
		<description><![CDATA[<p>By now I am sure lot of db2 users have adopted DB2 HADR as one of their high availability solution.  IBM has matured HADR over the last two versions and its becoming more and more robust.  Couple of years ago &#8230; <a href="http://techsatwork.com/blog/?p=1409">Continue reading <span class="meta-nav">&#8594;</span></a></p><p>The post <a href="http://techsatwork.com/blog/?p=1409">Checking on HADR</a> appeared first on <a href="http://techsatwork.com/blog">techs@work</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>By now I am sure lot of db2 users have adopted DB2 HADR as one of their high availability solution.  IBM has matured HADR over the last two versions and its becoming more and more robust.  Couple of years ago I had written an article on <a href="http://techsatwork.com/blog/?p=1033" target="_blank">how to setup HADR</a> which I know many of you used. The instruction hasn&#8217;t changed over the versions, but several of you have recently asked me for a script to check HADR status. Here is a simple script that will check on HADR status on each database on the instance and email the status.</p>
<p>As always verify the script  before you implement it in your system. You can download the script here : <a href="http://techsatwork.com/blog/wp-content/uploads/2013/02/hadr_checker.sh_.txt">hadr_checker.sh</a></p>
<p>Please feel free to comment on the script and ways to improve it.</p>
<p>&nbsp;</p>
<p>The post <a href="http://techsatwork.com/blog/?p=1409">Checking on HADR</a> appeared first on <a href="http://techsatwork.com/blog">techs@work</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://techsatwork.com/blog/?feed=rss2&#038;p=1409</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>A quick overview of DB2&#8242;s INGEST</title>
		<link>http://techsatwork.com/blog/?p=1388</link>
		<comments>http://techsatwork.com/blog/?p=1388#comments</comments>
		<pubDate>Thu, 31 Jan 2013 03:15:50 +0000</pubDate>
		<dc:creator>rpillai</dc:creator>
				<category><![CDATA[database]]></category>
		<category><![CDATA[db2]]></category>
		<category><![CDATA[how to]]></category>
		<category><![CDATA[unix]]></category>
		<category><![CDATA[data load]]></category>
		<category><![CDATA[db2 import]]></category>
		<category><![CDATA[DB2 INGEST]]></category>
		<category><![CDATA[db2 load]]></category>
		<category><![CDATA[db2 v10 features]]></category>
		<category><![CDATA[ETL]]></category>
		<category><![CDATA[high performance data load]]></category>
		<category><![CDATA[high performance load]]></category>
		<category><![CDATA[import]]></category>
		<category><![CDATA[INGEST]]></category>
		<category><![CDATA[load data with high availability]]></category>
		<category><![CDATA[loading high volume of data]]></category>
		<category><![CDATA[mass data insert]]></category>
		<category><![CDATA[restart]]></category>

		<guid isPermaLink="false">http://techsatwork.com/blog/?p=1388</guid>
		<description><![CDATA[<p>As a DB2 DBA or as data integrator we all face a challenge in loading large amount of data into DB2 database while up keeping the 24&#215;7 availability of the tables.  Traditionally we use LOAD or sometimes IMPORT while loading &#8230; <a href="http://techsatwork.com/blog/?p=1388">Continue reading <span class="meta-nav">&#8594;</span></a></p><p>The post <a href="http://techsatwork.com/blog/?p=1388">A quick overview of DB2&#8242;s INGEST</a> appeared first on <a href="http://techsatwork.com/blog">techs@work</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>As a DB2 DBA or as data integrator we all face a challenge in loading large amount of data into DB2 database while up keeping the 24&#215;7 availability of the tables.  Traditionally we use LOAD or sometimes IMPORT while loading large amount of data to tables. Either of them has data concurrency and availability issue. While INSERTS gives the highest availability, it can be painfully slow when inserting millions of rows.</p>
<p><span style="color: #99cc00;"><em>Brief Intro</em><em> :</em></span></p>
<p>INGEST from DB2 10 is fast and it enables us to continuously  load  data while giving high availability and recoverability. INGEST is a cross between LOAD and IMPORT. INGEST is optimized to be multithread to process data in parallel.  Unlike LOAD and IMPORT,  INGEST can run continuously reading a data stream through a pipe. This is great, if you are loading live feeds of data from a social media stream or from your  production stream.  Another feature of INGEST is, it can read multiple files as its source to load the data. Apart from the traditional INSERT statement, it can do UPDATE, MERGE and DELETE. This comes in handy if the data you are loading  contain  updates to existing rows .</p>
<p><span style="color: #99cc00;"><em>How does it work ?</em></span></p>
<p>INGEST has three threads/parts :</p>
<p>1. Transporter :  This thread reads from the input files or data stream pipe s in parallel and sets the thread to formatter. DB2 spawns one thread for each input files.</p>
<p>2. Formatter: Formatter threads formats and prepares the data to be send to Flusher. Formatter threads make sure the data is set in such a way that INGEST can insert into DB2 in parallel. The number of formatter threads is specified by the num_formatters configuration parameter.</p>
<p>3. Flusher:  Flusher threads insert the data into the DB2 table. If you are using INGEST to load into a partitioned database, then a flusher thread is associated with each partition.  There could be multiple flushers running to increase the throughput of the data ingest. The number of flushers for each partition is specified by the num_flushers_per_partition configuration parameter.</p>
<p>Like I said its completely designed to be run efficiently and give high availability.</p>
<p><span style="color: #99cc00;"><em>Can it recover from a failure ?</em></span></p>
<p>Absolutely ! INGEST is capable of restarting from where it failed. It literally uses INSERT statements to load the data. With INGEST, you can specify dumpfile to place any rejected rows due to formatting error or invalid character, exception table to place any rows with constraint violations, warning counts to stop if the threshold is met.  You can also specify commit count in rows or by time. This comes in handy when loading data continuously from a stream. If the INGEST utility gets aborted for any reasons (power failure or somebody accidentally killing the thread, you can restart the INGEST with RESTART option and DB2 will resume the INGEST from the last commit point. If do not want to restart INGEST you can issue the RESTART TERMINATE and DB2 will clean up the failed INGEST. Unlike with the TERMINATE parameter of the LOAD command, data already committed by the failed INGEST command is not removed from the table.</p>
<p><span style="color: #99cc00;"><em>What all format can it handle ?</em></span></p>
<p>INGEST utlitiy  supports the following input data formats:</p>
<p>Delimited text<br />
Positional text and binary<br />
Columns in various orders and formats</p>
<p><span style="color: #99cc00;"><em>How about performance ?</em></span></p>
<p>Obviously this is one of the most sacred part for the DBA when choosing the option to load lot of data.  The best performance is always LOAD, but it doesn&#8217;t give high availability. INGEST even though under the covers issues INSERTS, I have noticed that when loading hundred thousands of rows INGEST was able to perform 40% faster than traditional INSERT. The reason why I compared to INSERT, is because its the only option that gives me high availability.</p>
<p><span style="color: #99cc00;"><em>How is it run ?</em></span></p>
<p>Assume we have a coma delimited customer file as follows that needs to be loaded :</p>
<p>10001,&#8221;Edward&#8221;,&#8221;Williams&#8221;,&#8221;12349 West Ave St&#8221;,&#8221;Taos&#8221;,&#8221;NM&#8221;,&#8221;564-573-4839&#8243;<br />
10002,&#8221;James&#8221;,&#8221;Miller&#8221;,&#8221;43348 Knight St&#8221;,&#8221;Dumont&#8221;,&#8221;NJ&#8221;,&#8221;201-873-4239&#8243;<br />
10003,&#8221;Jessica&#8221;,&#8221;Robertson&#8221;,&#8221;489 River N Rd&#8221;,&#8221;Austin&#8221;,&#8221;TX&#8221;,&#8221;512-534-9859&#8243;<br />
:      :     :    :    :   :   :    :    :   :    :   :      :     :    :    :   :   :    :    :   :    :  :      :     :    :<br />
90000,&#8221;Kathy&#8221;,&#8221;Rodriguez&#8221;,&#8221;8293 Brooksheild Apt, # 201&#8243;,&#8221;Anahiem&#8221;,&#8221;CA&#8221;,&#8221;714-354-775</p>
<p>The customer table is :<br />
CNumber   INT          &#8212;&gt; primary key<br />
FName       varchar(50)<br />
LName       varchar(50)<br />
Street         varchar(100)<br />
City             varchar(50)<br />
State           char(2)<br />
Telephone  char(12)</p>
<p>Lets see our options to INGEST the data:</p>
<p>This is the simplest form :<br />
<span style="color: #ff9900;">ingest from file customer.del format delimited insert into raju.customer;</span></p>
<p>If you want to have more control or if the data is in different order than the table column, then you can do this . Note here I have flipped the firstname and lastname on the VALUES:</p>
<p><span style="color: #ff9900;">ingest from file customer.del format delimited</span><br />
<span style="color: #ff9900;"> ($cid integer external</span><br />
<span style="color: #ff9900;"> ,$firstname char(50)</span><br />
<span style="color: #ff9900;"> ,$lastname char(50)</span><br />
<span style="color: #ff9900;"> ,$streetname char(100)</span><br />
<span style="color: #ff9900;"> ,$cityname char(50)</span><br />
<span style="color: #ff9900;"> ,$statename char(2)</span><br />
<span style="color: #ff9900;"> ,$telephone char(12)</span><br />
<span style="color: #ff9900;"> )</span><br />
<span style="color: #ff9900;"> dumpfile customer_dump.del</span><br />
<span style="color: #ff9900;"> exception table raju.customerexcept</span><br />
<span style="color: #ff9900;"> warningcount 100</span><br />
<span style="color: #ff9900;"> messages ingest_customer.msg</span><br />
<span style="color: #ff9900;"> insert into raju.customer(cnumber,fname,lname,street,city,state,telephone)</span><br />
<span style="color: #ff9900;"> values($cid,</span><strong>$lastname,$firstname</strong><span style="color: #ff9900;">,$streetname,$cityname,$statename,$telephone);</span></p>
<p>The exception table should be in place before you run this. You can create the table with :<br />
create table raju.customerexcept like raju.customer  or run the same ddl you used for the customer table.</p>
<p>If your data contains updates to existing rows as well as new rows, you can use MERGE statement on your INGEST :</p>
<p><span style="color: #ff9900;">ingest from file customer_monday.del, customer_tuesday.del format delimited</span><br />
<span style="color: #ff9900;"> ($cid integer external</span><br />
<span style="color: #ff9900;"> ,$firstname char(50)</span><br />
<span style="color: #ff9900;"> ,$lastname char(50)</span><br />
<span style="color: #ff9900;"> ,$streetname char(100)</span><br />
<span style="color: #ff9900;"> ,$cityname char(50)</span><br />
<span style="color: #ff9900;"> ,$statename char(2)</span><br />
<span style="color: #ff9900;"> ,$telephone char(12)</span><br />
<span style="color: #ff9900;"> )</span><br />
<span style="color: #ff9900;"> dumpfile customer_dump.del</span><br />
<span style="color: #ff9900;"> warningcount 100</span><br />
<span style="color: #ff9900;"> messages ingest4.msg</span><br />
<span style="color: #ff9900;"> merge into raju.customer on (cnumber = $cid)</span><br />
<span style="color: #ff9900;"> when not matched then</span><br />
<span style="color: #ff9900;"> insert (cnumber,fname,lname,street,city,state,telephone)</span><br />
<span style="color: #ff9900;"> values($cid,$firstname,$lastname,$streetname,$cityname,$statename,$telephone)</span><br />
<span style="color: #ff9900;"> when matched then</span><br />
<span style="color: #ff9900;"> update set (fname,lname,street,city,state,telephone) =</span><br />
<span style="color: #ff9900;"> ($firstname,$lastname,$streetname,$cityname,$statename,$telephone);</span></p>
<p>Note that in the above example, I have two input files.  I have also removed the exception table. DB2 does not allow to use exception table option when using MERGE option. Don&#8217;t ask me why they don&#8217;t allow ?</p>
<p>If you have a list of rows that you want to delete, then you can do as well :</p>
<p><span style="color: #ff9900;">ingest from file customer1.del format delimited</span><br />
<span style="color: #ff9900;"> ($cid integer external</span><br />
<span style="color: #ff9900;"> ,$firstname char(50)</span><br />
<span style="color: #ff9900;"> ,$lastname char(50)</span><br />
<span style="color: #ff9900;"> ,$streetname char(100)</span><br />
<span style="color: #ff9900;"> ,$cityname char(50)</span><br />
<span style="color: #ff9900;"> ,$statename char(2)</span><br />
<span style="color: #ff9900;"> ,$telephone char(12)</span><br />
<span style="color: #ff9900;"> )</span><br />
<span style="color: #ff9900;"> delete from raju.customer</span><br />
<span style="color: #ff9900;"> where cnumber = $cid;</span></p>
<p><span style="color: #99cc00;"><em>How do we restart ?</em></span></p>
<p>You can restart a terminated INGEST with the RESTART CONTINUE &lt;job_id&gt; option</p>
<p>If you want the ability to easily restart a terminated INGEST use the option RESTART NEW &lt;job_id&gt; on your original INGEST command like :</p>
<p><span style="color: #ff9900;">ingest from file customer_monday.del, customer_tuesday.del format delimited</span><br />
<span style="color: #ff9900;"> ($cid integer external</span><br />
<span style="color: #ff9900;"> ,$firstname char(50)</span><br />
<span style="color: #ff9900;"> ,$lastname char(50)</span><br />
<span style="color: #ff9900;"> ,$streetname char(100)</span><br />
<span style="color: #ff9900;"> ,$cityname char(50)</span><br />
<span style="color: #ff9900;"> ,$statename char(2)</span><br />
<span style="color: #ff9900;"> ,$telephone char(12)</span><br />
<span style="color: #ff9900;"> )</span><br />
<span style="color: #ff9900;"> dumpfile customer_dump.del</span><br />
<span style="color: #ff9900;"> warningcount 100</span><br />
<span style="color: #ff9900;"> messages ingest4.msg</span><br />
<span style="color: #ff9900;"> <strong>restart new &#8216;customeringest1&#8242;</strong></span><br />
<span style="color: #ff9900;"> merge into raju.customer on (cnumber = $cid)</span><br />
<span style="color: #ff9900;"> when not matched then</span><br />
<span style="color: #ff9900;"> insert (cnumber,fname,lname,street,city,state,telephone)</span><br />
<span style="color: #ff9900;"> values($cid,$firstname,$lastname,$streetname,$cityname,$statename,$telephone)</span><br />
<span style="color: #ff9900;"> when matched then</span><br />
<span style="color: #ff9900;"> update set (fname,lname,street,city,state,telephone) =</span><br />
<span style="color: #ff9900;"> ($firstname,$lastname,$streetname,$cityname,$statename,$telephone);</span></p>
<p>The RESTART NEW option will help you identify the ingest command that got terminated. Once you identify the ingest that got terminated, you can restart it by issuing RESTART CONTINUE</p>
<p><span style="color: #ff9900;">ingest from file customer_monday.del, customer_tuesday.del format delimited</span><br />
<span style="color: #ff9900;"> ($cid integer external</span><br />
<span style="color: #ff9900;"> ,$firstname char(50)</span><br />
<span style="color: #ff9900;"> ,$lastname char(50)</span><br />
<span style="color: #ff9900;"> ,$streetname char(100)</span><br />
<span style="color: #ff9900;"> ,$cityname char(50)</span><br />
<span style="color: #ff9900;"> ,$statename char(2)</span><br />
<span style="color: #ff9900;"> ,$telephone char(12)</span><br />
<span style="color: #ff9900;"> )</span><br />
<span style="color: #ff9900;"> dumpfile customer_dump.del</span><br />
<span style="color: #ff9900;"> warningcount 100</span><br />
<span style="color: #ff9900;"> messages ingest4.msg</span><br />
<span style="color: #ff9900;"> <strong>restart continue &#8216;customeringest1&#8242;</strong></span><br />
<span style="color: #ff9900;"> merge into raju.customer on (cnumber = $cid)</span><br />
<span style="color: #ff9900;"> when not matched then</span><br />
<span style="color: #ff9900;"> insert (cnumber,fname,lname,street,city,state,telephone)</span><br />
<span style="color: #ff9900;"> values($cid,$firstname,$lastname,$streetname,$cityname,$statename,$telephone)</span><br />
<span style="color: #ff9900;"> when matched then</span><br />
<span style="color: #ff9900;"> update set (fname,lname,street,city,state,telephone) =</span><br />
<span style="color: #ff9900;"> ($firstname,$lastname,$streetname,$cityname,$statename,$telephone);</span></p>
<p>The RESTART CONTINUE option will enable us to restart INGEST from the last commit point.</p>
<p>If you want to terminate the utility and want to clean up from the previously failed run, then you can use  RESTART TERMINATE &lt;job_id&gt; option just like the RESTART CONTINUE option.</p>
<p><span style="color: #99cc00;"><em>How can I monitor the utility ?</em></span></p>
<p>There are few ways to watch what INGEST utility is doing .  IBM has provided few options:</p>
<p>1. <span style="color: #ff9900;">INGEST GET STATS</span><br />
2.<span style="color: #ff9900;"> INGEST LIST</span> or<br />
3 you can query <span style="color: #ff9900;">TABLE(MON_GET_CONNECTION(NULL,NULL))</span> and look for the application_name DB2_INGEST</p>
<p><span style="color: #99cc00;"><em>Conclusion</em></span></p>
<p>While INGEST has a lot of room for improvement, its a great utility to have when compared to other options. Its easy to use and keeps up the availability while inserting large amount of data. I also like the fact that we can use it to delete rows for a list of values.  I hate to use large IN clause in my delete statements or have to load the key into a temporary table scenario. Few limitation with INGEST you need to aware of , currently INGEST do now allow LOBs, XML, structured types, has lot of restrictions on generated columns. I definitely recommend anyone to try out the INGEST utility and see how you can benefit from it. After all you paid for the product, so the least you can do is try it. Trust me if you use it right, you will love it !</p>
<p>&nbsp;</p>
<p>The post <a href="http://techsatwork.com/blog/?p=1388">A quick overview of DB2&#8242;s INGEST</a> appeared first on <a href="http://techsatwork.com/blog">techs@work</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://techsatwork.com/blog/?feed=rss2&#038;p=1388</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Happy New Year !</title>
		<link>http://techsatwork.com/blog/?p=1383</link>
		<comments>http://techsatwork.com/blog/?p=1383#comments</comments>
		<pubDate>Mon, 31 Dec 2012 21:57:11 +0000</pubDate>
		<dc:creator>rpillai</dc:creator>
				<category><![CDATA[db2]]></category>

		<guid isPermaLink="false">http://techsatwork.com/blog/?p=1383</guid>
		<description><![CDATA[<p>To all my readers&#8230; Wish y&#8217;all a Very Happy New Year !</p><p>The post <a href="http://techsatwork.com/blog/?p=1383">Happy New Year !</a> appeared first on <a href="http://techsatwork.com/blog">techs@work</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>To all my readers&#8230; Wish y&#8217;all a <span style="color: #99cc00;">Very</span> <span style="color: #ff9900;">Happy <span style="color: #99cc00;">New</span> Year</span> <span style="color: #99cc00;">!</span></p>
<p>The post <a href="http://techsatwork.com/blog/?p=1383">Happy New Year !</a> appeared first on <a href="http://techsatwork.com/blog">techs@work</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://techsatwork.com/blog/?feed=rss2&#038;p=1383</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>DB2 V10 Adaptive Compression</title>
		<link>http://techsatwork.com/blog/?p=1364</link>
		<comments>http://techsatwork.com/blog/?p=1364#comments</comments>
		<pubDate>Wed, 19 Dec 2012 23:00:21 +0000</pubDate>
		<dc:creator>rpillai</dc:creator>
				<category><![CDATA[db2]]></category>
		<category><![CDATA[how to]]></category>
		<category><![CDATA[adaptive compression]]></category>
		<category><![CDATA[adc]]></category>
		<category><![CDATA[admintabinfo]]></category>
		<category><![CDATA[admin_get_index_compress_info]]></category>
		<category><![CDATA[admin_get_tab_compress_info]]></category>
		<category><![CDATA[admin_get_tab_info]]></category>
		<category><![CDATA[automatic dictionary creation]]></category>
		<category><![CDATA[classic compression]]></category>
		<category><![CDATA[compress yes]]></category>
		<category><![CDATA[database compression]]></category>
		<category><![CDATA[db2 compression]]></category>
		<category><![CDATA[db2 performance]]></category>
		<category><![CDATA[db2 tuning]]></category>
		<category><![CDATA[db2 udb]]></category>
		<category><![CDATA[db2 v10 compression]]></category>
		<category><![CDATA[deep compression]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[resetdictionary]]></category>
		<category><![CDATA[row compression]]></category>

		<guid isPermaLink="false">http://techsatwork.com/blog/?p=1364</guid>
		<description><![CDATA[<p>Last February, I wrote about DB2&#8242;s compression.  If that was McLaren, with DB2 V9.7&#8242;s compression, IBM upgraded to Lamborghini Aventador. Apparently IBM&#8217;s thirst didn&#8217;t stop there, they went one more step ahead and got the Bugatti Veyron with DB2 V10&#8242;s &#8230; <a href="http://techsatwork.com/blog/?p=1364">Continue reading <span class="meta-nav">&#8594;</span></a></p><p>The post <a href="http://techsatwork.com/blog/?p=1364">DB2 V10 Adaptive Compression</a> appeared first on <a href="http://techsatwork.com/blog">techs@work</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>Last February, I wrote about <a href="http://techsatwork.com/blog/?p=980" target="_blank">DB2&#8242;s compression</a>.  If that was McLaren, with DB2 V9.7&#8242;s compression, IBM upgraded to Lamborghini Aventador. Apparently IBM&#8217;s thirst didn&#8217;t stop there, they went one more step ahead and got the Bugatti Veyron with DB2 V10&#8242;s adaptive compression.  If you didn&#8217;t like the analogy, then I will put it in simple terms &#8211; DB2 V10 adaptive compression is compression on steroids.</p>
<p>On V9.5, I have noticed around 70% compression, with V9.7, it slightly increased to 75% compression. But then V9.7 was able to compress the indexes as well.  Galileo (a.k.a V10) adds some more juice to this, it now has adaptive compression.</p>
<p>So what is adaptive compression ?  Prior to V10, IBM used global pattern replacement algorithm. So if the value is found on the global dictionary its compressed. But with adaptive compression, besides compressing based on global pattern, DB2 will now look within a data page to see if there are further compression opportunities by finding locally repeating patterns within a data page. This increased the chance of compressing the data exponentially.  I have seen compression ratio of 85 % on certain tables.</p>
<p>I am not going to explain how the wheels move and turns and all that stuff. Most of us don&#8217;t need to know how the algorithm works.  So I am just going to show you how to use it and reap the benefit. After all thats what most of us are after. If you need to know how the algorithm works, I am sure there are many sites that explain it.</p>
<p>First of all  in order to use the compression feature you need to have the license for Storage Optimization or have AESE license. You can do that by doing a <span style="color: #ff6600;">db2licm -l</span> and see if the storage optimization is licensed or you have a AESE edition.</p>
<p>Let&#8217;s get started and rev up the engine:</p>
<p>1. If you are migrating from previous version of DB2 and /or want to see if you are already compressing tables :</p>
<address><span style="color: #ff9900; font-size: medium;">SELECT SUBSTR(CREATOR, 1, 10) AS TABSCHEMA,</span><br />
<span style="color: #ff9900; font-size: medium;"> SUBSTR(NAME, 1, 30) AS TABNAME,</span><br />
<span style="color: #ff9900; font-size: medium;"> COMPRESSION, ROWCOMPMODE</span><br />
<span style="color: #ff9900; font-size: medium;"> FROM SYSIBM.TABLES</span><br />
<span style="color: #ff9900; font-size: medium;"> WHERE CREATOR NOT LIKE &#8216;SYS%&#8217;;</span></address>
<address> </address>
<p>2. To find out how much you will save by compressing in DB2 V10 use the below SQL. Run against the schema you want to evaluate. The currently_pct_pagessaved will show you how many percent of pages are saved currently by compression (if any), the classic_pct_pagessaved shows you how many percent of pages will be saved with classic compression under V10 and the adaptive_pct_pagessaved show you how many percent of pages will be saved with adaptive compression. The storagesize_MB shows you how large the table is :</p>
<address><span style="font-family: sans-serif; font-size: small;"><span style="color: #ff9900; font-size: medium;">select tc.TABSCHEMA,tc.TABNAME, tc.ROWCOMPMODE ,</span><br />
<span style="color: #ff9900; font-size: medium;"> sum(tc.PCTPAGESSAVED_CURRENT) as CURRENTLY_PCTPAGESSAVED ,</span><br />
<span style="color: #ff9900; font-size: medium;"> sum(tc.PCTPAGESSAVED_STATIC) as CLASSIC_PCT_PAGESSAVED,</span><br />
<span style="color: #ff9900; font-size: medium;"> sum(tc.PCTPAGESSAVED_ADAPTIVE)as ADPATIVE_PCT_PAGESAVED,</span><br />
<span style="color: #ff9900; font-size: medium;"> SUM(TI.DATA_OBJECT_P_SIZE)/1024 AS STORAGESIZE_MB</span><br />
<span style="color: #ff9900; font-size: medium;"> from table(sysproc.admin_get_tab_compress_info(&#8216;RAJU&#8217;,&#8221;)) TC</span><br />
<span style="color: #ff9900; font-size: medium;"> join TABLE (sysproc.admin_get_tab_info(&#8216;RAJU&#8217;, &#8221;)) TI</span><br />
<span style="color: #ff9900; font-size: medium;"> ON TC.TABSCHEMA = TI.TABSCHEMA AND TC.TABNAME = TI.TABNAME</span><br />
<span style="color: #ff9900; font-size: medium;"> group by tc.TABSCHEMA,tc.TABNAME, tc.ROWCOMPMODE</span><br />
<span style="color: #ff9900; font-size: medium;"> order by 7 desc;</span><br />
</span></address>
<p>3. Starting from DB2 V9.7 you can compress index as well. Run the following sql to find out how much compression you will get on indexes :</p>
<address><span style="font-family: sans-serif; font-size: medium; color: #ff9900;">SELECT INDSCHEMA, INDNAME,TABNAME, index_compressed,</span><br />
<span style="font-family: sans-serif; font-size: medium; color: #ff9900;">       pct_pages_saved, num_leaf_pages_saved </span><br />
<span style="font-family: sans-serif; font-size: medium; color: #ff9900;">     FROM TABLE(sysproc.admin_get_index_compress_info(&#8216;T&#8217;, &#8216;RAJU&#8217;, &#8221;, NULL, NULL));</span></address>
<p>&nbsp;</p>
<p>Now you have the data to take a informed decision. As I mentioned on my <a href="http://techsatwork.com/blog/?p=980" target="_blank">previous article on compression</a> , use due diligence before selecting the tables you want to compress.  Generally tables with a read/write ratio of 70 percent or more reads and 30 percent or less writes are good candidates for compression.  If the table gets lot of updates, then you lose cpu cycles on db2 uncompressing and compressing data.   Row compression is a great feature for DSS based systems, where there is lot of data and has more reads than updates.  Row compression performs best in I/O or memory-bound environments where the bottleneck is not on the CPU. Extra CPU cycles are required to perform row compression and expansion of data rows whenever they are accessed or modified. However this overhead can be offset by efficiencies that are gained in doing fewer I/O operations.</p>
<p>Similarly, index compression is another awesome feature , but not all indexes will benefit from compression. Best candidates for index compression are indices with multi column, columns with character data, varchar columns, columns with low cardinality.</p>
<p>4. Once you determine what tables and index to compress , you now need to turn on compression  :</p>
<address><span style="font-size: small;">  <span style="font-size: medium;"> <span style="color: #ff9900;">alter table raju.orders_history compress yes;</span></span></span><br />
<span style="color: #ff9900; font-size: medium;">    alter index raju.orderhist_lkp1 compress yes;</span></address>
<p>5. Now that you have altered the objects to turn on compression you can either wait for the dictionary to get build automatically by ADC or run one of utilities that will build the dictionary, I recommend you running a reorg if you can :</p>
<address><span style="color: #ff9900; font-size: medium;"> reorg table raju.orders_history index raju.orderhist_lkp2 resetdictionary;</span><br />
<span style="color: #ff9900; font-size: medium;">  reorg indexes for all table raju.orders_history;</span></address>
<p>6. Run the query from step 2 and 3 and see how much space you have saved. Prepared to be amazed.</p>
<p>As always, make sure you get some metrics before and after compressing the tables. Saving storage is great, but whats even more great is saving system resources.  I have noticed I/O wait time go down by 80% in certain cases and logical reads going high because now DB2 can fit more rows in the buffer pools.  CPU cycle does go a bit high,but overall its lower than before because of less I/O operations.</p>
<p>They say a picture says a thousand words.  The below graph shows my % I/O wait before and after I turned on adaptive compression:</p>
<p><a href="http://techsatwork.com/blog/wp-content/uploads/2012/12/adaptivecompression.jpg"><img class="alignnone size-full wp-image-1377" title="adaptivecompression" src="http://techsatwork.com/blog/wp-content/uploads/2012/12/adaptivecompression.jpg" alt="" width="922" height="317" /></a></p>
<p>You can see how much it has gone down and in some cases it has gone away.  Now do you see why I say its the Bugatti Veyron ! If you haven&#8217;t looked into compression, I strongly suggest your try it out.</p>
<p>As always the above is my opinion and I strongly urge you to test it out in your environment to see what benefits you get. I am sure you won&#8217;t be disappointed.</p>
<p>The post <a href="http://techsatwork.com/blog/?p=1364">DB2 V10 Adaptive Compression</a> appeared first on <a href="http://techsatwork.com/blog">techs@work</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://techsatwork.com/blog/?feed=rss2&#038;p=1364</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ADMIN_MOVE_TABLE</title>
		<link>http://techsatwork.com/blog/?p=1344</link>
		<comments>http://techsatwork.com/blog/?p=1344#comments</comments>
		<pubDate>Sun, 28 Oct 2012 20:59:00 +0000</pubDate>
		<dc:creator>rpillai</dc:creator>
				<category><![CDATA[database]]></category>
		<category><![CDATA[db2]]></category>
		<category><![CDATA[how to]]></category>
		<category><![CDATA[ADMIN_MOVE_TABLE]]></category>
		<category><![CDATA[data movement]]></category>
		<category><![CDATA[db2 move table]]></category>
		<category><![CDATA[moving a table in db2]]></category>
		<category><![CDATA[moving db2 table using stored procedure]]></category>
		<category><![CDATA[moving table from one tablespace to another.]]></category>
		<category><![CDATA[SYSPROC]]></category>

		<guid isPermaLink="false">http://techsatwork.com/blog/?p=1344</guid>
		<description><![CDATA[<p>Have you ever had to move a table from one tablespace to another ?  If you haven&#8217;t then you haven&#8217;t been working with lot of large tables. Ask a dba who supports SAP, Siebel or PeopleSoft database.  Traditionally when a &#8230; <a href="http://techsatwork.com/blog/?p=1344">Continue reading <span class="meta-nav">&#8594;</span></a></p><p>The post <a href="http://techsatwork.com/blog/?p=1344">ADMIN_MOVE_TABLE</a> appeared first on <a href="http://techsatwork.com/blog">techs@work</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>Have you ever had to move a table from one tablespace to another ?  If you haven&#8217;t then you haven&#8217;t been working with lot of large tables. Ask a dba who supports SAP, Siebel or PeopleSoft database.  Traditionally when a DBA has to move a table from one tablespace to another there are several steps he or she needs to take, like unloading the table, reverse engineer the objects and dependencies  , drop and recreate the objects and dependencies, load the data. While you do all that the table needs to be offline.  But what if its a 24&#215;7 table and you cannot afford any downtime.  You might say there are other options and  yes there are and one such option (easy) is using the stored procedure <a href="http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.sql.rtn.doc/doc/r0055069.html" target="_blank">SYSPROC.ADMIN_MOVE_TABLE</a>.  This stored procedure came with DB2 V9.7 and can move a table from one tablespace to another while the table is online . It can also handle moving a range partition to a different tablespaces, change column type while you copy,  remove columns, create MDC tables and so on.  The key point here is , the table is ONLINE while you do all this and its completely recoverable.<br />
Now this comes with a caveat, since its recoverable and online, all the activities are logged, the data is moved using a insert..select , so the transaction logs are used.  There is a LOAD option you can specify, but then the table might be locked for a  period of time.</p>
<p>ADMIN_MOVE_TABLE has 5 stages :</p>
<p>1. INIT : During this stage, db2 checks to see if the table move can take place and if the user has the proper authority. If the user passes a target table, db2 creates the table if it doesn&#8217;t exist. DB2 creates a staging table to capture any DML that happens during the copy phase. DB2 also creates 4 triggers to capture any data change activity.</p>
<p>2. COPY :  In this phase, DB2 copies the data from source table to the target table. Cursor Stability is used when DB2 reads the data from the source table.  By default, DB2 inserts the data to the target table using regular INSERT, so transaction logs are used to make the process recoverable.  You can optionally use can load the data using a cursor by specifying NONRECOVERABLE LOAD. But then the table might be locked for a period of time and the process us not recoverable. Its advised to take a backup if a load is used. DB2 created all the indexes and other objects</p>
<p>3. REPLAY :  While the COPY phase is in progress, DB2 records changes to source table to a staging table using the triggers it created in the INIT phase.  Once the COPY phase is complete, DB2 replays or merges all the rows in the staging table to the target table. There might be instances that few rows might still be left pending in the staging table.</p>
<p>4. SWAP : On this phase, DB2 swaps the name of the target table with that of the source table.  In other words the source table is given a new name and the target tables is renamed to the actual table name.  DB2 takes an exclusive lock for a brief period on both the source and target table to ensure that no new data change happens while it completes any rows that is still there on the staging table. Once this is complete,  the old source table is then removed or kept according to the option specified.</p>
<p>5. CLEANUP: DB2 now cleans up all the temporary objects it created for this process. It drops the 4 triggers and the staging table and completes the transaction.</p>
<p>At the end of the process, it writes all the details on the systools.ADMIN_MOVE_TABLE.</p>
<p>SYNTAX:  There are essentially two methods to use ADMIN_MOVE_TABLE.  The first method allows you to change certain parts of the table definition for the target table. For instance, if you had a table DDL that is quite large , and all you want to do is modify the table spaces for the table, you can do so without having to determine the entire CREATE TABLE statement needed to re-create the source table. All you need to do is to fill out the data_tbsp, index_tbsp, and lob_tbsp parameters, leaving the other optional parameters blank. You can also use this method to add MDC columns, change column types etc.</p>
<p>The second method provides you with more control and flexibility by allowing you to create the target table beforehand, rather than having the stored procedure create the target table. This enables you to create a target table that would not be possible using the first method.</p>
<p>Method # 1:</p>
<pre><a href="http://pic.dhe.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.sql.rtn.doc/doc/r0055069.html#d1919776e102"><img src="http://pic.dhe.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.sql.rtn.doc/c.gif" alt="Skip visual syntax diagram" border="0" /></a>
&gt;&gt;-ADMIN_MOVE_TABLE--(--<em>tabschema</em>--,--<em>tabname</em>--,----------------&gt;

&gt;--<em>data_tbsp</em>--,--<em>index_tbsp</em>--,--<em>lob_tbsp</em>--,--<em>mdc_cols</em>--,--------&gt;

                                             .-,-------.      
                                             V         |      
&gt;--<em>partkey_cols</em>--,--<em>data_part</em>--,--<em>coldef</em>--,----<em>options</em>-+--,-----&gt;

&gt;--<em>operation</em>--)------------------------------------------------&gt;&lt;</pre>
<p><a name="d1919776e102"></a></p>
<p>Method # 2:</p>
<p><img src="http://pic.dhe.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.sql.rtn.doc/c.gif" alt="Read syntax diagram" longdesc="http://pic.dhe.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.sql.rtn.doc/doc/r0055069syn2.html" border="0" /></p>
<pre><a href="http://pic.dhe.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.sql.rtn.doc/doc/r0055069.html#d1919776e170"><img src="http://pic.dhe.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.sql.rtn.doc/c.gif" alt="Skip visual syntax diagram" border="0" /></a>
&gt;&gt;-ADMIN_MOVE_TABLE--(--<em>tabschema</em>--,--<em>tabname</em>--,----------------&gt;

                      .-,-------.                    
                      V         |                    
&gt;--<em>target_tabname</em>--,----<em>options</em>-+--,--<em>operation</em>--)-------------&gt;&lt;</pre>
<p>Here is an example that I used to move ORDERS table to a new tablespaces:</p>
<p>CALL SYSPROC.ADMIN_MOVE_TABLE(<br />
&#8216;RAJU&#8217;,<br />
&#8216;ORDERS&#8217;,<br />
&#8216;ORDERSTBSP&#8217;,<br />
&#8216;ORDERSIDXSP,<br />
&#8216;ORDERSLOBSP&#8217;,<br />
&#8221;,<br />
&#8221;,<br />
&#8221;,<br />
&#8221;,<br />
&#8221;,<br />
&#8216;MOVE&#8217;)</p>
<p>Here is a short video I attempted to show  how it works. In this video, I will demonstrate  how DB2 ADMIN_MOVE_TABLE moves the ORDERS table from a tablespace IBMDB2SAMPLEREL tablespace to USERSPACE1 while a batch insert is running.</p>
<p><iframe src="http://www.youtube.com/embed/afvlPKFm1YY" frameborder="0" width="640" height="480"></iframe></p>
<p>What I am mentioned above is solely my opinion, please do your due diligence before you try this on your system.  Please send me any comments or suggestions on this.</p>
<p>The post <a href="http://techsatwork.com/blog/?p=1344">ADMIN_MOVE_TABLE</a> appeared first on <a href="http://techsatwork.com/blog">techs@work</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://techsatwork.com/blog/?feed=rss2&#038;p=1344</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP &amp; Postgres</title>
		<link>http://techsatwork.com/blog/?p=1337</link>
		<comments>http://techsatwork.com/blog/?p=1337#comments</comments>
		<pubDate>Sun, 28 Oct 2012 03:20:55 +0000</pubDate>
		<dc:creator>rpillai</dc:creator>
				<category><![CDATA[Applications]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[db2]]></category>
		<category><![CDATA[how to]]></category>
		<category><![CDATA[bitmani]]></category>
		<category><![CDATA[connect php to postgres]]></category>
		<category><![CDATA[pg_connect]]></category>
		<category><![CDATA[pg_query]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[php and postgres]]></category>
		<category><![CDATA[php5-pgsql]]></category>
		<category><![CDATA[postgres]]></category>
		<category><![CDATA[psql]]></category>

		<guid isPermaLink="false">http://techsatwork.com/blog/?p=1337</guid>
		<description><![CDATA[<p>I have been using PHP for a while now.  When people say PHP, its usually associated with     MySQL as its backend database. But PHP will work with pretty much any database.  Few years ago I wrote about how &#8230; <a href="http://techsatwork.com/blog/?p=1337">Continue reading <span class="meta-nav">&#8594;</span></a></p><p>The post <a href="http://techsatwork.com/blog/?p=1337">PHP &#038; Postgres</a> appeared first on <a href="http://techsatwork.com/blog">techs@work</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>I have been using PHP for a while now.  When people say PHP, its usually associated with     MySQL as its backend database. But PHP will work with pretty much any database.  Few years ago I wrote about how to get <a href="http://techsatwork.com/blog/?p=145" target="_blank">PHP to work with DB2</a>.   Here I am going to attempt to explain how to configure PHP to work with Postgres.  For those of you not heard of <a href="http://www.postgresql.org" target="_blank">Postgres</a>, its another famous open source database. Its highly scalable and stable. Postgres can run pretty much on any operating systems.  I have been trying to get more familiar with it and potentially write an application that uses Postgres as its backend database.</p>
<p>Here is what you would need to get PHP to work with Postgres:<br />
a. Apache<br />
b. PHP with pgsql option<br />
c. <a href="http://www.postgresql.org/download/" target="_blank">Postgres </a></p>
<p>If you don&#8217;t want to install each of the component by yourself then you can optionally use the <a href="http://bitnami.org/stacks" target="_blank">stack from bitnami.org</a> Install the appropriate stack for your operating system. If you are using Ubuntu (debian), you can do apt-get install php5-pgsql.</p>
<p>Open up the php.ini file and make sure you have the PostgresSQL extensions turned on.  If you are on Linux the install/compile PHP5 with pgsql . With windows you may have to install the pgsql extensions.</p>
<p>Lets get into postgres and create a database , table and insert some data that we can query using php.</p>
<p>Assuming the userid you are on has  postgres libraries in its environments, open a command prompt.<br />
<strong>Create a Database :</strong><br />
<span style="color: #ff9900;">postgres@ubuntu:/home/public_html$ createdb rajudb<br />
</span><br />
<strong>Get to a psql prompt :</strong><br />
<span style="color: #ff9900;">postgres@ubuntu:/home/public_html$ psql</span></p>
<p><span style="color: #99cc00;"> psql (8.4.11)</span><br />
<span style="color: #99cc00;"> Type &#8220;help&#8221; for help.</p>
<p></span><strong>Connect to database rajudb:</strong><br />
<span style="color: #ff9900;">postgres=# \c rajudb</span></p>
<p><span style="color: #99cc00;">psql (8.4.11)</span><br />
<span style="color: #99cc00;"> You are now connected to database &#8220;rajudb&#8221;.<br />
</span><br />
<strong>Create a table called emailaddress:</strong><br />
<span style="color: #ff9900;">rajudb=# create table emailaddress(userid char(4) not null,emailid char(25), primary key(userid));</span><br />
<span style="color: #99cc00;">NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index &#8220;emailaddress_pkey&#8221; for table &#8220;emailaddress&#8221;</span><br />
<span style="color: #99cc00;"> CREATE TABLE</span></p>
<p><strong>Insert data into the table emailaddress that you created earlier:</strong><br />
<span style="color: #ff9900;">rajudb=# insert into emailaddress values(&#8216;A001&#8242;,&#8217;a001@techsatwork.com&#8217;);</span><br />
<span style="color: #99cc00;"> INSERT 0 1</span><br />
<span style="color: #ff9900;"> rajudb=# insert into emailaddress values(&#8216;A002&#8242;,&#8217;a002@techsatwork.com&#8217;);</span><br />
<span style="color: #99cc00;"> INSERT 0 1</span><br />
<span style="color: #ff9900;"> rajudb=# insert into emailaddress values(&#8216;A003&#8242;,&#8217;a003@techsatwork.com&#8217;);</span><br />
<span style="color: #99cc00;"> INSERT 0 1</span></p>
<p><strong>Select data from the table :</strong><br />
<span style="color: #ff9900;">rajudb=# select * from emailaddress;</span><br />
<span style="color: #99cc00;">userid |          emailid</span><br />
<span style="color: #99cc00;"> &#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</span><br />
<span style="color: #99cc00;"> A001   | a001@techsatwork.com</span><br />
<span style="color: #99cc00;"> A002   | a002@techsatwork.com</span><br />
<span style="color: #99cc00;"> A003   | a003@techsatwork.com</span><br />
<span style="color: #99cc00;"> (3 rows)</span></p>
<p>Now lets try to retrieve the same rows using a web browser through a php script. Make sure your apache webserver is running and php is enabled to connect to postgres. Open a text editor and type the following and save it on the web server directory .</p>
<p><span style="color: #ff9900;">&lt;!DOCTYPE html PUBLIC &#8220;-//W3C//DTD HTML 4.01//EN&#8221;&gt;</span><br />
<span style="color: #ff9900;"> &lt;html&gt;</span><br />
<span style="color: #ff9900;"> &lt;head&gt;&lt;/head&gt;</span><br />
<span style="color: #ff9900;"> &lt;body&gt;</span></p>
<p><span style="color: #ff9900;">&lt;?php</span><br />
<span style="color: #ff9900;"> // attempt a connection</span><br />
<span style="color: #ff9900;"> $dbh = pg_connect(&#8220;host=localhost dbname=rajudb user=postgres password=secret!&#8221;);</span><br />
<span style="color: #ff9900;"> if (!$dbh) {</span><br />
<span style="color: #ff9900;"> die(&#8220;Error in connection: &#8221; . pg_last_error());</span><br />
<span style="color: #ff9900;"> }</span></p>
<p><span style="color: #ff9900;">// execute query</span><br />
<span style="color: #ff9900;"> $sql = &#8220;SELECT * FROM emailaddress&#8221;;</span><br />
<span style="color: #ff9900;"> $result = pg_query($dbh, $sql);</span><br />
<span style="color: #ff9900;"> if (!$result) {</span><br />
<span style="color: #ff9900;"> die(&#8220;Error in SQL query: &#8221; . pg_last_error());</span><br />
<span style="color: #ff9900;"> }</span></p>
<p><span style="color: #ff9900;">// iterate over result set</span><br />
<span style="color: #ff9900;"> // print each row</span><br />
<span style="color: #ff9900;"> while ($row = pg_fetch_array($result)) {</span><br />
<span style="color: #ff9900;"> echo &#8220;User Id: &#8221; . $row[0] . &#8220;&lt;br /&gt;&#8221;;</span><br />
<span style="color: #ff9900;"> echo &#8220;Email address: &#8221; . $row[1] . &#8220;&lt;p /&gt;&#8221;;</span><br />
<span style="color: #ff9900;"> }</span></p>
<p><span style="color: #ff9900;">// free memory</span><br />
<span style="color: #ff9900;"> pg_free_result($result);</span></p>
<p><span style="color: #ff9900;">// close connection</span><br />
<span style="color: #ff9900;"> pg_close($dbh);</span><br />
<span style="color: #ff9900;"> ?&gt;</span></p>
<p><span style="color: #ff9900;">&lt;/body&gt;</span><br />
<span style="color: #ff9900;"> &lt;/html&gt;</span></p>
<p><span style="color: #ff9900;"> <span style="color: #000000;">This is one set of pg functions that you can use to interact with postgres using php. To find out about others, refer to the <a href="http://php.net/manual/en/book.pgsql.php" target="_blank">php manuals.</a> </span></span></p>
<p><span style="color: #000000;"><a href="http://bitnami.org/stack/wappstack" target="_blank"><span style="color: #000000;"><br />
</span></a></span></p>
<p>The post <a href="http://techsatwork.com/blog/?p=1337">PHP &#038; Postgres</a> appeared first on <a href="http://techsatwork.com/blog">techs@work</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://techsatwork.com/blog/?feed=rss2&#038;p=1337</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Retrieving data as XML using stored procedure</title>
		<link>http://techsatwork.com/blog/?p=1328</link>
		<comments>http://techsatwork.com/blog/?p=1328#comments</comments>
		<pubDate>Mon, 04 Jun 2012 03:30:11 +0000</pubDate>
		<dc:creator>rpillai</dc:creator>
				<category><![CDATA[database]]></category>
		<category><![CDATA[db2]]></category>
		<category><![CDATA[how to]]></category>
		<category><![CDATA[db2 stored procedure]]></category>
		<category><![CDATA[db2 XML]]></category>
		<category><![CDATA[getting data from db2 in xml]]></category>
		<category><![CDATA[pureXML]]></category>
		<category><![CDATA[querying db2 in xml]]></category>
		<category><![CDATA[retrieve data in xml]]></category>
		<category><![CDATA[stored procedure]]></category>
		<category><![CDATA[XML]]></category>
		<category><![CDATA[xml output]]></category>
		<category><![CDATA[XML query]]></category>
		<category><![CDATA[xml stored procedure]]></category>
		<category><![CDATA[xmlagg]]></category>
		<category><![CDATA[xmlattributes]]></category>
		<category><![CDATA[xmlelement]]></category>
		<category><![CDATA[xmlforest]]></category>
		<category><![CDATA[xquery]]></category>

		<guid isPermaLink="false">http://techsatwork.com/blog/?p=1328</guid>
		<description><![CDATA[<p>On a previous post I showed how to insert parent-child data from an XML document using stored procedure. Well here I am going to show how to retrieve data from a table as an XML document.  Using the table set &#8230; <a href="http://techsatwork.com/blog/?p=1328">Continue reading <span class="meta-nav">&#8594;</span></a></p><p>The post <a href="http://techsatwork.com/blog/?p=1328">Retrieving data as XML using stored procedure</a> appeared first on <a href="http://techsatwork.com/blog">techs@work</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>On a <a href="http://techsatwork.com/blog/?p=1318" target="_blank">previous post</a> I showed how to insert parent-child data from an XML document using stored procedure. Well here I am going to show how to retrieve data from a table as an XML document.  Using the table set of tables from the previous post lets retrieve all the order details for a given customer.  Here is a stored procedure that will take customer_id as an input and then return an xml document that has all the orders and order item that customer has purchased (customer order history) :</p>
<p><span style="color: #ff9900;">CREATE PROCEDURE spRcustomer_order_history</span><br />
<span style="color: #ff9900;">(IN customerid int, OUT customerorders XML)</span><br />
<span style="color: #ff9900;">DYNAMIC RESULT SETS 1</span></p>
<p><span style="color: #ff9900;">P1: BEGIN </span><br />
<span style="color: #ff9900;">declare not_found condition for &#8217;02000&#8242;;</span><br />
<span style="color: #ff9900;">declare exit handler for not_found </span><br />
<span style="color: #ff9900;">   set customerorders = xmlcast(&#8216;NO ROWS FOUND&#8217; as xml);</span></p>
<p><span style="color: #ff9900;">#####################################################</span><br />
<span style="color: #ff9900;"> &#8212; # Returns results in a XML parameter</span><br />
<span style="color: #ff9900;">#####################################################</span></p>
<p><span style="color: #ff9900;">select xmlelement(name &#8220;customerid&#8221; , xmlattributes (o.customer_id),</span><br />
<span style="color: #ff9900;"> xmlagg(</span><br />
<span style="color: #ff9900;"> xmlelement(name &#8220;order_id&#8221;,o.order_id,</span><br />
<span style="color: #ff9900;"> xmlelement(name &#8220;order_timestamp&#8221;,o.order_timestamp),</span><br />
<span style="color: #ff9900;"> ( select </span><br />
<span style="color: #ff9900;"> xmlagg( </span><br />
<span style="color: #ff9900;"> xmlelement(name &#8220;product_id&#8221;, oi.product_id, </span><br />
<span style="color: #ff9900;"> (xmlforest (oi.qty as &#8220;qty&#8221;,</span><br />
<span style="color: #ff9900;"> oi.unit_price as &#8220;unit_price&#8221;,</span><br />
<span style="color: #ff9900;"> oi.product_discount as &#8220;product_discount&#8221;,</span><br />
<span style="color: #ff9900;"> (oi.qty*oi.unit_price-oi.product_discount) as &#8220;total_price&#8221;</span><br />
<span style="color: #ff9900;"> )))) from order_items oi</span><br />
<span style="color: #ff9900;"> where o.order_id = oi.order_id</span><br />
<span style="color: #ff9900;"> )))) into customerorders</span><br />
<span style="color: #ff9900;">FROM orders o</span><br />
<span style="color: #ff9900;">where o.customer_id = customerid</span><br />
<span style="color: #ff9900;"> group by customer_id</span><br />
<span style="color: #ff9900;"> ; </span><br />
<span style="color: #ff9900;">END P1</span><br />
<span style="color: #ff9900;">@</span></p>
<p>Now lets call the stored procedure:<br />
<span style="color: #ff9900;">Call spRcustomer_order_history(13453,?);</span></p>
<p><span style="color: #99cc00;">&lt;customerid CUSTOMER_ID=&#8221;13453&#8243;&gt;</span><br />
<span style="color: #99cc00;">&lt;order_id&gt;1003</span><br />
<span style="color: #99cc00;">&lt;order_timestamp&gt;2012-05-24T21:05:33.552802&lt;/order_timestamp&gt;</span><br />
<span style="color: #99cc00;">&lt;product_id&gt;Z001</span><br />
<span style="color: #99cc00;">&lt;qty&gt;10&lt;/qty&gt;</span><br />
<span style="color: #99cc00;">&lt;unit_price&gt;10.50&lt;/unit_price&gt;</span><br />
<span style="color: #99cc00;">&lt;product_discount&gt;.00&lt;/product_discount&gt;</span><br />
<span style="color: #99cc00;">&lt;total_price&gt;105.00&lt;/total_price&gt;</span><br />
<span style="color: #99cc00;">&lt;/product_id&gt;</span><br />
<span style="color: #99cc00;">&lt;product_id&gt;Z002</span><br />
<span style="color: #99cc00;">&lt;qty&gt;14&lt;/qty&gt;</span><br />
<span style="color: #99cc00;">&lt;unit_price&gt;20.50&lt;/unit_price&gt;</span><br />
<span style="color: #99cc00;">&lt;product_discount&gt;.00&lt;/product_discount&gt;</span><br />
<span style="color: #99cc00;">&lt;total_price&gt;287.00&lt;/total_price&gt;</span><br />
<span style="color: #99cc00;">&lt;/product_id&gt;</span><br />
<span style="color: #99cc00;">&lt;/order_id&gt;</span><br />
<span style="color: #99cc00;">&lt;/customerid&gt;</span></p>
<p>This will retrieve order history for the customer 13453 and return the data in XML format.  Since the data is returned in an XML format, you do not need to use a cursor.  Test it out and me know if there is any errors or a better way to do it.</p>
<p>The post <a href="http://techsatwork.com/blog/?p=1328">Retrieving data as XML using stored procedure</a> appeared first on <a href="http://techsatwork.com/blog">techs@work</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://techsatwork.com/blog/?feed=rss2&#038;p=1328</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>What if you encounter Error number: 20598 with SQL Server replication ?</title>
		<link>http://techsatwork.com/blog/?p=1323</link>
		<comments>http://techsatwork.com/blog/?p=1323#comments</comments>
		<pubDate>Thu, 31 May 2012 04:25:52 +0000</pubDate>
		<dc:creator>rpillai</dc:creator>
				<category><![CDATA[database]]></category>
		<category><![CDATA[sql server]]></category>
		<category><![CDATA[distributor not working]]></category>
		<category><![CDATA[Error number: 20598]]></category>
		<category><![CDATA[find replication errors]]></category>
		<category><![CDATA[MSrepl_commands]]></category>
		<category><![CDATA[pending replication command]]></category>
		<category><![CDATA[sp_browsereplcmds]]></category>
		<category><![CDATA[sql server replication commands]]></category>
		<category><![CDATA[sql server replication error]]></category>

		<guid isPermaLink="false">http://techsatwork.com/blog/?p=1323</guid>
		<description><![CDATA[<p>Today on one of the sql server I encountered an interesting scenario, one of the dbas accidentally deleted data from subscriber and then when he realized he turned around and delete the data from publisher. Crap ! is the diplomatic term &#8230; <a href="http://techsatwork.com/blog/?p=1323">Continue reading <span class="meta-nav">&#8594;</span></a></p><p>The post <a href="http://techsatwork.com/blog/?p=1323">What if you encounter Error number: 20598 with SQL Server replication ?</a> appeared first on <a href="http://techsatwork.com/blog">techs@work</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>Today on one of the sql server I encountered an interesting scenario, one of the dbas accidentally deleted data from subscriber and then when he realized he turned around and delete the data from publisher. Crap ! is the diplomatic term to use here.  That too it was a huge table and part of a 50 table article. The moment he did that transactional replication stopped throwing the <a href="http://www.microsoft.com/products/ee/transform.aspx?ProdName=Microsoft+SQL+Server&amp;ProdVer=09.00&amp;EvtSrc=MSSQLServer&amp;EvtID=20598" target="_blank">Error number: 20598.</a> Which means the distributor is not able to deliver the delete statement to the subscriber since it cannot find the row.  Once this happens all the subsequent transactions just pile up. You got few ways to handle it:</p>
<p>1. Reinitialize the subscription (after giving the dba a kick in the you know what)<br />
2. If replication must continue while you identify the source of the error, specify the parameter -SkipErrors 20598 for the Distribution Agent and either fix the subscriber table.<br />
3. Manually insert the deleted rows to subscriber table, so the deletes can flow through<br />
4. If all of the above can&#8217;t be done, then delete the offending commands from the MSrepl_commands table. (again give the dba a kick in the you know what !)</p>
<p>The last option should be done with care since you are messing with replication commands that the distributor has pending. The table distribution.dbo.<a href="http://msdn.microsoft.com/en-us/library/ms178611.aspx" target="_blank">MSrepl_commands</a> table has all the commands the distributor has send and going to send to subscriber. If you delete more than what you need now you would have data inconsistency between publisher and subscriber.  In this post I am going to show you how you can identify the offending command and delete them from the MSrepl_commands table.</p>
<p>First lets find the errors that the distributor has encountered . You can find this either from the Replication monitor or by querying dbo.MSrepl_errors.  From the error_text column you should be able to identify the xact_seqno and command_id . Get the list of the xact_seqno and command_id that is causing the issue.</p>
<p>Second lets see what those commands are . For this execute the<a href="http://msdn.microsoft.com/en-us/library/ms176109.aspx" target="_blank"> sp_browsereplcmds</a> passing the xact_seqno. This will give you the list of all the commands that the distributor is trying to execute. Confirm the once you need to delete.<br />
eg: sp_browsereplcmds @xact_seqno_start = &#8217;0x0000002A000000D3000700000000&#8242;</p>
<p>Third  delete the rows from the MSrepl_commands table so that replication can continue with other pending ones. Be very cautious on what rows you delete. You do not want to delete rows that are not causing the issue.<br />
eg:  delete from dbo.MSrepl_commands<br />
where xact_seqno = 0x0000002A000000D3000700000000 and command_id in (1,2)</p>
<p>Once you delete the offending rows from the MSrepl_commands, replication should start sending the commands to subscriber. You the replication monitor to see whether the undistributed commands queue is decreasing.</p>
<p>Use this approach at your own risk.</p>
<p>&nbsp;</p>
<p>The post <a href="http://techsatwork.com/blog/?p=1323">What if you encounter Error number: 20598 with SQL Server replication ?</a> appeared first on <a href="http://techsatwork.com/blog">techs@work</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://techsatwork.com/blog/?feed=rss2&#038;p=1323</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Stored Procedure to insert data to parent and child using XML</title>
		<link>http://techsatwork.com/blog/?p=1318</link>
		<comments>http://techsatwork.com/blog/?p=1318#comments</comments>
		<pubDate>Fri, 25 May 2012 14:22:16 +0000</pubDate>
		<dc:creator>rpillai</dc:creator>
				<category><![CDATA[db2]]></category>
		<category><![CDATA[how to]]></category>
		<category><![CDATA[db2 stored procedure]]></category>
		<category><![CDATA[db2 XML]]></category>
		<category><![CDATA[inserting child data using XML]]></category>
		<category><![CDATA[inserting multiple rows using XML]]></category>
		<category><![CDATA[inserting XML data]]></category>
		<category><![CDATA[inserting XML to db2 table]]></category>
		<category><![CDATA[pureXML]]></category>
		<category><![CDATA[stored procedure]]></category>
		<category><![CDATA[XML column type]]></category>
		<category><![CDATA[XML query]]></category>
		<category><![CDATA[xmlparse]]></category>
		<category><![CDATA[xmltable]]></category>

		<guid isPermaLink="false">http://techsatwork.com/blog/?p=1318</guid>
		<description><![CDATA[<p>Couple of days back I wrote an article that showed how to quickly insert a child table with a  parent table having generated column. On this one I am going to show you how to insert data using XML as &#8230; <a href="http://techsatwork.com/blog/?p=1318">Continue reading <span class="meta-nav">&#8594;</span></a></p><p>The post <a href="http://techsatwork.com/blog/?p=1318">Stored Procedure to insert data to parent and child using XML</a> appeared first on <a href="http://techsatwork.com/blog">techs@work</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>Couple of days back I wrote an <a href="http://techsatwork.com/blog/?p=1313" target="_blank">article</a> that showed how to quickly insert a child table with a  parent table having generated column. On this one I am going to show you how to insert data using XML as a value.  As my previous article show its easy to insert to child table , but you have to insert one row at a time. Well what if we have multiple child rows that needs to be inserted . Here I am going to show you how to do that using XML as an input string holding child data. To make it nice and tight I wrote a small stored procedure . First lets create the tables (its the same set of tables I had it on my previous post) :</p>
<p><span style="color: #ff9900;">create table orders</span><br />
<span style="color: #ff9900;">(order_id  int not null</span><br />
<span style="color: #ff9900;">generated always as identity (start with 1000,increment by 1, nocache)</span><br />
<span style="color: #ff9900;">,customer_id int not null</span><br />
<span style="color: #ff9900;">,order_timestamp  timestamp</span><br />
<span style="color: #ff9900;">,order_channel_id  varchar(5)</span><br />
<span style="color: #ff9900;">,csr_id  varchar(10)</span><br />
<span style="color: #ff9900;">,primary key (order_id)</span><br />
<span style="color: #ff9900;">);</span><br />
<span style="color: #ff9900;">create table order_items</span><br />
<span style="color: #ff9900;">(order_id  int not null</span><br />
<span style="color: #ff9900;">,seq_num  int not null</span><br />
<span style="color: #ff9900;">,product_id  varchar(20) not null</span><br />
<span style="color: #ff9900;">,qty int</span><br />
<span style="color: #ff9900;">,unit_price dec(9,2)</span><br />
<span style="color: #ff9900;">,product_discount dec(9,2)</span><br />
<span style="color: #ff9900;">,primary key(order_id,seq_num)</span><br />
<span style="color: #ff9900;">);</span></p>
<p>Now that the table is created, lets create the stored procedure that will insert the data to the parent table and all data to the child table. Granted this stored procedure does not have all the bells and whistles and is only intended for demonstrating a method.</p>
<p><span style="color: #ff9900;">create or replace procedure spIorders</span><br />
<span style="color: #ff9900;">(in customerid int</span><br />
<span style="color: #ff9900;">,in orderchannelid varchar(5)</span><br />
<span style="color: #ff9900;">,in csrid varchar(10)</span><br />
<span style="color: #ff9900;">,in orderitems XML</span><br />
<span style="color: #ff9900;">,out orderid int</span><br />
<span style="color: #ff9900;">)</span><br />
<span style="color: #ff9900;">LANGUAGE SQL</span><br />
<span style="color: #ff9900;">NO EXTERNAL ACTION</span><br />
<span style="color: #ff9900;">P1:BEGIN</span><br />
<span style="color: #ff9900;">&#8211; declaring global temporary table to hold the data</span><br />
<span style="color: #ff9900;">declare global temporary table session.gtt_orders</span><br />
<span style="color: #ff9900;">(customer_id int not null</span><br />
<span style="color: #ff9900;">,order_channel_id varchar(5)</span><br />
<span style="color: #ff9900;">,csr_id varchar(10)</span><br />
<span style="color: #ff9900;">,order_item XML)</span><br />
<span style="color: #ff9900;">on commit delete rows</span><br />
<span style="color: #ff9900;">not logged;</span><br />
<span style="color: #ff9900;">&#8211; insert the data to the global temporary table from the data passed in</span><br />
<span style="color: #ff9900;">insert into session.gtt_orders</span><br />
<span style="color: #ff9900;">(customer_id,order_channel_id,csr_id,order_item)</span><br />
<span style="color: #ff9900;">values</span><br />
<span style="color: #ff9900;">(customerid</span><br />
<span style="color: #ff9900;">,orderchannelid</span><br />
<span style="color: #ff9900;">,csrid</span><br />
<span style="color: #ff9900;">,orderitems);</span><br />
<span style="color: #ff9900;">&#8211;insert into parent table (orders) from global temporary table</span><br />
<span style="color: #ff9900;">select order_id into orderid</span><br />
<span style="color: #ff9900;">from new table</span><br />
<span style="color: #ff9900;">(insert into orders</span><br />
<span style="color: #ff9900;">(customer_id,order_timestamp,order_channel_id,csr_id)</span><br />
<span style="color: #ff9900;">select gtt.customer_id,current_timestamp,gtt.order_channel_id,gtt.csr_id</span><br />
<span style="color: #ff9900;">from session.gtt_orders gtt);</span><br />
<span style="color: #ff9900;">&#8211;insert into child table (order_items) from global temporary table</span><br />
<span style="color: #ff9900;">&#8211;xmltable will split the XML document to multiple rows</span><br />
<span style="color: #ff9900;">&#8211;row_number() over() is an olap function that will generate rows number for seq_num</span><br />
<span style="color: #ff9900;">insert into order_items</span><br />
<span style="color: #ff9900;">(order_id,seq_num,product_id,qty,unit_price,product_discount)</span><br />
<span style="color: #ff9900;">select orderid,row_number() over(),x.productid,x.qty,x.unitprice,x.productdiscount</span><br />
<span style="color: #ff9900;">from session.gtt_orders gtt,</span><br />
<span style="color: #ff9900;">xmltable(&#8216;$c/orderitem/item&#8217; passing gtt.order_item as &#8220;c&#8221;</span><br />
<span style="color: #ff9900;">columns</span><br />
<span style="color: #ff9900;">productid varchar(20) path &#8216;productid&#8217;,</span><br />
<span style="color: #ff9900;">qty int path &#8216;qty&#8217;,</span><br />
<span style="color: #ff9900;">unitprice dec(9,2) path &#8216;unitprice&#8217;,</span><br />
<span style="color: #ff9900;">productdiscount dec(9,2) path &#8216;productdiscount&#8217;) as x;</span><br />
<span style="color: #ff9900;">&#8211;</span><br />
<span style="color: #ff9900;">commit;</span><br />
<span style="color: #ff9900;">&#8211; dropping the global temporary table since the inserts have be done.</span><br />
<span style="color: #ff9900;">drop table session.gtt_orders;</span><br />
<span style="color: #ff9900;">END P1</span><br />
<span style="color: #ff9900;">@</span></p>
<p>Now lets call the stored procedure we just created an pass in an XML that has three order items :</p>
<p><span style="color: #ff9900;">call spIorders (5000,&#8217;Web&#8217;,'RAJU&#8217;,</span><br />
<span style="color: #ff9900;">xmlparse(document</span><br />
<span style="color: #ff9900;">&#8216;&lt;orderitem&gt;</span><br />
<span style="color: #ff9900;">&lt;item&gt;</span><br />
<span style="color: #ff9900;">&lt;productid&gt;iPad3-Cell-64&lt;/productid&gt;</span><br />
<span style="color: #ff9900;">&lt;qty&gt;10&lt;/qty&gt;</span><br />
<span style="color: #ff9900;">&lt;unitprice&gt;829.00&lt;/unitprice&gt;</span><br />
<span style="color: #ff9900;">&lt;productdiscount&gt;50.00&lt;/productdiscount&gt;</span><br />
<span style="color: #ff9900;">&lt;/item&gt;</span><br />
<span style="color: #ff9900;">&lt;item&gt;</span><br />
<span style="color: #ff9900;">&lt;productid&gt;iPad2-Wifi-16&lt;/productid&gt;</span><br />
<span style="color: #ff9900;">&lt;qty&gt;5&lt;/qty&gt;</span><br />
<span style="color: #ff9900;">&lt;unitprice&gt;629.00&lt;/unitprice&gt;</span><br />
<span style="color: #ff9900;">&lt;productdiscount&gt;0.00&lt;/productdiscount&gt;</span><br />
<span style="color: #ff9900;">&lt;/item&gt;</span><br />
<span style="color: #ff9900;">&lt;item&gt;</span><br />
<span style="color: #ff9900;">&lt;productid&gt;iPod-Tch-8&lt;/productid&gt;</span><br />
<span style="color: #ff9900;">&lt;qty&gt;100&lt;/qty&gt;</span><br />
<span style="color: #ff9900;">&lt;unitprice&gt;199.00&lt;/unitprice&gt;</span><br />
<span style="color: #ff9900;">&lt;productdiscount&gt;100.00&lt;/productdiscount&gt;</span><br />
<span style="color: #ff9900;">&lt;/item&gt;</span><br />
<span style="color: #ff9900;">&lt;/orderitem&gt;</span><br />
<span style="color: #ff9900;">&#8216; preserve whitespace),?);</span></p>
<p>If you query the orders and order_items you should be able to see one row in orders table and three rows in order_items.<br />
Please feel free to comment on this and possible improvements or alternate methods.</p>
<p>&nbsp;</p>
<p>The post <a href="http://techsatwork.com/blog/?p=1318">Stored Procedure to insert data to parent and child using XML</a> appeared first on <a href="http://techsatwork.com/blog">techs@work</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://techsatwork.com/blog/?feed=rss2&#038;p=1318</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Inserting child table with parent table having generated column</title>
		<link>http://techsatwork.com/blog/?p=1313</link>
		<comments>http://techsatwork.com/blog/?p=1313#comments</comments>
		<pubDate>Wed, 23 May 2012 21:54:16 +0000</pubDate>
		<dc:creator>rpillai</dc:creator>
				<category><![CDATA[db2]]></category>
		<category><![CDATA[how to]]></category>
		<category><![CDATA[autogenerated parent key]]></category>
		<category><![CDATA[generated column]]></category>
		<category><![CDATA[insert child table with generated value]]></category>
		<category><![CDATA[insert child table with parent key]]></category>
		<category><![CDATA[inserting child table]]></category>
		<category><![CDATA[retreiving insert value]]></category>
		<category><![CDATA[retrieving generated value]]></category>
		<category><![CDATA[select insert]]></category>
		<category><![CDATA[sequence]]></category>

		<guid isPermaLink="false">http://techsatwork.com/blog/?p=1313</guid>
		<description><![CDATA[<p>I am sure we all have come across situations were we have to populate a child table with a value that has been generated in a parent table. If you don&#8217;t know how to handle it can take a bit &#8230; <a href="http://techsatwork.com/blog/?p=1313">Continue reading <span class="meta-nav">&#8594;</span></a></p><p>The post <a href="http://techsatwork.com/blog/?p=1313">Inserting child table with parent table having generated column</a> appeared first on <a href="http://techsatwork.com/blog">techs@work</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>I am sure we all have come across situations were we have to populate a child table with a value that has been generated in a parent table. If you don&#8217;t know how to handle it can take a bit of coding. Recently I came across a situation at work where a newbie was trying to populate a child table with an id that was generated at the parent table.<br />
The girl first inserted the data to the parent table which has an id column defined as GENERATED ALWAYS. She then selected the row to retrieve the generated value and then used it to populate the child table.</p>
<p>Whats wrong with this ? Nothing wrong with it unless you don&#8217;t want to kill the I/O system on a heavily used table.  So I introduced her to the famous  select from insert statement. Yes you heard it right&#8230;select from insert.  Surely everybody knows  INSERT SELECT, but  SELECT from INSERT is a slick feature.  You can retrieve the data you inserted without doing any additional I/O.  Here is a small example :</p>
<p>Lets create two sample tables :</p>
<p><span style="color: #99cc00;">create table orders</span><br />
<span style="color: #99cc00;"> (order_id  int not null</span><br />
<span style="color: #99cc00;"> generated always as identity (start with 1000,increment by 1, nocache)</span><br />
<span style="color: #99cc00;"> ,customer_id int not null</span><br />
<span style="color: #99cc00;"> ,order_timestamp  timestamp</span><br />
<span style="color: #99cc00;"> ,order_channel_id  varchar(5)</span><br />
<span style="color: #99cc00;"> ,csr_id  varchar(10)</span><br />
<span style="color: #99cc00;"> ,primary key (order_id)</span><br />
<span style="color: #99cc00;"> );</span><br />
<span style="color: #99cc00;"> create table order_items</span><br />
<span style="color: #99cc00;"> (order_id  int not null</span><br />
<span style="color: #99cc00;"> ,seq_num  int not null</span><br />
<span style="color: #99cc00;"> ,product_id  varchar(20) not null</span><br />
<span style="color: #99cc00;"> ,qty int</span><br />
<span style="color: #99cc00;"> ,unit_price dec(9,2)</span><br />
<span style="color: #99cc00;"> ,product_discount dec(9,2)</span><br />
<span style="color: #99cc00;"> ,primary key(order_id,seq_num)</span><br />
<span style="color: #99cc00;"> );</span></p>
<p>Now lets try to add a row to orders table and then using the generated order_id we will add a row to the order_items table.</p>
<p><span style="color: #99cc00;">create or replace variable vseq int;</span><br />
<span style="color: #99cc00;"> set vseq = 1;</span><br />
<span style="color: #99cc00;"> create or replace variable vorder int;</span><br />
<span style="color: #99cc00;"> set vorder =</span><br />
<span style="color: #99cc00;"> (select order_id</span><br />
<span style="color: #99cc00;"> from new table (</span><br />
<span style="color: #99cc00;"> insert into orders</span><br />
<span style="color: #99cc00;"> (customer_id,order_timestamp,order_channel_id,csr_id)</span><br />
<span style="color: #99cc00;"> values(5000,current_timestamp,&#8217;web&#8217;,'raju&#8217;)));</span></p>
<p><span style="color: #99cc00;">insert into order_items</span><br />
<span style="color: #99cc00;"> values(vorder,vseq,&#8217;A001&#8242;,10,100.00,0.00);</span></p>
<p><span style="color: #99cc00;">set vseq = vseq + 1;</span></p>
<p><span style="color: #99cc00;">insert into order_items</span><br />
<span style="color: #99cc00;"> values(vorder,vseq,&#8217;B002&#8242;,25,35.50,5.50);</span></p>
<p>The reason why I added the vseq variable was to show you that it can also be done. Another thing you can do while you are still connected on the same session you can issue : <span style="color: #99cc00;">select vorder from sysibm.sysdummy1</span>   to retrieve the value of the variable.</p>
<p>The variable is dropped when the connection or session is terminated. However its a good practice to drop the variable at the end of the transactions :</p>
<p><span style="color: #99cc00;">DROP VARIABLE vorder;</span></p>
<p>You can use the same approach if you are using the sequences</p>
<p>&nbsp;</p>
<p>The post <a href="http://techsatwork.com/blog/?p=1313">Inserting child table with parent table having generated column</a> appeared first on <a href="http://techsatwork.com/blog">techs@work</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://techsatwork.com/blog/?feed=rss2&#038;p=1313</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
