<?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>Kde... &#187; Oracle</title>
	<atom:link href="http://kirtandesai.com/write/index.php/category/oracle/feed/" rel="self" type="application/rss+xml" />
	<link>http://kirtandesai.com/write</link>
	<description></description>
	<lastBuildDate>Fri, 25 Jun 2010 13:46:45 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Oracle VM.</title>
		<link>http://kirtandesai.com/write/2007/11/15/oracle-vm/</link>
		<comments>http://kirtandesai.com/write/2007/11/15/oracle-vm/#comments</comments>
		<pubDate>Thu, 15 Nov 2007 02:44:55 +0000</pubDate>
		<dc:creator>Administrator</dc:creator>
				<category><![CDATA[BLOG]]></category>
		<category><![CDATA[Oracle]]></category>

		<guid isPermaLink="false">http://kirtandesai.com/write/2007/11/15/oracle-vm-is-not-for-me/</guid>
		<description><![CDATA[Oracle just announced the release of Oracle Virtualization software, Oracle VM. It sounds all great and fun but it needs two machines, one for installing the server and another for managing it. I don&#8217;t have two machines for this. I have two machines but this approach seems like a little too much effort for &#8220;virtualization&#8221;. [...]]]></description>
			<content:encoded><![CDATA[<p>Oracle just announced the release of Oracle Virtualization software, Oracle VM. It sounds all great and fun but it needs two machines, one for installing the server and another for managing it. I don&#8217;t have two machines for this. I have two machines but this approach seems like a little too much effort for &#8220;virtualization&#8221;. How does this make it simple. I am sticking with VMWare for now.</p>
]]></content:encoded>
			<wfw:commentRss>http://kirtandesai.com/write/2007/11/15/oracle-vm/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Oracle timestamp in Informatica</title>
		<link>http://kirtandesai.com/write/2007/09/10/oracle-timestamp/</link>
		<comments>http://kirtandesai.com/write/2007/09/10/oracle-timestamp/#comments</comments>
		<pubDate>Mon, 10 Sep 2007 19:41:54 +0000</pubDate>
		<dc:creator>Administrator</dc:creator>
				<category><![CDATA[Informatica]]></category>
		<category><![CDATA[Oracle]]></category>

		<guid isPermaLink="false">http://kirtandesai.com/write/2007/09/10/oracle-timestamp/</guid>
		<description><![CDATA[To extract values from an oracle table column of timestamp datatype, you need to convert it to a character datatype since the Oracle Timestamp datatype is not currently supported by PowerCenter. To extract the value do the following.
Use SQL override and function to_char, provided by oracle, to convert the values of a field to character [...]]]></description>
			<content:encoded><![CDATA[<p>To extract values from an oracle table column of timestamp datatype, you need to convert it to a character datatype since the Oracle Timestamp datatype is not currently supported by PowerCenter. To extract the value do the following.</p>
<li>Use SQL override and function to_char, provided by oracle, to convert the values of a field to character type before bringing it into PowerCenter mapping. For example,SQL> create table tst1 (tmstmp timestamp);Table created.
<p>SQL> insert into tst1 values (current_timestamp);</p>
<p>1 row created.</p>
<p>SQL> /</p>
<p>1 row created.</p>
<p>SQL> /</p>
<p>1 row created.</p>
<p>SQL> /</p>
<p>1 row created.</p>
<p>SQL> /</p>
<p>1 row created.</p>
<p>SQL> commit;</p>
<p>Commit complete.</p>
<p>SQL> select * from tst1;</p>
<p>TMSTMP<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
10-SEP-07 02.44.14.807930 PM<br />
10-SEP-07 02.44.16.700373 PM<br />
10-SEP-07 02.44.17.357597 PM<br />
10-SEP-07 02.44.18.163876 PM<br />
10-SEP-07 02.44.18.685926 PM</p>
<p>SQL> select tmstmp, to_char(tmstmp,&#8217;YYYY-MM-DD HH:MM:SS.FF6&#8242;) as CHAR_TMSTMP from tst1;</p>
<p>TMSTMP                        CHAR_TMSTMP<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-  &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
10-SEP-07 02.44.14.807930 PM  2007-09-10 02:09:14.807930<br />
10-SEP-07 02.44.16.700373 PM  2007-09-10 02:09:16.700373<br />
10-SEP-07 02.44.17.357597 PM  2007-09-10 02:09:17.357597<br />
10-SEP-07 02.44.18.163876 PM  2007-09-10 02:09:18.163876<br />
10-SEP-07 02.44.18.685926 PM  2007-09-10 02:09:18.685926</p>
<p>The resultant column CHAR_TMSTMP in the output of the query is now ready to be extracted in a mapping.</li>
<li>IMPORTANT thing to remember here is to make sure that the column for the timestamp value in the mapping, is defined as String(26).</li>
<p>Hope this helps&#8230;<br />
Kirtan</p>
]]></content:encoded>
			<wfw:commentRss>http://kirtandesai.com/write/2007/09/10/oracle-timestamp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Pivot Query</title>
		<link>http://kirtandesai.com/write/2007/09/05/pivot-query/</link>
		<comments>http://kirtandesai.com/write/2007/09/05/pivot-query/#comments</comments>
		<pubDate>Wed, 05 Sep 2007 09:46:20 +0000</pubDate>
		<dc:creator>Administrator</dc:creator>
				<category><![CDATA[Informatica]]></category>
		<category><![CDATA[Oracle]]></category>

		<guid isPermaLink="false">http://kirtandesai.com/write/2007/02/20/pivot-query/</guid>
		<description><![CDATA[So how to pivot data in a table?
I was asked about this by someone at work today. Let&#8217;s say you have a table that looks like following. I have included create and insert statements so that you can see it and understand it yourself.
Create table t1 (a number, b number);
insert into t1 values (1,1);
insert into [...]]]></description>
			<content:encoded><![CDATA[<p>So how to pivot data in a table?<br />
I was asked about this by someone at work today. Let&#8217;s say you have a table that looks like following. I have included create and insert statements so that you can see it and understand it yourself.</p>
<p><code>Create table t1 (a number, b number);</code></p>
<p><code>insert into t1 values (1,1);<br />
insert into t1 values (1,2);<br />
insert into t1 values (1,3);<br />
insert into t1 values (2,1);<br />
insert into t1 values (2,2);<br />
insert into t1 values (2,3);<br />
insert into t1 values (3,1);<br />
insert into t1 values (3,2);<br />
insert into t1 values (3,3);</code></p>
<p>select * from t1 order by 1,2;</p>
<p>####<br />
(A hint aside: You must specify the order in which you want the data to be back. It is completely wrong to say that oracle will return the data in order it was inserted.)<br />
####</p>
<p><code>A B<br />
----- ------<br />
1 1<br />
1 2<br />
1 3<br />
2 1<br />
2 2<br />
2 3<br />
3 1<br />
3 2<br />
3 3 </code></p>
<p>Now, let&#8217;s say you want to retrieve all the records from table t1 in a fashion where all the values in column B that belong to the group Column A should be shown side by side. Something like</p>
<p><code>A Val1 Val2 Val3<br />
-- ---- ---- ----<br />
1 1 2 3</code></p>
<p>One way would be to write a procedural code that stores different values of a group in an array or a series of variables and then displays them on screen or returns them to the calling program.</p>
<p>Or</p>
<p>You could just write a simple SQL statement that does it for you. You could write a piece of code that looks like this&#8230;</p>
<p><code>select<br />
a<br />
,max(decode(b,1,b,null)) col1<br />
,max(decode(b,2,b,null)) col2<br />
,max(decode(b,3,b,null)) col3<br />
from t1<br />
group by a;</code></p>
<p>A COL1 COL2 COL3<br />
&#8212;&#8211; &#8212;&#8212;- &#8212;&#8212;- &#8212;&#8212;-<br />
1 1 2 3<br />
2 1 2 3<br />
3 1 2 3</p>
<p>3 rows selected</p>
<p>&#8230; and you won&#8217;t have to worry about supporting an object such as a function or a procedure.</p>
<p>What if you had null values in one of the columns.</p>
<p><code>update t1 set b=null where a=2 and b=2;</code></p>
<p>One row updated</p>
<p>select<br />
a<br />
,max(decode(b,1,b,null)) col1<br />
,max(decode(b,2,b,null)) col2<br />
,max(decode(b,3,b,null)) col3<br />
from t1<br />
group by a;</p>
<p>A COL1 COL2 COL3<br />
&#8212;&#8211; &#8212;&#8212;- &#8212;&#8212;- &#8212;&#8212;-<br />
1 1 2 3<br />
2 1    3<br />
3 1 2 3</p>
<p>3 rows selected</p>
<p>There are many ways to write pivot queries. This is probably the easiest way of doing it.</p>
<p><strong>Using Informatica to perform pivot operation.</strong></p>
<p>You can use the Normalizer Transformation to generate rows out of columns. But to pivot values in rows into columns you would have to use Aggregator Transformation. You have to use the *FIRST* or *LAST* function to achieve this. First or last functions will pick first or last of the incoming rows if there are duplicates. Here is an example&#8230;</p>
<p>Suppose you have a source table with this data that is a record of monthly expenses for each of your departments. <code> create table deptexp (sales_id number(5), mon char(3), amt number(10,2));</code></p>
<p>insert into deptexp values (1,&#8217;JAN&#8217;,100);<br />
insert into deptexp values (1,&#8217;FEB&#8217;,120);<br />
insert into deptexp values (1,&#8217;MAR&#8217;,135);<br />
insert into deptexp values (2,&#8217;JAN&#8217;,110);<br />
insert into deptexp values (2,&#8217;FEB&#8217;,130);<br />
insert into deptexp values (2,&#8217;MAR&#8217;,120);<br />
Commit;</p>
<p>You want to load this data after denormalizing it into this structure.<br />
<code>create table deptexp1 (DEPT_ID number(5), JAN_AMT number(10,2), FEB_AMT number(10,2), MAR_AMT number(10,2))</code><br />
The data after our process would look like&#8230;<br />
<code>DEPT_ID   JAN_AMT   FEB_AMT   MAR_AMT<br />
1          100       120        135<br />
2          110       130        120<br />
</code><br />
Do the following to accomplish this.<br />
1. Create an Aggregator transformation with the following ports and expressions:<br />
<code>NAME	IN/OUT	EXPRESSION	GROUP BY<br />
DEPT_ID	IN	 	YES<br />
MONTH	IN	 	NO<br />
AMOUNT	IN	 	NO<br />
JAN_AMT	OUT	FIRST(AMOUNT, MONTH='JAN')<br />
FEB_AMT	OUT	FIRST(AMOUNT, MONTH='FEB')<br />
MAR_AMT	OUT	FIRST(AMOUNT, MONTH='MAR')<br />
APR_AMT	OUT	FIRST(AMOUNT, MONTH='APR')<br />
</code> 2. Connect the DEPT_ID, MONTH and the AMOUNT ports from the Source Qualifier to the Aggregator.<br />
3. Connect the JAN_AMT, FEB_AMT, MAR_AMT, etc. ports to the target.<br />
And that would do it&#8230;</p>
<p>Hope this helps&#8230;</p>
<p>Kirtan</p>
]]></content:encoded>
			<wfw:commentRss>http://kirtandesai.com/write/2007/09/05/pivot-query/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Analytic functions:</title>
		<link>http://kirtandesai.com/write/2007/05/10/analytic-functions/</link>
		<comments>http://kirtandesai.com/write/2007/05/10/analytic-functions/#comments</comments>
		<pubDate>Thu, 10 May 2007 07:46:16 +0000</pubDate>
		<dc:creator>Administrator</dc:creator>
				<category><![CDATA[Oracle]]></category>

		<guid isPermaLink="false">http://kirtandesai.com/write/2007/04/12/analytic-functions/</guid>
		<description><![CDATA[Analytic functions:
All my findings regarding analytic functions will go in this post. In other words I will keep on adding my finding to this post instead of creating new one all the time. I will also make sure that everytime when I update this post I bring up to the top of the list so [...]]]></description>
			<content:encoded><![CDATA[<p>Analytic functions:<br />
All my findings regarding analytic functions will go in this post. In other words I will keep on adding my finding to this post instead of creating new one all the time. I will also make sure that everytime when I update this post I bring up to the top of the list so that people notice the change.</p>
<p>Below is a small but sweet example that shows the difference between using three different functions.</p>
<p><code><br />
DENSE_RANK()<br />
RANK()<br />
ROW_NUMBER()<br />
</code></p>
<p><code><br />
create table t1 (<br />
a number,<br />
b varchar2(10)<br />
);</code></p>
<p>insert into t1 values (5, &#8216;ABC&#8217;);<br />
insert into t1 values (6, &#8216;ABC&#8217;);<br />
insert into t1 values (5, &#8216;ABC&#8217;);<br />
insert into t1 values (3, &#8216;ABC&#8217;);<br />
insert into t1 values (5, &#8216;ABC&#8217;);<br />
insert into t1 values (3, &#8216;ABC&#8217;);<br />
insert into t1 values (6, &#8216;ABC&#8217;);</p>
<p>insert into t1 values (4, &#8216;XYZ&#8217;);<br />
insert into t1 values (8, &#8216;XYZ&#8217;);<br />
insert into t1 values (4, &#8216;XYZ&#8217;);<br />
insert into t1 values (8, &#8216;XYZ&#8217;);<br />
insert into t1 values (4, &#8216;XYZ&#8217;);</p>
<p>commit;</p>
<p>SQL> select * from t1;</p>
<p>A B<br />
&#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;-<br />
5 ABC<br />
6 ABC<br />
5 ABC<br />
3 ABC<br />
5 ABC<br />
3 ABC<br />
6 ABC<br />
4 XYZ<br />
8 XYZ<br />
4 XYZ<br />
8 XYZ</p>
<p>A B<br />
&#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;-<br />
4 XYZ</p>
<p>12 rows selected.</p>
<p>SQL> select dense_rank() over (partition by b order by a) &#8220;denserank&#8221;,<br />
rank() over (partition by b order by a) &#8220;rank&#8221;,<br />
row_number() over (partition by b order by a) &#8220;rownumber&#8221;,<br />
a,b<br />
from t1;</p>
<p>denserank       rank  rownumber          A B<br />
&#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;-<br />
1          1          1          3 ABC<br />
1          1          2          3 ABC<br />
2          3          3          5 ABC<br />
2          3          4          5 ABC<br />
2          3          5          5 ABC<br />
3          6          6          6 ABC<br />
3          6          7          6 ABC<br />
1          1          1          4 XYZ<br />
1          1          2          4 XYZ<br />
1          1          3          4 XYZ<br />
2          4          4          8 XYZ</p>
<p>denserank       rank  rownumber          A B<br />
&#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;-<br />
2          4          5          8 XYZ</p>
<p>12 rows selected.</p>
<p>SQL><br />
Hope this helps.<br />
Kirtan</p>
<p>##### UPDATES BELOW #####</p>
<p>The example below uses MAX() function to show highest salary in each department right next to each employee record. It also shows what an employee&#8217;s salary is compared to the highest salary in the department.<br />
Here the key is (PARTITION BY DEPTNO) part of the analytic function. That&#8217;s what tells oracle to break data up based on the partition details.<br />
<code><br />
SQL> SELECT<br />
ENAME,<br />
SAL,<br />
DEPTNO,<br />
MAX(SAL) OVER (PARTITION BY DEPTNO) MGR_SAL_BY_DEPT,<br />
sal/MAX(SAL) OVER (PARTITION BY DEPTNO) *100   EMP_percent_SAL<br />
FROM EMP<br />
ORDER BY DEPTNO;</code></p>
<p>ENAME             SAL     DEPTNO MGR_SAL_BY_DEPT EMP_PERCENT_SAL<br />
&#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212;&#8212;<br />
CLARK            2450         10            5000              49<br />
KING             5000         10            5000             100<br />
MILLER           1300         10            5000              26<br />
JONES            2975         20            3000      99.1666667<br />
FORD             3000         20            3000             100<br />
ADAMS            1100         20            3000      36.6666667<br />
SMITH             800         20            3000      26.6666667<br />
SCOTT            3000         20            3000             100<br />
WARD             1250         30            2850      43.8596491<br />
TURNER           1500         30            2850      52.6315789<br />
ALLEN            1600         30            2850      56.1403509<br />
JAMES             950         30            2850      33.3333333<br />
BLAKE            2850         30            2850             100<br />
MARTIN           1250         30            2850      43.8596491</p>
<p>14 rows selected.</p>
<p>SQL></p>
<p>Now by adding one more MAX() function to the query we can have max salary across departments and a comparision of what an empolyee is making compared to the maximum salary across all departments.<br />
<code><br />
SQL> SELECT<br />
ENAME, SAL,DEPTNO,<br />
MAX(SAL) OVER (PARTITION BY DEPTNO) max_dept_sal<br />
,sal/MAX(SAL) OVER (PARTITION BY DEPTNO) *100   dept_percent<br />
,MAX(SAL) OVER () max_comp_sal<br />
,sal/MAX(SAL) OVER () *100 comp_percent<br />
FROM EMP<br />
ORDER BY DEPTNO;</code></p>
<p>ENAME             SAL     DEPTNO MAX_DEPT_SAL DEPT_PERCENT MAX_COMP_SAL COMP_PERCENT<br />
&#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212;<br />
CLARK            2450         10         5000           49         5000           49<br />
KING             5000         10         5000          100         5000          100<br />
MILLER           1300         10         5000           26         5000           26<br />
JONES            2975         20         3000   99.1666667         5000         59.5<br />
FORD             3000         20         3000          100         5000           60<br />
ADAMS            1100         20         3000   36.6666667         5000           22<br />
SMITH             800         20         3000   26.6666667         5000           16<br />
SCOTT            3000         20         3000          100         5000           60<br />
WARD             1250         30         2850   43.8596491         5000           25<br />
TURNER           1500         30         2850   52.6315789         5000           30<br />
ALLEN            1600         30         2850   56.1403509         5000           32</p>
<p>ENAME             SAL     DEPTNO MAX_DEPT_SAL DEPT_PERCENT MAX_COMP_SAL COMP_PERCENT<br />
&#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212;<br />
JAMES             950         30         2850   33.3333333         5000           19<br />
BLAKE            2850         30         2850          100         5000           57<br />
MARTIN           1250         30         2850   43.8596491         5000           25</p>
<p>14 rows selected.</p>
<p>SQL></p>
<p>##############UPDATES ###################</p>
<p>example showing the use of LAG and LEAD functions. Here, LAG is used for reading rows before the current row and LEAD is used for reading rows after the current row. Example below shows the difference between salaries of row and its previous row and row and its next row. The key here would be the ORDER BY clause in the OVER() section of the analytic function.<br />
<code /></p>
<p>SQL> SELECT<br />
2  EMPNO,<br />
3  ENAME,<br />
4  JOB,<br />
5  SAL,<br />
6  LAG(sal, 1, 0) OVER (ORDER BY sal) AS sal_prev,<br />
7  sal - LAG(sal, 1, 0) OVER (ORDER BY sal) AS LAG_sal_diff,<br />
8  LEAD(sal, 1, 0) OVER (ORDER BY sal) AS sal_NEXT,<br />
9  sal - LEAD(sal, 1, 0) OVER (ORDER BY sal) AS LEAD_sal_diff<br />
10  FROM<br />
11  EMP;</p>
<p>EMPNO ENAME      JOB              SAL   SAL_PREV LAG_SAL_DIFF   SAL_NEXT LEAD_SAL_DIFF<br />
---------- ---------- --------- ---------- ---------- ------------ ---------- -------------<br />
7369 SMITH      CLERK            800          0          800        950          -150<br />
7900 JAMES      CLERK            950        800          150       1100          -150<br />
7876 ADAMS      CLERK           1100        950          150       1250          -150<br />
7521 WARD       SALESMAN        1250       1100          150       1250             0<br />
7654 MARTIN     SALESMAN        1250       1250            0       1300           -50<br />
7934 MILLER     CLERK           1300       1250           50       1500          -200<br />
7844 TURNER     SALESMAN        1500       1300          200       1600          -100<br />
7499 ALLEN      SALESMAN        1600       1500          100       2450          -850<br />
7782 CLARK      MANAGER         2450       1600          850       2850          -400<br />
7698 BLAKE      MANAGER         2850       2450          400       2975          -125<br />
7566 JONES      MANAGER         2975       2850          125       3000           -25</p>
<p>EMPNO ENAME      JOB              SAL   SAL_PREV LAG_SAL_DIFF   SAL_NEXT LEAD_SAL_DIFF<br />
---------- ---------- --------- ---------- ---------- ------------ ---------- -------------<br />
7788 SCOTT      ANALYST         3000       2975           25       3000             0<br />
7902 FORD       ANALYST         3000       3000            0       5000         -2000<br />
7839 KING       PRESIDENT       5000       3000         2000          0          5000</p>
<p>14 rows selected.</p>
<p>SQL></p>
]]></content:encoded>
			<wfw:commentRss>http://kirtandesai.com/write/2007/05/10/analytic-functions/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>COALESCE</title>
		<link>http://kirtandesai.com/write/2007/04/06/coalesce/</link>
		<comments>http://kirtandesai.com/write/2007/04/06/coalesce/#comments</comments>
		<pubDate>Fri, 06 Apr 2007 15:37:17 +0000</pubDate>
		<dc:creator>Administrator</dc:creator>
				<category><![CDATA[Oracle]]></category>

		<guid isPermaLink="false">http://kirtandesai.com/write/2007/04/06/coalesce/</guid>
		<description><![CDATA[COALESCE is one of many convenient ways provided by oracle to handle NULL values in the database. The Oracle COALESCE function accepts a varying length list of arguments and returns the first non-NULL value/expr in the list. If all arguments in the list evaluate to a NULL value, then the COALESCE function will return a [...]]]></description>
			<content:encoded><![CDATA[<p>COALESCE is one of many convenient ways provided by oracle to handle NULL values in the database. The Oracle COALESCE function accepts a varying length list of arguments and returns the first non-NULL value/expr in the list. If all arguments in the list evaluate to a NULL value, then the COALESCE function will return a NULL value. Instead of scanning through all the arguments, oracle takes a short-circuit evaluation approach to processing what&#8217;s provided. In other words, it evaluates each expr value and determines whether it is NULL, rather than evaluating all of the expr values before determining whether any of them is NULL. As soon as it find the first non-NULL value it will stop processing rest of the provided arguments.</p>
<p>There is always more than one way to achieve the same outcome. You can use COALESCE as a variety of the CASE or DECODE expression.</p>
<p>For example,<br />
Using DECODE, you would do something like<br />
<code><br />
SELECT DECODE(mgr, NULL, 9999, mgr) FROM SCOTT.EMP<br />
</code><br />
OR</p>
<p>Using CASE, you would do something like<br />
<code><br />
SELECT<br />
CASE<br />
WHEN MGR IS NULL THEN<br />
9999<br />
ELSE<br />
MGR<br />
END<br />
FROM SCOTT.EMP;<br />
</code><br />
The following demonstrates how to substitute in a default value in a SELECT statement when there are NULL values present using COALESCE function.<br />
<code><br />
SELECT COALESCE(mgr, 9999) FROM SCOTT.EMP;<br />
</code><br />
The statement above looks much cleaner, well at least to everyone who knows what&#8217;s going on. In examples above, 9999 is a default value that you would like to assign to any null values in the list.</p>
<p>But a better use of COALESCE would be when more than 1 value is passed to it as input.\<br />
For example,<br />
<code><br />
SQL> select coalesce(null,null, 5, null) from dual;</p>
<p>COALESCE(NULL,NULL,5,NULL)<br />
--------------------------<br />
5</p>
<p>SQL> select coalesce(null,5,null,10, null) from dual;</p>
<p>COALESCE(NULL,5,NULL,10,NULL)<br />
-----------------------------<br />
5</p>
<p>SQL> select coalesce(null, null, null, null,555) from dual;</p>
<p>COALESCE(NULL,NULL,NULL,NULL,555)<br />
---------------------------------<br />
555</p>
<p>SQL><br />
</code><br />
As you can notice COALESCE picks up the first non-null value from a given list.</p>
<p>hope this helps.<br />
Kirtan</p>
]]></content:encoded>
			<wfw:commentRss>http://kirtandesai.com/write/2007/04/06/coalesce/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Name Parser</title>
		<link>http://kirtandesai.com/write/2007/04/04/name-parser/</link>
		<comments>http://kirtandesai.com/write/2007/04/04/name-parser/#comments</comments>
		<pubDate>Wed, 04 Apr 2007 20:56:07 +0000</pubDate>
		<dc:creator>Administrator</dc:creator>
				<category><![CDATA[Oracle]]></category>

		<guid isPermaLink="false">http://kirtandesai.com/write/2007/04/04/name-parser/</guid>
		<description><![CDATA[There was a question asked on InformaticaDevelopement yahoo group about parsing names. I had a piece of code saved from asktom. I don&#8217;t know when I got it from asktom, but I know I got it from asktom. I just wanted to put it out here for reference. To parse names you would have to [...]]]></description>
			<content:encoded><![CDATA[<p>There was a question asked on InformaticaDevelopement yahoo group about parsing names. I had a piece of code saved from asktom. I don&#8217;t know when I got it from asktom, but I know I got it from asktom. I just wanted to put it out here for reference. To parse names you would have to do the following.<br />
<code><br />
SQL>create table name_test ( a varchar2(15) );<br />
Table created.</code><code>SQL>insert into name_test values ( 'kirtan' );</p>
<p>1 row created.</p>
<p>SQL>insert into name_test values ( 'kirtan desai' );</p>
<p>1 row created.</p>
<p>SQL>insert into name_test values ( 'kirtan desai s' );</p>
<p>1 row created.</p>
<p>SQL>select substr( a||' ', 1, instr(a||' ' ' ')-1 ) first_name,<br />
  2         substr( a||'  ', instr( a||'  '  ' ') +1, instr( a||'  '  ' ', 1, 2 )-instr(a||'  ' ' ')-1 ) last_name,<br />
  3         rtrim(substr( a||'  ', instr( a||'  ' ' ',1,2)+1),' ') middle_init<br />
  4   from name_test<br />
  5  /</p>
<p>FIRST_NAME        LAST_NAME          MIDDLE_INIT<br />
----------------  -----------------  -----------------<br />
kirtan<br />
kirtan  desai<br />
kirtan  desai               s</p>
<p>hope this helps<br />
Kirtan</p>
<p></code>hope this helpsKirtan</p>
]]></content:encoded>
			<wfw:commentRss>http://kirtandesai.com/write/2007/04/04/name-parser/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Flashback Queries</title>
		<link>http://kirtandesai.com/write/2007/04/04/flashback-queries/</link>
		<comments>http://kirtandesai.com/write/2007/04/04/flashback-queries/#comments</comments>
		<pubDate>Wed, 04 Apr 2007 20:46:16 +0000</pubDate>
		<dc:creator>Administrator</dc:creator>
				<category><![CDATA[Oracle]]></category>

		<guid isPermaLink="false">http://kirtandesai.com/write/2007/04/04/flashback-queries/</guid>
		<description><![CDATA[Flashback features were there in 9i. 10g is providing something new/extra.
### From new features guide  ###
What if you ever need to do a resetlogs operation for recovery purposes, you can take the
database back to a point in time before the resetlogs if you find that you made a
mistake. This provides administrators more flexibility to detect [...]]]></description>
			<content:encoded><![CDATA[<p>Flashback features were there in 9i. 10g is providing something new/extra.</p>
<p>### From new features guide  ###<br />
What if you ever need to do a resetlogs operation for recovery purposes, you can take the<br />
database back to a point in time before the resetlogs if you find that you made a<br />
mistake. This provides administrators more flexibility to detect and correct human<br />
error situations.<br />
It is now possible to flashback the primary and standby databases to an SCN or a point in<br />
time prior to the switchover operation. Using flashback in this way on a physical standby<br />
database preserves the standby role. Using flashback in this way on a logical standby<br />
database changes the role of the standby database to what it was at the target SCN/time.<br />
###    ###<br />
Here is how you can use Flashback options.<br />
<code><br />
SQL> create table ksdesai.fstes (a number(2));</code><code>Table created.</p>
<p>SQL> insert into ksdesai.fstes values (1);</p>
<p>1 row created.</p>
<p>SQL> insert into ksdesai.fstes values (2);</p>
<p>1 row created.</p>
<p>SQL> insert into ksdesai.fstes values (3);</p>
<p>1 row created.</p>
<p>SQL> insert into ksdesai.fstes values (4);</p>
<p>1 row created.</p>
<p>SQL> insert into ksdesai.fstes values (5);</p>
<p>1 row created.</p>
<p>SQL> commit;</p>
<p>Commit complete.</p>
<p>SQL> select * from ksdesai.fstes;</p>
<p>         A<br />
----------<br />
         1<br />
         2<br />
         3<br />
         4<br />
         5</p>
<p>SQL> delete from ksdesai.fstes where a<3;</p>
<p>2 rows deleted.</p>
<p>SQL> commit;</p>
<p>Commit complete.</p>
<p>SQL> SELECT versions_xid XID, versions_startscn START_SCN,<br />
  2  versions_endscn END_SCN, versions_operation OPERATION,<br />
  3  A AS TABLE_COLUMN FROM KSDESAI.FSTES<br />
  4  VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE<br />
  5  ;\<br />
  6 <br />
SQL> SELECT versions_xid XID, versions_startscn START_SCN,<br />
  2  versions_endscn END_SCN, versions_operation OPERATION,<br />
  3  A AS TABLE_COLUMN FROM KSDESAI.FSTES<br />
  4  VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE;</p>
<p>XID               START_SCN    END_SCN O TABLE_COLUMN<br />
---------------- ---------- ---------- - ------------<br />
000A001B00078D60  660961162            D            2<br />
000A001B00078D60  660961162            D            1<br />
0005002E0007F815  660961134            I            5<br />
0005002E0007F815  660961134            I            4<br />
0005002E0007F815  660961134            I            3<br />
0005002E0007F815  660961134  660961162 I            2<br />
0005002E0007F815  660961134  660961162 I            1</p>
<p>7 rows selected.</p>
<p>SQL> insert into ksdesai.fstes<br />
  2  select a from ksdesai.fstes<br />
  3  VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE<br />
  4  where versions_operation='D';</p>
<p>2 rows created.</p>
<p>SQL> commit;</p>
<p>Commit complete.</p>
<p>SQL> select * from ksdesai.fstes;</p>
<p>         A<br />
----------<br />
         3<br />
         4<br />
         5<br />
         2<br />
         1<br />
</code>Magical!!! Or is it?</p>
<p>Kirtan</p>
<p>####UPDATES####</p>
<p>Retriving delete records from a table within certain period.</p>
<p><code><br />
SQL> create table t1 (a number);</p>
<p>Table created.</p>
<p>SQL> desc t1;<br />
 Name   Null?  Type<br />
------ ------ --------<br />
 A             NUMBER</p>
<p>SQL> insert into t1 values (1);</p>
<p>1 row created.</p>
<p>SQL> insert into t1 values (2);</p>
<p>1 row created.</p>
<p>SQL> insert into t1 values (3);</p>
<p>1 row created.</p>
<p>SQL> commit;</p>
<p>Commit complete.</p>
<p>SQL> select * from t1;</p>
<p>         A<br />
----------<br />
         1<br />
         2<br />
         3</p>
<p>SQL> create table t3 (a number);</p>
<p>Table created.</p>
<p>SQL> insert into t3 values (1);</p>
<p>1 row created.</p>
<p>SQL> insert into t3 values (2);</p>
<p>1 row created.</p>
<p>SQL> insert into t3 values (3);</p>
<p>1 row created.</p>
<p>SQL> commit;</p>
<p>Commit complete.</p>
<p>SQL> select * from t3;</p>
<p>         A<br />
----------<br />
         1<br />
         2<br />
         3</p>
<p></code><br />
######################<br />
<code><br />
SQL> delete from t1 where a=2;</p>
<p>1 row deleted.</p>
<p>SQL> commit;</p>
<p>Commit complete.</p>
<p>SQL> select * from t1;</p>
<p>         A<br />
----------<br />
         1<br />
         3</p>
<p>SQL> select * from t3;</p>
<p>         A<br />
----------<br />
         1<br />
         2<br />
         3</p>
<p>########################</p>
<p>SQL> select versions_xid XID, versions_startscn START_SCN,<br />
  2  versions_endscn END_SCN, versions_operation OPERATION,<br />
  3  A AS TABLE_COLUMN from t1<br />
  4  VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE;</p>
<p>XID               START_SCN    END_SCN O TABLE_COLUMN<br />
---------------- ---------- ---------- - ------------<br />
000B000D0006B0E0  661139198            D            2<br />
000B002C0006B412  661139095            I            3<br />
000B002C0006B412  661139095  661139198 I            2<br />
000B002C0006B412  661139095            I            1</p>
<p>######################</p>
<p>SQL>  select * from t3;</p>
<p>         A<br />
----------<br />
         1<br />
         2<br />
         3</p>
<p>SQL> delete from t3 where a in (<br />
  2  select a from t1<br />
  3  VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE<br />
  4  where<br />
  5  versions_operation='D'<br />
  6  );</p>
<p>1 row deleted.</p>
<p>SQL> select * from t3;</p>
<p>         A<br />
----------<br />
         1<br />
         3</p>
<p>#######################</p>
<p>SQL> select * from  t1 a, t1 b where a.a=b.a;</p>
<p>         A          A<br />
---------- ----------<br />
         1          1<br />
         3          3</p>
<p>######################</p>
<p>SQL> insert into t1<br />
  2  select a from t1<br />
  3  VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE<br />
  4  where<br />
  5  versions_operation='D';</p>
<p>1 row created.</p>
<p>SQL> commit;</p>
<p>Commit complete.</p>
<p>SQL> select * from t1;</p>
<p>         A<br />
----------<br />
         1<br />
         3<br />
         2<br />
</code><br />
######################</p>
]]></content:encoded>
			<wfw:commentRss>http://kirtandesai.com/write/2007/04/04/flashback-queries/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>duplicate file check</title>
		<link>http://kirtandesai.com/write/2007/04/03/duplicate-file-check/</link>
		<comments>http://kirtandesai.com/write/2007/04/03/duplicate-file-check/#comments</comments>
		<pubDate>Tue, 03 Apr 2007 23:24:58 +0000</pubDate>
		<dc:creator>Administrator</dc:creator>
				<category><![CDATA[Oracle]]></category>

		<guid isPermaLink="false">http://kirtandesai.com/write/2007/04/03/duplicate-file-check/</guid>
		<description><![CDATA[I just wrote this procedure below that does duplicate file (dataset, i should say) check.
Let&#8217;s say, you have a system where your clients/users have rights to write straight to your &#8220;staging&#8221; or &#8220;landing&#8221; tables. You have a system where multiple users are feeding multiple files everyday. You have a requirement to check whether users are [...]]]></description>
			<content:encoded><![CDATA[<p>I just wrote this procedure below that does duplicate file (dataset, i should say) check.</p>
<p>Let&#8217;s say, you have a system where your clients/users have rights to write straight to your &#8220;staging&#8221; or &#8220;landing&#8221; tables. You have a system where multiple users are feeding multiple files everyday. You have a requirement to check whether users are sending duplicate files into your system intentionally or unintentionally. You could probably find a million ways of doing a duplicate file check. I just wrote a simple stored procedure that does that for me. Let&#8217;s have a look at it. \</p>
<p><code><br />
create or replace PROCEDURE clob_to_hash IS<br />
 i number(5);<br />
 mychar VARCHAR2(4000);<br />
 myclob CLOB;<br />
 myraw raw(2000);<br />
 rec_cnt NUMBER(2);<br />
 CURSOR mycur1 IS<br />
  SELECT column_name AS<br />
  field_name<br />
  FROM sys.all_tab_cols<br />
  WHERE owner = 'SCOTT'<br />
  AND TABLE_NAME = 'EMP'<br />
  ORDER BY column_id;<br />
 mycur mycur1%ROWTYPE;<br />
 col_names VARCHAR2(4000);<br />
 mysqlstr varchar2(4000);<br />
BEGIN<br />
 i:=0;<br />
 OPEN mycur1;<br />
 LOOP<br />
  FETCH mycur1 INTO mycur;<br />
  EXIT WHEN mycur1%NOTFOUND;<br />
  IF i = 0 THEN<br />
   col_names := mycur.field_name;<br />
  ELSE<br />
   col_names := col_names || ',' || mycur.field_name;<br />
  end if;<br />
 i:=i+1;<br />
 END LOOP;<br />
 close mycur1;<br />
 mysqlstr := 'SELECT xmlagg(xmlelement("emp",' || col_names || ')).getclobval() FROM scott.emp';<br />
 execute immediate mysqlstr INTO myclob;<br />
 myraw := dbms_crypto.hash(src => myclob, typ => dbms_crypto.hash_md5);<br />
 mychar := rawtohex(myraw);<br />
 SELECT COUNT(*) INTO rec_cnt FROM hashtest WHERE mchar = mychar;<br />
 IF rec_cnt = 0 THEN<br />
  INSERT INTO hashtest VALUES(mychar);<br />
 ELSE<br />
  INSERT INTO hashtest VALUES('duplicate data set');<br />
 END IF;<br />
 COMMIT;<br />
END;<br />
</code></p>
<p>This procedure creates a list of column names of &#8216;emp&#8217; table from sys.all_tab_cols in order they were created. It builds a clob of xml data out of the emp table and create an MD5 key for that clob. It converts the &#8216;raw&#8217; value returned by DBMS_CRYPTO.HASH function to a &#8216;hex&#8217; value. After that it tries to find a row in the &#8220;hashtest&#8221; table to see if the same &#8216;hash&#8217; key exists. If it finds duplicate records, it write &#8216;duplicate data set&#8217; in the hashtest table. otherwise it writes the &#8216;hex&#8217; value generated from the &#8216;hash&#8217; value which was returned in &#8216;raw&#8217; format by DBMS_CRYPTO.HASH function.</p>
<p><code><br />
SQL> truncate table hashtest;</p>
<p>Table truncated.</p>
<p>SQL> exec clob_to_hash;</p>
<p>PL/SQL procedure successfully completed.</p>
<p>SQL> desc hashtest;</p>
<p>Name                                      Null?    Type<br />
----------------------------------------- -------- ----------------------------<br />
MCHAR                                              VARCHAR2(255)</p>
<p>SQL> select * from hashtest;</p>
<p>MCHAR<br />
--------------------------------------------------------------------------------<br />
4FCD4351B718B46FC8DCE7BA01B3F910</p>
<p>SQL> exec clob_to_hash;</p>
<p>PL/SQL procedure successfully completed.</p>
<p>SQL> select * from hashtest;</p>
<p>MCHAR<br />
--------------------------------------------------------------------------------<br />
17A6E53EA979BFB0E67CCE2E5BDDB769<br />
duplicate data set</p>
<p>SQL> update scott.emp set sal=sal+100 where empno=7844;</p>
<p>1 rows updated.</p>
<p>SQL> commit;</p>
<p>Commit complete</p>
<p>SQL> exec clob_to_hash;</p>
<p>PL/SQL procedure successfully completed.</p>
<p>SQL> select * from hashtest;</p>
<p>MCHAR<br />
--------------------------------------------------------------------------------<br />
17A6E53EA979BFB0E67CCE2E5BDDB769<br />
duplicate data set<br />
4FCD4351B718B46FC8DCE7BA01B3F910</p>
<p></code></p>
<p>That&#8217;s it!!! With a little modification, you could pretty much use this to compare any two datasets.</p>
]]></content:encoded>
			<wfw:commentRss>http://kirtandesai.com/write/2007/04/03/duplicate-file-check/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Useful Scripts.</title>
		<link>http://kirtandesai.com/write/2007/03/28/oracle-scripts-01/</link>
		<comments>http://kirtandesai.com/write/2007/03/28/oracle-scripts-01/#comments</comments>
		<pubDate>Wed, 28 Mar 2007 14:22:55 +0000</pubDate>
		<dc:creator>Administrator</dc:creator>
				<category><![CDATA[Oracle]]></category>

		<guid isPermaLink="false">http://kirtandesai.com/write/2007/03/28/oracle-scripts-01/</guid>
		<description><![CDATA[Below are some useful scripts that i found in one of my old hard drives. If you want to gather stat reports for the oracle ser sessions you could use the following scripts. Right before posting this i tried them on 8i, 9i, and 10g.
To find total cpu usage by each/all sessions, you could use [...]]]></description>
			<content:encoded><![CDATA[<p>Below are some useful scripts that i found in one of my old hard drives. If you want to gather stat reports for the oracle ser sessions you could use the following scripts. Right before posting this i tried them on 8i, 9i, and 10g.</p>
<p>To find total cpu usage by each/all sessions, you could use the following sql statement.</p>
<p><code><br />
Select   nvl ( sess.username, 'oracle_process' ) username<br />
,        sess_stat.sid session_id, value cpu_usage<br />
From     v$session sess<br />
,        v$sesstat sess_stat<br />
,        v$statname stat_name<br />
Where    sess_stat.statistic# = stat_name.statistic#<br />
And      name like '%cpu used by this session%'<br />
And      sess_stat.sid = sess.sid<br />
And      value > 0<br />
Order by value desc<br />
/<br />
</code><br />
To find total resource usage by each user, you could use the following sql statement.<br />
<code><br />
Select   sess.sid, nvl ( sess.username, 'oracle_process' ) username<br />
,        sess_stat.sid session_id, stat_name.name statistic, value cpu_usage<br />
From     v$session sess<br />
,        v$statname stat_name<br />
,        v$sesstat sess_stat<br />
Where    sess_stat.sid = sess.sid<br />
And      stat_name.statistic# = sess_stat.statistic#<br />
And      value != 0<br />
Order by value desc<br />
,        sess.username<br />
,        sess.sid<br />
,        stat_name.name<br />
/<br />
</code></p>
<p>To find session i/o activity by each user, you could use the following sql statement.<br />
<code><br />
Select   nvl ( sessions.username, 'oracle_process' ) username, osuser os_user<br />
,        process pid, sessions.sid sid, serial#, physical_reads, block_gets<br />
,        consistent_gets, block_changes, consistent_gets, block_changes<br />
,        consistent_changes<br />
From     v$session sessions<br />
,        v$sess_io session_io<br />
Where    sessions.sid = session_io.sid<br />
Order by physical_reads desc<br />
,        sessions.username<br />
/</code></p>
<p>hope this helps&#8230;</p>
<p>Kirtan</p>
]]></content:encoded>
			<wfw:commentRss>http://kirtandesai.com/write/2007/03/28/oracle-scripts-01/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Oracle Function:Translate &amp; Replace</title>
		<link>http://kirtandesai.com/write/2007/02/28/remove-special-characters-from-a-string/</link>
		<comments>http://kirtandesai.com/write/2007/02/28/remove-special-characters-from-a-string/#comments</comments>
		<pubDate>Wed, 28 Feb 2007 19:34:55 +0000</pubDate>
		<dc:creator>Administrator</dc:creator>
				<category><![CDATA[Oracle]]></category>

		<guid isPermaLink="false">http://kirtandesai.com/write/2007/02/28/remove-special-characters-from-a-string/</guid>
		<description><![CDATA[Using Oracle function TRANSLATE and REPLACE to remove special characters from a string.
This is the definition of the function.
TRANSLATE(expr, from_string, to_string)
Descrption: [FROM ORACLE DOCUMENTATION]
TRANSLATE returns expr with all occurrences of each character in from_string replaced by its corresponding character in to_string. Characters in expr that are not in from_string are not replaced. If expr is [...]]]></description>
			<content:encoded><![CDATA[<p>Using Oracle function TRANSLATE and REPLACE to remove special characters from a string.</p>
<p>This is the definition of the function.</p>
<p>TRANSLATE(expr, from_string, to_string)</p>
<p>Descrption: [<strong>FROM ORACLE DOCUMENTATION</strong>]</p>
<p>TRANSLATE returns expr with all occurrences of each character in from_string replaced by its corresponding character in to_string. Characters in expr that are not in from_string are not replaced. If expr is a character string, then you must enclose it in single quotation marks. The argument from_string can contain more characters than to_string. In this case, the extra characters at the end of from_string have no corresponding characters in to_string. If these extra characters appear in char, then they are removed from the return value.</p>
<p>You cannot use an empty string for to_string to remove all characters in from_string from the return value. Oracle Database interprets the empty string as null, and if this function has a null argument, then it returns null.</p>
<p>Let&#8217;s see&#8230;</p>
<p><code>SQL> create table t6 (a varchar2(20));</p>
<p>Table created.</p>
<p>SQL> insert into t6 values (<a href="mailto:'ABC!@#$%^&#038;*XYZ'">'ABC!@#$%^&#038;*XYZ'</a>);</p>
<p>1 row created.</p>
<p>SQL> commit;</p>
<p>Commit complete.</p>
<p>SQL> select * from t6;</p>
<p>A<br />
--------------<br />
<a href="mailto:ABC!@#$%^&#038;*XYZ">ABC!@#$%^&#038;*XYZ</a><br />
SQL> SELECT TRANSLATE(a, <a href="mailto:'!@#$%^&#038;*'">'!@#$%^&#038;*'</a>, ' ') FROM t6;<br />
TRANSLATE(A,'!@#$%^&#038;<br />
---------------------<br />
ABC XYZ</code></p>
<p>#####<br />
Notice that I removed the $ (DOLLAR) sign from the list of junk.<br />
#####</p>
<p><code>SQL> SELECT TRANSLATE(a, <a href="mailto:'!@#%^&#038;*'">'!@#%^&#038;*'</a>, ' ') FROM t6;<br />
TRANSLATE(A,'!@#%^&#038;*<br />
--------------------<br />
ABC $XYZ</code><br />
#####<br />
I would create a function that accepts a varchar2 and returns a &#8216;cleaned&#8217; varchar2 for this purpose.<br />
#####</p>
<p><code>SQL> create or replace function clean_str(in_string in varchar2)<br />
2 return varchar2<br />
3 is<br />
4 out_string varchar2(4000);<br />
5 remove_char varchar2(100);<br />
6 begin<br />
7 remove_char:='!@#$%^&#038;*æ';<br />
8 select TRANSLATE(in_string,remove_char , ' ') into out_string FROM dual;<br />
9 return (out_string);<br />
10 end;<br />
11 /</p>
<p>Function created.</p>
<p>SQL> select clean_str(a) from t6;</p>
<p>CLEAN_STR(A)<br />
------------<br />
ABC XYZ</code></p>
<p>I kept the last argument &#8216; &#8216; (a space) because of the NULL rule mentioned above in the description. I just asked Oracle to assign a single space instead.</p>
<p><code>SQL> insert into t6 values (<a href="mailto:'ABC!@#$XYZ%^&#038;*XML'">'ABC!@#$XYZ%^&#038;*XML'</a>);</p>
<p>1 row created.</p>
<p>SQL> commit;</p>
<p>Commit complete.</p>
<p>SQL> select * from t6;</p>
<p>A<br />
-----------------<br />
<a href="mailto:ABC!@#$%^&#038;*XYZ">ABC!@#$%^&#038;*XYZ</a><br />
<a href="mailto:ABC!@#$XYZ%^&#038;*XML">ABC!@#$XYZ%^&#038;*XML</a></p>
<p>SQL> select clean_str(a) from t6;</p>
<p>CLEAN_STR(A)<br />
------------<br />
ABC XYZ<br />
ABC XYZXML</code></p>
<p>Now that I have a string like &#8216;ABC XYZ&#8217; and &#8216;ABC XYZXML&#8217;, I am going to use Oracle function REPLACE to remove the extra space(s). The advantage of REPLACE is that it replaces all the occurances of the string/character with the provided replacement string. So lets change the function a little bit.</p>
<p><code>SQL> create or replace function clean_str(in_string in varchar2)<br />
2 return varchar2<br />
3 is<br />
4 out_string varchar2(4000);<br />
5 remove_char varchar2(100);<br />
6 begin<br />
7 remove_char:='!@#$%^&#038;*æ';<br />
8 select<br />
9 REPLACE(TRANSLATE(in_string,remove_char , ' '),' ',NULL)<br />
10 into out_string<br />
11 FROM dual;<br />
12 return (out_string);<br />
13 end;<br />
14 /</p>
<p>Function created.</p>
<p>SQL> select clean_str(a) from t6;</p>
<p>CLEAN_STR(A)<br />
------------<br />
ABCXYZ<br />
ABCXYZXML</code><br />
So now all you have to do is keep a list of unwanted or special characters in the <em>remove_char</em> variable of the function and you are golden.</p>
<p>I hope this helps.</p>
<p>-Kirtan</p>
<p><strong>Updated!!!</strong></p>
<p>I just realized that there is no need to use REPLACE function above. I will keep it as it is just in case if someone wants to use it as it is. Below is an updated(and better IMHO) version of clean_str() function. The idea is to pass the character that you want to remove as the THIRD argument and concatenate the variable remove_char with the same character. It is going to be a space for this example.<br />
<code><br />
create or replace function clean_str(in_string in varchar2)<br />
return varchar2<br />
is<br />
out_string varchar2(4000);<br />
remove_char varchar2(100);<br />
begin<br />
remove_char:=' ' || '!@#''''$%^&#038;*æ';<br />
select<br />
--REPLACE(TRANSLATE(in_string,remove_char , ' '),' ',NULL)<br />
TRANSLATE(in_string,remove_char , ' ')<br />
into out_string<br />
FROM dual;<br />
return (out_string);<br />
end;<br />
/<br />
</code></p>
<p>What you can also do is you can allow the character that you want to be removed as  an input to the function.</p>
<p><code>create or replace function clean_str1(in_string in varchar2,culprit in char)<br />
return varchar2<br />
is<br />
out_string varchar2(4000);<br />
remove_char varchar2(100);<br />
begin<br />
remove_char:=culprit || '!@#''''$%^&#038;*æ';<br />
select<br />
--REPLACE(TRANSLATE(in_string,remove_char , ' '),' ',NULL)<br />
TRANSLATE(in_string,remove_char , culprit)<br />
into out_string<br />
FROM dual;<br />
return (out_string);<br />
end;<br />
/</code><code>SQL> select clean_str1('KIR$#@%TAN',' ') from dual;</p>
<p>CLEAN_STR1('KIR$#@%TAN','')<br />
--------------------------------------------------------------------------------<br />
KIRTAN</p>
<p>SQL></p>
<p></code></p>
]]></content:encoded>
			<wfw:commentRss>http://kirtandesai.com/write/2007/02/28/remove-special-characters-from-a-string/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>
