<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Techblog</title>
    <link rel="alternate" type="text/html" href="http://www.somberi.com/techblog/" />
    <link rel="self" type="application/atom+xml" href="http://www.somberi.com/techblog/atom.xml" />
   <id>tag:www.somberi.com,2008:/techblog/5</id>
    <link rel="service.post" type="application/atom+xml" href="http://www.somberi.com/nrk-mt/mt-atom.cgi/weblog/blog_id=5" title="Techblog" />
    <updated>2008-07-10T00:37:43Z</updated>
    <subtitle>This blog contains articles and scripts for Oracle and Teradata DBAs and Developers</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type 3.2ysb5-20051201</generator>
 
<entry>
    <title>Teradata Announcement</title>
    <link rel="alternate" type="text/html" href="http://www.somberi.com/techblog/2008/01/teradata_announcement.php" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.somberi.com/nrk-mt/mt-atom.cgi/weblog/blog_id=5/entry_id=154" title="Teradata Announcement" />
    <id>tag:www.somberi.com,2008:/techblog//5.154</id>
    
    <published>2008-01-23T00:59:34Z</published>
    <updated>2008-07-10T00:37:43Z</updated>
    
    <summary>Claybourne Barrineau is going to contribute Teradata tips and articles</summary>
    <author>
        <name>Ramakrishna Nemani</name>
        
    </author>
            <category term="Announcements" />
    
    <content type="html" xml:lang="en" xml:base="http://www.somberi.com/techblog/">
        <![CDATA[<p align="justify">I am&nbsp;pleased to&nbsp;announce that <strong>Mr.Claybourne Barrineau</strong> who is my friend and colleague at Coca-Cola Enterprises Inc. has kindly agreed to share his Teradata knowledge in this forum.</p><p align="justify">Claybourne Barrineau (or Clay as he is known to his friends), has been working with Teradata technologies since 1998. Clay is very well known in Teradata circles. He is a member of&nbsp;the <a href="http://www.teradata.com/teradata-partners/about/product.shtml" target="_blank">Teradata Product Advisory Council (PAC)</a>&nbsp;which<span>&nbsp; </span>is an advisory group that provides input to the&nbsp;Teradata corporation regarding the product direction for Teradata RDBMS along with related products and platforms. Look out for his contributions in the coming days.</p><p align="justify">Claybourne Barrineau works as a Senior Application DBA with Coca-Cola Enterprises, Inc., where he is responsible for architecting and maintaining a world class Teradata information warehouse. </p><p align="justify">- Ramakrishna Nemani <br /></p>]]>
        
    </content>
</entry>
<entry>
    <title>Teradata Dignostics commands</title>
    <link rel="alternate" type="text/html" href="http://www.somberi.com/techblog/2007/11/dignostics_commands.php" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.somberi.com/nrk-mt/mt-atom.cgi/weblog/blog_id=5/entry_id=118" title="Teradata Dignostics commands" />
    <id>tag:somberi.com,2007:/techblog//5.118</id>
    
    <published>2007-11-04T23:25:39Z</published>
    <updated>2008-01-23T13:02:27Z</updated>
    
    <summary>These commands help DBAs in troubleshooting query performance issues</summary>
    <author>
        <name>Ramakrishna Nemani</name>
        
    </author>
            <category term="DBA" />
            <category term="Ramakrishna Nemani" />
            <category term="Teradata" />
    
    <content type="html" xml:lang="en" xml:base="http://www.somberi.com/techblog/">
        <![CDATA[<p align="justify">Diagnostic commands are undocumented features of Teradata. These commands come in handy to DBAs when dignosing performance problems. I use a couple of the Diagnostic commands regularly in troubleshooting&nbsp; performance issues. </p><p>&nbsp;</p>]]>
        <![CDATA[<p><strong>DIAGNOSTIC VERBOSEEXPLAIN ON FOR SESSION;&nbsp; </strong></p><p>The above command makes Teradata to include additional&nbsp; info in the output of an <strong>explain</strong> command.&nbsp; The output from all subsequent <strong>explain</strong> commands </p><ul><li>qualify Spool File on join columns in the explain output</li><li>specify hash distribution column names for spool files.</li></ul><p>To turn off additional information in the output of the explain command just issue the following command.</p><p><strong>DIAGNOSTIC VERBOSEEXPLAIN NOT ON FOR SESSION;&nbsp; </strong></p><p>Below is another command that is quite helpful&nbsp;</p><p><strong>DIAGNOSTIC HELPSTATS ON FOR SESSION;</strong></p><p>The above command makes Teradata to include the collect statistics possibilities in the ouput of expplain command</p><p>To turn off collect statistics possibilities in the output of the explain command just issue the following command.</p><p><strong>DIAGNOSTIC HELPSTATS NOT ON FOR SESSION;</strong><br /></p>]]>
    </content>
</entry>
<entry>
    <title>An Introduction to Teradata components</title>
    <link rel="alternate" type="text/html" href="http://www.somberi.com/techblog/2007/11/an_introduction_to_teradata_co.php" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.somberi.com/nrk-mt/mt-atom.cgi/weblog/blog_id=5/entry_id=117" title="An Introduction to Teradata components" />
    <id>tag:somberi.com,2007:/techblog//5.117</id>
    
    <published>2007-11-04T22:19:32Z</published>
    <updated>2008-01-23T01:36:17Z</updated>
    
    <summary>This explains Teradata RDBMS components</summary>
    <author>
        <name>Ramakrishna Nemani</name>
        
    </author>
            <category term="General" />
            <category term="Ramakrishna Nemani" />
            <category term="Teradata" />
    
    <content type="html" xml:lang="en" xml:base="http://www.somberi.com/techblog/">
        <![CDATA[<p align="justify">Teradata is a relational database management system. A Teradata system has many components (hardware and software). A Teradata system contains one or more nodes. A node is a term for a general-purpose processing unit under the control of a single operating system. The basic building block for a Teradata system, the node is where the processing occurs for the database. </p><p align="justify">A node contains a large number of hardware and software components as explained below&hellip;<br /></p>]]>
        <![CDATA[<p align="justify"><strong>PDE<br /></strong>The PDE (Parallel Database Extensions) software layer runs the operating system on each node. It was created by NCR to support the parallel environment.</p><p align="justify"><strong>System Disks<br /></strong>System disks are contained on the node used for the following:<br />&bull;&nbsp;Operating system software<br />&bull;&nbsp;Teradata software <br />&bull;&nbsp;Application software <br />&bull;&nbsp;System dump space <br />Teradata database tables are stored on disk arrays, not on the system disks.</p><p align="justify"><strong>Memory<br /></strong>Vprocs share a free memory pool within a node. A segment of memory is allocated to a vproc for its use, then returned to the memory pool for use by another vproc. The free memory pool is a collection of memory available to the node. </p><p align="justify"><strong>Application<br /></strong>An application is software that accesses the Teradata RDBMS. It can run on various platforms: <br />&bull;&nbsp;Channel-attached client <br />&bull;&nbsp;LAN-attached client <br />&bull;&nbsp;Node </p><p align="justify"><strong>Vproc<br /></strong>A virtual processor or a vproc is a group of one or more software processes running under the operating system's multi-tasking environment:<br />&bull;&nbsp;On the UNIX operating system, a vproc is a collection of software processes.<br />&bull;&nbsp;On the Windows operating systems, a vproc is a single software process.</p><p align="justify">The two types of Teradata vprocs are:<br />&bull;&nbsp;AMP (Access Module Processor) <br />&bull;&nbsp;PE (Parsing Engine) </p><p align="justify">When vprocs communicate, they use BYNET hardware (on MPP systems), BYNET software, and PDE. The BYNET hardware and software carry vproc messages to and from a particular node. Within a node, the BYNET and PDE software deliver messages to and from the participating vprocs. </p><p align="justify"><strong>PE<br /></strong>PEs (Parsing Engines) are vprocs that receive SQL requests from the client and break the requests into steps. The PEs send the steps to the AMPs and subsequently return the answer to the client.</p><p align="justify"><strong>AMP<br /></strong>AMPs (Access Module Processors) are virtual processors (vprocs) that receive steps from PEs (Parsing Engines) and perform database functions to retrieve or update data. Each AMP is associated with one virtual disk (vdisk), where the data is stored. An AMP manages only its own vdisk, not the vdisk of any other AMP. </p><p align="justify"><strong>Vdisk (Virtual Disk)<br /></strong>A vdisk&nbsp; is the logical disk space that is managed by an AMP. Depending on the configuration, a vdisk may not be contained on the node; however, it is managed by an AMP, which is always a part of the node.<br />The vdisk is made up of 1 to 64 pdisks (user slices in UNIX or partitions in Windows NT, whose size and configuration vary based on RAID level). The pdisks logically combine to comprise the AMP's vdisk. Although an AMP can manage up to 64 pdisks, it controls only one vdisk. An AMP manages only its own vdisk, not the vdisk of any other AMP. </p><p align="justify"><strong>Channel Driver <br /></strong>Channel driver software is the means of communication between the PEs and applications running on channel-attached (mainframe) clients.</p><p align="justify"><strong>Gateway <br /></strong>The Teradata Gateway software is the means of communication between the PEs and applications running on a LAN-attached clients&nbsp; or A node in the system </p><p align="justify"><strong>BYNET<br /></strong>The BYNET (banyan network) is a combination of hardware and software that provides high performance networking between the nodes of a Teradata system. A dual-redundant, bi-directional, multi-staged network, the BYNET enables the nodes to communicate in a high speed, loosely-coupled fashion. It is based on banyan topology, a mathematically defined structure that has branches reminiscent of a banyan tree.<br />The BYNET is a high-speed interconnect (network) that enables multiple nodes in the system to communicate.</p><p align="justify">The BYNET hardware and software handle the communication between the vprocs. <br />&bull;&nbsp;Hardware: The nodes of an MPP system are connected with the BYNET hardware, consisting of BYNET boards and cables. <br />&bull;&nbsp;Software: The BYNET software is installed on every node. This BYNET driver is an interface between the PDE software and the BYNET hardware. </p><p align="justify">SMP systems do not contain BYNET hardware. The PDE and BYNET software emulates BYNET activity in a single-node environment. The SMP implementation is sometimes called &quot;boardless BYNET.&quot; <br /></p><p align="justify">Teradata uses different types of messages for the highest efficiency: <br />&bull;&nbsp;Broadcast: BYNET hardware delivers a message to all nodes in an MPP system. This is simulated in SMP systems using BYNET software. A single broadcast message consumes more BYNET bandwidth than a single point-to-point message, but sometimes a broadcast may be the most efficient for processing.<br />&bull;&nbsp;Point-to-Point: A single message to a single vproc is carried over BYNET hardware to the destination node, and relayed to or from a particular vproc using PDE software. Point-to-point messages enable the BYNET to be scalable because as the system grows, the capacity to handle point-to-point messages also grows.<br />&bull;&nbsp;Multicast: A message can be sent to several vprocs (multicast). The BYNET hardware first sends a broadcast message to all nodes. The PDE software on the receiving nodes determines which vprocs should receive the message and delivers it to those vprocs. Multicast messages give the system yet another method to deliver messages for the best performance<br />&nbsp;<br />A Teradata node requires three distinct pieces of software.</p><p align="justify"><strong>Operating System :&nbsp; <br /></strong>UNIX or Windows. Or Linux</p><p align="justify"><strong>The Parallel Database Extensions (PDE) :<br /></strong>The Parallel Database Extensions (PDE) software layer was added to the operating system by NCR to support the parallel software environment.</p><p align="justify"><strong>Teradata RDBMS aka Trusted Parallel Application (TPA)<br /></strong>A Trusted Parallel Application (TPA) uses PDE to implement virtual processors (vprocs). The Teradata RDBMS is classified as a TPA. The four components of the Teradata TPA are: <br />&bull;&nbsp;AMP <br />&bull;&nbsp;PE <br />&bull;&nbsp;Channel Driver <br />&bull;&nbsp;Teradata Gateway <br />&nbsp;<br /><strong>Access Module Processor (AMP)<br /></strong>AMPs (Access Module Processors) are virtual processors (vprocs) that receive steps from PEs (Parsing Engines) and perform database functions to retrieve or update data<br />AMP Worker Task Functions<br />The AWT functions in the AMP perform a number of operations, including: <br />&bull;&nbsp;Locking tables to ensure data consistency. <br />&bull;&nbsp;Executing AMP step operations such as select, insert, update, delete and sort. <br />&bull;&nbsp;Joining tables as required. <br />&bull;&nbsp;Executing end transaction steps as required to support multi-AMP operations. </p><p align="justify"><strong>AMP File System<br /></strong>The file system software accesses the data on the virtual disks. Each AMP uses the file system software to read from and write to the virtual disks.</p><p align="justify"><strong>AMP Console Utilities<br /></strong>The AMP software includes utilities to perform systems management functions such as:<br />&bull;&nbsp;Configure and reconfigure the system <br />&bull;&nbsp;Rebuild tables <br />&bull;&nbsp;Reveal details about locks and space status <br />&nbsp;<br /><strong>Parsing Engine (PE)<br /></strong>PEs (Parsing Engines) are vprocs that receive SQL requests from the client and break the requests into steps. The PEs send the steps to the AMPs and subsequently return the answer to the client.</p><p align="justify"><strong>PE Session Control&nbsp; <br /></strong>When you log on to the Teradata RDBMS through your application, the session control software on the PE establishes that session. Session control also manages and terminates sessions on that PE. </p><p align="justify"><strong>PE Parser/Optimizer<br /></strong>The Parser interprets an incoming Teradata SQL request and checks the syntax. The Parser decomposes the request into AMP steps, using the Optimizer to determine the most efficient way to access the data on the virtual disks (vdisks). <br />The Optimizer develops the &quot;least expensive&quot; plan (in terms of time and system resources) to return the requested response set. Processing alternatives are evaluated, and the fastest alternative is chosen. The selected alternative is converted to executable steps that will performed by the AMPs. Then, the Parser sends the steps to the dispatcher. </p><p align="justify"><strong>PE Dispatcher<br /></strong>The dispatcher is responsible for a number of tasks, depending on the operation it is performing: <br />&bull;&nbsp;Processing Requests: Controls the sequence in which the steps are executed and passes the steps to the AMPs through the BYNET. <br />&bull;&nbsp;Processing Responses: After the AMPs process the steps, the dispatcher builds a response message and sends the response back to the user.&nbsp;</p><p align="justify"><strong>Channel Driver <br /></strong>Channel Driver software is the means of communication between an application and the PEs assigned to channel-attached clients. There is one Channel Driver per node. </p><p align="justify"><strong>Teradata Gateway<br /></strong>Teradata Gateway software is the means of communication between an application and the PEs assigned to network-attached clients. There is one Teradata Gateway per node.<br />&nbsp;<br /><strong>User Access<br /></strong>Clients communicate with the Teradata RDBMS in three ways: <br />&bull;&nbsp;Channel <br />&bull;&nbsp;Network<br />&bull;&nbsp;Node</p><p align="justify"><strong>Channel<br /></strong>Communication from applications on the mainframe goes through the Channel Driver.<br />Traffic and communications between client applications on the mainframe and the Teradata database are managed by the Teradata Director Program (TDP) software.</p><p align="justify"><strong>Network<br /></strong>Communication from applications on a network-attached client goes through the Teradata Gateway.<br />Traffic and communication between network-attached client applications and the Teradata database are managed by either: ODBC or CLIv2.</p><p align="justify"><strong>Node <br /></strong>If you install application software on a node, it will be treated like an application on a network-attached client. In other words, communications from applications on the node go through the Teradata Gateway. </p><p align="justify">To summarize, users can access data in the Teradata RDBMS through an application on both channel-attached and network-attached clients. Additionally, the node itself can act as a client. Teradata client software is installed on each client (channel-attached, network-attached, or node) and communicates with RDBMS software on the node. <br />&nbsp;<br /><strong>Primary Indexes <br /></strong>The Teradata Database distributes the data in each table&nbsp; across all AMPs on a system.&nbsp; Since each amp is responsible for managing it&rsquo;s own vdisk, it effectively means distributing data across disks automatically. This is one of the major differences between Teradata and other RDBMSs </p><p align="justify">Teradata assigns rows to AMPs based on the value of their primary index. The determination of which hash bucket, and hence which AMP the row is to be stored on, is made solely on the row hash value of its primary index. Each Teradata Database table must have a primary index.</p>]]>
    </content>
</entry>
<entry>
    <title>RMAN Disaster Recovery script (rman_dr.ksh)</title>
    <link rel="alternate" type="text/html" href="http://www.somberi.com/techblog/2007/07/rman_disaster_recovery_script.php" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.somberi.com/nrk-mt/mt-atom.cgi/weblog/blog_id=5/entry_id=63" title="RMAN Disaster Recovery script (rman_dr.ksh)" />
    <id>tag:somberi.com,2007:/techblog//5.63</id>
    
    <published>2007-07-03T20:17:46Z</published>
    <updated>2008-01-23T01:37:35Z</updated>
    
    <summary>This script is intended to provide a mechanism for disaster recovery.</summary>
    <author>
        <name>Ramakrishna Nemani</name>
        
    </author>
            <category term="DBA" />
            <category term="Oracle" />
            <category term="Ramakrishna Nemani" />
            <category term="rman scripts" />
    
    <content type="html" xml:lang="en" xml:base="http://www.somberi.com/techblog/">
        <![CDATA[This script is intended to provide a mechanism for disaster recovery. Output log of this script is given as another entry&nbsp; which you can check]]>
        <![CDATA[<p>#!/bin/ksh<br />. ~/.profile<br />##<br />## script name : rman_dr.ksh<br />## Author : Ramakrishna Nemani<br />## <br />## Purpose :<br />## This script is for restoring the complete database from tape. This could be used<br />## after a disaster to do a disaster recovery. It assumes that a new unix box has <br />## been set up and Oracle software has been installed and all the directory structures<br />## have been restored by the UNIX admins. This script does not use rman recovery catalog.<br />##<br />## Note :<br />## You have to replace the DBID value with the DBID that you are attempting to restore and recover<br />## You need to login as a unix user id that belongs to the dba group and run this script<br />## I have tested this script only on Oracle 10g on an IBM AIX platform. Use it at your own risk.<br />##<br />## This is an example or sample script<br />##<br /></p><p>rman &lt;&lt; EOF &gt; ./cmad_dr.log</p><p>CONNECT TARGET /</p><p>STARTUP FORCE NOMOUNT;</p><p>##<br />## set dbid because we are not using an rman recovery catalog<br />##<br />SET DBID 1522268517 ;</p><p>##<br />## Specify AUTOBACKUP Format<br />##<br />SET CONTROLFILE AUTOBACKUP FORMAT FOR DEVICE TYPE SBT_TAPE TO '%F';<br />##<br />## Restore spfile from autobackup first<br />##<br />RUN {<br />ALLOCATE CHANNEL tape_1 DEVICE TYPE sbt <br />PARMS 'ENV=(TDPO_OPTFILE=/usr/tivoli/tsm/client/oracle/bin64/tdpo.opt)' <br />FORMAT '%u_%p_%c' ;<br />RESTORE SPFILE FROM AUTOBACKUP&nbsp; ;<br />}<br />##<br />## Restart the database with newly restored SPFILE<br />##<br />SHUTDOWN IMMEDIATE;<br />STARTUP NOMOUNT;</p><p>##<br />## Now restore controlfile from autobackup <br />##<br />RUN {<br />ALLOCATE CHANNEL tape_1 DEVICE TYPE sbt <br />PARMS 'ENV=(TDPO_OPTFILE=/usr/tivoli/tsm/client/oracle/bin64/tdpo.opt)' <br />FORMAT '%u_%p_%c' ;<br />RESTORE CONTROLFILE FROM AUTOBACKUP ;<br />}</p><p>##<br />## Mount the database, restore and recover<br />##<br />ALTER DATABASE MOUNT ;</p><p>RUN {<br />ALLOCATE CHANNEL tape_1 DEVICE TYPE sbt <br />PARMS 'ENV=(TDPO_OPTFILE=/usr/tivoli/tsm/client/oracle/bin64/tdpo.opt)' <br />FORMAT '%u_%p_%c' ;<br />RESTORE DATABASE&nbsp; ;<br />RECOVER DATABASE&nbsp; ;<br />}<br />##<br />## Open the database, if restore and recover are successful<br />##</p><p>EOF</p><p>&nbsp;</p>]]>
    </content>
</entry>
<entry>
    <title>RMAN tape backup script</title>
    <link rel="alternate" type="text/html" href="http://www.somberi.com/techblog/2007/07/rman_tape_backup_script.php" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.somberi.com/nrk-mt/mt-atom.cgi/weblog/blog_id=5/entry_id=54" title="RMAN tape backup script" />
    <id>tag:somberi.com,2007:/techblog//5.54</id>
    
    <published>2007-07-01T17:55:01Z</published>
    <updated>2008-01-23T01:39:10Z</updated>
    
    <summary>This script  does a backup of backupset to tape.</summary>
    <author>
        <name>Ramakrishna Nemani</name>
        
    </author>
            <category term="DBA" />
            <category term="Oracle" />
            <category term="Ramakrishna Nemani" />
            <category term="rman scripts" />
    
    <content type="html" xml:lang="en" xml:base="http://www.somberi.com/techblog/">
        <![CDATA[This script&nbsp;&nbsp;does a backup of backupset to tape.]]>
        <![CDATA[<p>#!/bin/ksh<br />. ~/.profile</p><p>##<br />## script name : rman_tape_bkup.ksh<br />## Author : Ramakrishna Nemani<br />## <br />## Purpose :<br />## This script&nbsp; takes database sid as a command line argument and does a backup of<br />## backupset to tape. It backs up to the tape device using automatic channel <br />## allocation. Make sure you have configured the default device and channels. You<br />## can find the configuration that I have used in a script called rman_config.ksh<br />##<br />## Other Features :<br />## This script emails the backup log to the email ids set up in the email configuration<br />## file email configuration file is just a text file containing the email ids to where <br />## the backup log will be emailed to.<br />## This script creates a log file on the datbase server where this script is hosted.<br />##<br />## It also creates and uses a lockfile to make sure no other rman process is running for<br />## the database sid that was supplied through the command line. Should this script fail<br />## for any reason, it does not remove the lockfile so that no rman process can run for this<br />## database until the error is fixed and the lock file is removed manually<br />##<br />## Note :<br />## You need to login as a unix user id that belongs to the dba group and run this script<br />## There are a bunch of modifiable parameters in this script that you should modify to <br />## reflect your environment.<br />## I have tested this script on only Oracle 10g on an IBM AIX platform. Use it at your own risk.<br />##<br />## This is an example or sample script<br />##</p><p>##<br />## Make sure ORACLE_SID is passed as an argument<br />##</p><p>if (( $# &lt; 1 ))<br />then<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo Error Missing Arguement, Please supply Oracle Sid<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo Usage: $0 ORACLE_SID<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit<br />fi</p><p>export ORACLE_SID=$1</p><p>## ----------------------------------------------------------------------------------<br />##<br />## -------------------- Start of modifiable parameters ------------------------------<br />##<br />## Change the values for the following parameters to reflect your environment<br />##<br />##</p><p>LOG_DIR=&quot;/u01/oracle/admin/rman&quot;<br />LOCKFILE=&quot;${LOG_DIR}/$ORACLE_SID.lock&quot;<br />EMAIL_INFO_FILE=&quot;${LOG_DIR}/${ORACLE_SID}_email.cfg&quot;<br />SENDER=&quot;<a href="mailto:rman@`hostname">rman@`hostname</a>&quot;<br />CURR_DATE=`date +&quot;%Y%m%d_%H%M%S&quot;`<br />##<br />## using two seperate files instead of one for keeping the logs<br />## The LOGFILE will have log from just the latest run<br />## The LOGARCFILE will have the cumulative log <br />##</p><p>## LOGFILE=&quot;${LOG_DIR}/rman_tape_bkup_$CURR_DATE.log&quot;</p><p>LOGFILE=&quot;${LOG_DIR}/rman_tape_bkup.$ORACLE_SID.log&quot; <br />LOGARCFILE=&quot;${LOG_DIR}/rman_tape_bkup.$ORACLE_SID.log.arc&quot;</p><p>##<br />## using two seperate files instead of one for keeping the errors<br />## The EMAILFILE will have errors if any from just the latest run<br />## The EMAILARCFILE will have the cumulative errors <br />##</p><p>EMAILFILE=&quot;${LOG_DIR}/rman_tape_bkup.$ORACLE_SID.email&quot; <br />EMAILARCFILE=&quot;${LOG_DIR}/rman_tape_bkup.$ORACLE_SID.email.arc&quot; </p><p>## --------------------------------------------------------------------------------<br />##<br />## -------------------- End of modifiable parameters ------------------------------<br />##<br />## --------------------------------------------------------------------------------</p><p>##<br />## Make sure no other rman process is running for this ORACLE_SID<br />##</p><p>echo -------------------------------------------------------------- &gt; $LOGFILE<br />date &gt;&gt; $LOGFILE<br />echo ---------------- rman_tape_bkup.ksh started ------------------ &gt;&gt; $LOGFILE</p><p>while [ 1 ]<br />do</p><p><br />if [&nbsp; -e&nbsp; $LOCKFILE ]<br />then</p><p>##<br />## Some rman process is running. Check again after 3 minutes<br />##<br />&nbsp;echo &quot;$LOCKFILE exists. Will check again after 3 minutes&quot; &gt;&gt; $LOGFILE<br />&nbsp;echo&nbsp; &gt;&gt; $LOGFILE<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sleep 180</p><p>else</p><p>##<br />## No rman process is running. Create a lock file<br />##</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo Do not remove this file. This is a lock file for $ORACLE_SID &gt; $LOCKFILE<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break<br />fi</p><p>done</p><p>rman &lt;&lt;EOF&nbsp;&nbsp; &gt;&gt; $LOGFILE<br />connect target / ;</p><p>SHOW ALL ;</p><p>## RUN <br />## {<br />&nbsp;## ALLOCATE CHANNEL t1 type 'SBT_TAPE' parms 'ENV=(TDPO_OPTFILE=/usr/tivoli/tsm/client/oracle/bin64/tdpo.opt)' format '%u_%p_%c';<br />&nbsp;## BACKUP BACKUPSET ALL ;<br />## }</p><p>BACKUP DEVICE TYPE SBT BACKUPSET ALL ;</p><p>REPORT SCHEMA ;</p><p>EXIT ;</p><p>EOF</p><p>rmanstatus=$?</p><p>if (( $rmanstatus &gt; 0 ))<br />then<br />&nbsp;if [ ! -e&nbsp; $EMAIL_INFO_FILE ]<br />&nbsp;then<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;echo &quot;To:rnemani@na.cokecce.com&quot; &gt; $EMAIL_INFO_FILE<br />&nbsp;fi</p><p>&nbsp;cat $EMAIL_INFO_FILE &gt; $EMAILFILE<br />&nbsp;echo &quot;Subject: The $0 script failed for $ORACLE_SID !!!&quot; &gt;&gt; $EMAILFILE</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo &gt;&gt; $EMAILFILE<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; date &gt;&gt; $EMAILFILE<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo&nbsp; &quot;rman error!!! ...&quot; &gt;&gt; $EMAILFILE<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo&nbsp; &quot;Not removed the lock file : $LOCKFILE &quot; &gt;&gt; $EMAILFILE<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo&nbsp; &quot;Please fix the error and remove the lock file&quot; &gt;&gt; $EMAILFILE<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo&nbsp; &quot;before re-running the script again!!!&quot; &gt;&gt; $EMAILFILE<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo &gt;&gt; $EMAILFILE</p><p>&nbsp;grep -i 'RMAN-'&nbsp; $LOGFILE &gt;&gt; $EMAILFILE<br />&nbsp;grep -i 'ORA-'&nbsp;&nbsp; $LOGFILE &gt;&gt; $EMAILFILE<br />&nbsp;grep -i 'sbt'&nbsp;&nbsp;&nbsp; $LOGFILE &gt;&gt; $EMAILFILE<br />&nbsp;grep -i 'tsm'&nbsp;&nbsp;&nbsp; $LOGFILE &gt;&gt; $EMAILFILE</p><p>&nbsp;sendmail -F &quot;$SENDER&quot; -t &lt; $EMAILFILE</p><p>&nbsp;cat $EMAILFILE &gt;&gt; $EMAILARCFILE</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit 12<br />fi</p><p>echo -------------------------------------------------------------- &gt;&gt; $LOGFILE<br />date &gt;&gt; $LOGFILE<br />echo ---------------- rman_tape_bkup.ksh completed ---------------- &gt;&gt; $LOGFILE<br />echo &gt;&gt; $LOGFILE</p><p>cat $EMAIL_INFO_FILE &gt; $EMAILFILE<br />echo &quot;Subject: The $0 script completed successfully for $ORACLE_SID !!!&quot; &gt;&gt; $EMAILFILE<br />cat $LOGFILE &gt;&gt; $EMAILFILE</p><p>sendmail -F &quot;$SENDER&quot; -t &lt; $EMAILFILE</p><p>cat $EMAILFILE &gt;&gt; $EMAILARCFILE</p><p>cat $LOGFILE &gt;&gt; $LOGARCFILE</p><p>##<br />## Remove lock file to allow other rman processs for this ORACLE_SID to run, if any<br />##</p><p>rm $LOCKFILE</p><p>## --------------------------------------------------------------------------------<br />## End of&nbsp; rman_tape_bkup.ksh<br />## --------------------------------------------------------------------------------</p><p>&nbsp;</p>]]>
    </content>
</entry>
<entry>
    <title>RMAN configuration script</title>
    <link rel="alternate" type="text/html" href="http://www.somberi.com/techblog/2007/07/rman_configuration_script.php" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.somberi.com/nrk-mt/mt-atom.cgi/weblog/blog_id=5/entry_id=53" title="RMAN configuration script" />
    <id>tag:somberi.com,2007:/techblog//5.53</id>
    
    <published>2007-07-01T17:19:25Z</published>
    <updated>2008-01-23T01:40:06Z</updated>
    
    <summary>This script configures persistent rman settings.</summary>
    <author>
        <name>Ramakrishna Nemani</name>
        
    </author>
            <category term="DBA" />
            <category term="Oracle" />
            <category term="Ramakrishna Nemani" />
            <category term="rman scripts" />
    
    <content type="html" xml:lang="en" xml:base="http://www.somberi.com/techblog/">
        <![CDATA[This script configures&nbsp;persistent rman settings]]>
        <![CDATA[<p>#!/bin/ksh<br />. ~/.profile<br />##<br />## script name : rman_config.ksh<br />## Author : Ramakrishna Nemani<br />## <br />## Purpose :<br />## This script&nbsp; takes database sid as a command line argument and configures<br />## persistent rman settings<br />##<br />## Other Features :<br />## This script creates a log file on the datbase server where this script is hosted.<br />##<br />## It also creates and uses a lockfile to make sure no other rman process is running for<br />## the database sid that was supplied through the command line. Should this script fail<br />## for any reason, it does not remove the lockfile so that no rman process can run for this<br />## database until the error is fixed and the lock file is removed manually.<br />##<br />##<br />## Note :<br />## You need to login as a unix user id that belongs to dba group and run this script.<br />## For device type sbt , the setting that I have here is for our TSM setup. Your setting may differ.<br />## I have tested this script on only Oracle 10g on an IBM AIX platform. Use it at your own risk.<br />##<br />## This is an example or sample script<br />##</p><p>##<br />## Make sure ORACLE_SID is passed as an argument<br />## </p><p>if (( $# &lt; 1 ))<br />then<br />&nbsp;echo<br />&nbsp;echo Error Missing Arguement, Please supply Oracle Sid<br />&nbsp;echo<br />&nbsp;echo Usage: $0 ORACLE_SID<br />&nbsp;echo<br />&nbsp;exit<br />fi</p><p>export ORACLE_SID=$1<br />LOG_DIR=&quot;.&quot;</p><p>##<br />## Make sure no other rman process is running for this ORACLE_SID<br />##</p><p>LOCKFILE=&quot;${LOG_DIR}/$ORACLE_SID.lock&quot;</p><p>while [ 1 ]<br />do</p><p>if [&nbsp; -e&nbsp; $LOCKFILE ]<br />then</p><p>##<br />## Some rman process is running. Check again after 3 minutes<br />##<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sleep 80<br />else</p><p>##<br />## No rman process is running. Create the lock file<br />##<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo Do not remove this file. This is a lock file for $ORACLE_SID &gt; $LOCKFILE<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break<br />fi</p><p>done</p><p>CURR_DATE=`date +&quot;%Y%m%d_%H%M%S&quot;`</p><p>##<br />## using two seperate files instead of one <br />## The LOGFILE will have log from just the latest run<br />## The ARCFILE will have cumulative log <br />##</p><p><br />## LOGFILE=&quot;${LOG_DIR}/rman_config_$CURR_DATE.$ORACLE_SID.log&quot;</p><p>LOGFILE=&quot;${LOG_DIR}/rman_config.$ORACLE_SID.log&quot;<br />ARCFILE=&quot;${LOG_DIR}/rman_config.$ORACLE_SID.arc&quot;</p><p>##<br />## Run rman config commands<br />## </p><p>rman &lt;&lt;EOF&nbsp; &gt; $LOGFILE<br />connect target / ;</p><p>CONFIGURE RETENTION POLICY TO REDUNDANCY 1;<br />CONFIGURE BACKUP OPTIMIZATION ON;</p><p>CONFIGURE CONTROLFILE AUTOBACKUP ON;<br />CONFIGURE CONTROLFILE AUTOBACKUP <br />FORMAT FOR DEVICE TYPE DISK TO 'controlfile_%F';</p><p>CONFIGURE DEFAULT DEVICE TYPE TO DISK ;</p><p>CONFIGURE DEVICE TYPE DISK PARALLELISM 4 BACKUP TYPE TO BACKUPSET ;</p><p>CONFIGURE DEVICE TYPE sbt PARALLELISM 4 BACKUP TYPE TO BACKUPSET ;</p><p>CONFIGURE CHANNEL DEVICE TYPE sbt <br />PARMS 'ENV=(TDPO_OPTFILE=/usr/tivoli/tsm/client/oracle/bin64/tdpo.opt)' <br />FORMAT '%u_%p_%c' ;</p><p>EOF</p><p>cat $LOGFILE &gt;&gt; $ARCFILE</p><p>##<br />## Remove lock file to allow other rman processs for this ORACLE_SID to run, if any<br />##</p><p>rm $LOCKFILE</p><p>## ---------------------------------------------------------------------------------<br />## End of&nbsp; rman_config.ksh<br />## ---------------------------------------------------------------------------------<br /></p>]]>
    </content>
</entry>
<entry>
    <title>RMAN archive logs backup script</title>
    <link rel="alternate" type="text/html" href="http://www.somberi.com/techblog/2007/07/rman_archive_logs_script.php" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.somberi.com/nrk-mt/mt-atom.cgi/weblog/blog_id=5/entry_id=52" title="RMAN archive logs backup script" />
    <id>tag:somberi.com,2007:/techblog//5.52</id>
    
    <published>2007-07-01T17:16:10Z</published>
    <updated>2008-01-23T01:49:43Z</updated>
    
    <summary>This script does  archive logs backup using rman.</summary>
    <author>
        <name>Ramakrishna Nemani</name>
        
    </author>
            <category term="DBA" />
            <category term="Oracle" />
            <category term="Ramakrishna Nemani" />
            <category term="rman scripts" />
    
    <content type="html" xml:lang="en" xml:base="http://www.somberi.com/techblog/">
        <![CDATA[This script does&nbsp; archive logs&nbsp;backup using rman.]]>
        <![CDATA[<p>#!/bin/ksh<br />. ~/.profile</p><p>##<br />## script name : rman_arch_bkup.ksh<br />## Author : Ramakrishna Nemani<br />## <br />## Purpose :<br />## This script&nbsp; takes database sid as a command line argument and does&nbsp; archive logs<br />## backup. It backs up to the default device using automatic channel allocation.<br />## Make sure you have configured the default device and channels. You can find the <br />## configuration that I have used in a script called rman_config.ksh<br />##<br />## Other Features :<br />## This script emails the backup log to the email ids set up in the email configuration<br />## file email configuration file is just a text file containing the email ids to where <br />## the backup log will be emailed to.<br />## This script creates a log file on the datbase server where this script is hosted.<br />##<br />## It also creates and uses a lockfile to make sure no other rman process is running for<br />## the database sid that was supplied through the command line. Should this script fail<br />## for any reason, it does not remove the lockfile so that no rman process can run for this<br />## database until the error is fixed and the lock file is removed manually<br />##<br />##<br />## Note :<br />## You need to login as a unix user id that belongs to the dba group and run this script<br />## There are a bunch of modifiable parameters in this script that you should modify to <br />## reflect your environment.<br />## I have tested this script on only Oracle 10g on an IBM AIX platform. Use it at your own risk.<br />##<br />## This is an example or sample script<br />##</p><p>##<br />## Make sure ORACLE_SID is passed as an argument<br />##</p><p>if (( $# &lt; 1 ))<br />then<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo Error Missing Arguement, Please supply Oracle Sid<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo Usage: $0 ORACLE_SID<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit<br />fi</p><p>export ORACLE_SID=$1</p><p>## ----------------------------------------------------------------------------------<br />##<br />## -------------------- Start of modifiable parameters ------------------------------<br />##<br />## Change the values for the following parameters to reflect your environment<br />##<br />##</p><p>LOG_DIR=&quot;/u01/oracle/admin/rman&quot;<br />LOCKFILE=&quot;${LOG_DIR}/$ORACLE_SID.lock&quot;<br />EMAIL_INFO_FILE=&quot;${LOG_DIR}/${ORACLE_SID}_email.cfg&quot;<br />SENDER=&quot;<a href="mailto:rman@`hostname">rman@`hostname</a>&quot;<br />CURR_DATE=`date +&quot;%Y%m%d_%H%M%S&quot;`<br />##<br />## using two seperate files instead of one for keeping the logs<br />## The LOGFILE will have log from just the latest run<br />## The LOGARCFILE will have the cumulative log <br />##</p><p>## LOGFILE=&quot;${LOG_DIR}/rman_arch_bkup_$CURR_DATE.log&quot;</p><p>LOGFILE=&quot;${LOG_DIR}/rman_arch_bkup.$ORACLE_SID.log&quot; <br />LOGARCFILE=&quot;${LOG_DIR}/rman_arch_bkup.$ORACLE_SID.log.arc&quot;</p><p>##<br />## using two seperate files instead of one for keeping the errors<br />## The EMAILFILE will have errors if any from just the latest run<br />## The EMAILARCFILE will have the cumulative errors <br />##</p><p>EMAILFILE=&quot;${LOG_DIR}/rman_arch_bkup.$ORACLE_SID.email&quot; <br />EMAILARCFILE=&quot;${LOG_DIR}/rman_arch_bkup.$ORACLE_SID.email.arc&quot; <br />## --------------------------------------------------------------------------------<br />##<br />## -------------------- End of modifiable parameters ------------------------------<br />##<br />## --------------------------------------------------------------------------------</p><p><br />##<br />## Make sure no other rman process is running for this ORACLE_SID<br />##</p><p>echo --------------------------------------------------------- &gt; $LOGFILE<br />date &gt;&gt; $LOGFILE<br />echo ---------------- rman_arch_bkup.ksh started ------------------ &gt;&gt; $LOGFILE</p><p>while [ 1 ]<br />do</p><p><br />if [&nbsp; -e&nbsp; $LOCKFILE ]<br />then</p><p>##<br />## Some rman process is running. Check again after 3 minutes<br />##<br />&nbsp;echo &quot;$LOCKFILE exists. Will check again after 3 minutes&quot; &gt;&gt; $LOGFILE<br />&nbsp;echo&nbsp; &gt;&gt; $LOGFILE<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sleep 180</p><p>else</p><p>##<br />## No rman process is running. Create a lock file<br />##</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo Do not remove this file. This is a lock file for $ORACLE_SID &gt; $LOCKFILE<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break<br />fi</p><p>done</p><p>rman &lt;&lt;EOF&nbsp;&nbsp; &gt;&gt; $LOGFILE<br />connect target / ;</p><p>SHOW ALL ;</p><p>## RUN <br />## {<br />&nbsp;## ALLOCATE CHANNEL c1 DEVICE TYPE DISK;<br />&nbsp;## BACKUP DATABASE FILESPERSET 1 PLUS ARCHIVELOG DELETE INPUT;<br />&nbsp;## DELETE NOPROMPT OBSOLETE; <br />## }<br />BACKUP ARCHIVELOG ALL DELETE INPUT;<br />DELETE NOPROMPT OBSOLETE; </p><p>REPORT SCHEMA ;<br />REPORT UNRECOVERABLE;</p><p>EXIT ;</p><p>EOF</p><p>rmanstatus=$?</p><p>if (( $rmanstatus &gt; 0 ))<br />then<br />&nbsp;if [ ! -e&nbsp; $EMAIL_INFO_FILE ]<br />&nbsp;then<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;echo &quot;To:rnemani@na.cokecce.com&quot; &gt; $EMAIL_INFO_FILE<br />&nbsp;fi</p><p>&nbsp;cat $EMAIL_INFO_FILE &gt; $EMAILFILE<br />&nbsp;echo &quot;Subject: The $0 script failed for $ORACLE_SID !!!&quot; &gt;&gt; $EMAILFILE</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo &gt;&gt; $EMAILFILE<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; date &gt;&gt; $EMAILFILE<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo&nbsp; &quot;rman error!!! ...&quot; &gt;&gt; $EMAILFILE<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo&nbsp; &quot;Not removed the lock file : $LOCKFILE &quot; &gt;&gt; $EMAILFILE<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo&nbsp; &quot;Please fix the error and remove the lock file&quot; &gt;&gt; $EMAILFILE<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo&nbsp; &quot;before re-running the script again!!!&quot; &gt;&gt; $EMAILFILE<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo &gt;&gt; $EMAILFILE</p><p>&nbsp;grep -i 'RMAN-'&nbsp; $LOGFILE &gt;&gt; $EMAILFILE<br />&nbsp;grep -i 'ORA-'&nbsp;&nbsp; $LOGFILE &gt;&gt; $EMAILFILE<br />&nbsp;grep -i 'sbt'&nbsp;&nbsp;&nbsp; $LOGFILE &gt;&gt; $EMAILFILE<br />&nbsp;grep -i 'tsm'&nbsp;&nbsp;&nbsp; $LOGFILE &gt;&gt; $EMAILFILE</p><p>&nbsp;sendmail -F &quot;$SENDER&quot; -t &lt; $EMAILFILE</p><p>&nbsp;cat $EMAILFILE &gt;&gt; $EMAILARCFILE</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit 12<br />fi</p><p>echo --------------------------------------------------------- &gt;&gt; $LOGFILE<br />date &gt;&gt; $LOGFILE<br />echo ---------------- rman_arch_bkup.ksh completed ---------------- &gt;&gt; $LOGFILE<br />echo &gt;&gt; $LOGFILE</p><p>cat $EMAIL_INFO_FILE &gt; $EMAILFILE<br />echo &quot;Subject: The $0 script completed successfully for $ORACLE_SID !!!&quot; &gt;&gt; $EMAILFILE<br />cat $LOGFILE &gt;&gt; $EMAILFILE</p><p>sendmail -F &quot;$SENDER&quot; -t &lt; $EMAILFILE</p><p>cat $EMAILFILE &gt;&gt; $EMAILARCFILE</p><p>cat $LOGFILE &gt;&gt; $LOGARCFILE</p><p>##<br />## Remove lock file to allow other rman processs for this ORACLE_SID to run, if any<br />##<br />rm $LOCKFILE</p><p>## ----------------------------------------------------------------------------------<br />## End of&nbsp; rman_arch_bkup.ksh<br />## ----------------------------------------------------------------------------------</p><p>&nbsp;</p>]]>
    </content>
</entry>
<entry>
    <title>RMAN complete database backup script</title>
    <link rel="alternate" type="text/html" href="http://www.somberi.com/techblog/2007/07/rman_backup_script.php" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.somberi.com/nrk-mt/mt-atom.cgi/weblog/blog_id=5/entry_id=51" title="RMAN complete database backup script" />
    <id>tag:somberi.com,2007:/techblog//5.51</id>
    
    <published>2007-07-01T17:11:34Z</published>
    <updated>2008-01-23T01:50:38Z</updated>
    
    <summary>This script does a full database backup including the archive logs.</summary>
    <author>
        <name>Ramakrishna Nemani</name>
        
    </author>
            <category term="DBA" />
            <category term="Oracle" />
            <category term="Ramakrishna Nemani" />
            <category term="rman scripts" />
    
    <content type="html" xml:lang="en" xml:base="http://www.somberi.com/techblog/">
        <![CDATA[This script does a full database&nbsp;backup including the archive logs.]]>
        <![CDATA[<p>#!/bin/ksh<br />. ~/.profile<br />##<br />## script name : rman_bkup.ksh<br />## Author : Ramakrishna Nemani<br />## <br />## Purpose :<br />## This script&nbsp; takes database sid as a command line argument and does a full database <br />## backup including the archive logs. It backs up to the default device using automatic <br />## channel allocation. Make sure you have configured the default device and channels. <br />## You can find the configuration that I have used in a script called rman_config.ksh<br />##<br />## Other Features :<br />## This script emails the backup log to the email ids set up in the email configuration<br />## file email configuration file is just a text file containing the email ids to where <br />## the backup log will be emailed to.<br />## This script creates a log file on the datbase server where this script is hosted.<br />##<br />## It also creates and uses a lockfile to make sure no other rman process is running for<br />## the database sid that was supplied through the command line. Should this script fail<br />## for any reason, it does not remove the lockfile so that no rman process can run for this<br />## database until the error is fixed and the lock file is removed manually<br />##<br />##<br />## Note :<br />## You need to login as a unix user id that belongs to the dba group and run this script<br />## There are a bunch of modifiable parameters in this script that you should modify to <br />## reflect your environment.<br />## I have tested this script on only Oracle 10g on an IBM AIX platform. Use it at your own risk.<br />##<br />## This is an example or sample script<br />##</p><p><br />##<br />## Make sure ORACLE_SID is passed as an argument<br />##</p><p>if (( $# &lt; 1 ))<br />then<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo Error Missing Arguement, Please supply database sid (Oracle Sid)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo Usage: $0 ORACLE_SID<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit<br />fi</p><p>export ORACLE_SID=$1</p><p>## ----------------------------------------------------------------------------------<br />##<br />## -------------------- Start of modifiable parameters ------------------------------<br />##<br />## Change the values for the following parameters to reflect your environment<br />##<br />##<br />LOG_DIR=&quot;/u01/oracle/admin/rman&quot;<br />LOCKFILE=&quot;${LOG_DIR}/$ORACLE_SID.lock&quot;<br />EMAIL_INFO_FILE=&quot;${LOG_DIR}/${ORACLE_SID}_email.cfg&quot;<br />SENDER=&quot;<a href="mailto:rman@`hostname">rman@`hostname</a>&quot;<br />CURR_DATE=`date +&quot;%Y%m%d_%H%M%S&quot;`</p><p>##<br />## using two seperate files instead of one for keeping the logs<br />## The LOGFILE will have log from just the latest run<br />## The LOGARCFILE will have the cumulative log <br />##</p><p>LOGFILE=&quot;${LOG_DIR}/rman_bkup.$ORACLE_SID.log&quot; <br />LOGARCFILE=&quot;${LOG_DIR}/rman_bkup.$ORACLE_SID.log.arc&quot;</p><p>##<br />## using two seperate files instead of one for keeping the errors<br />## The EMAILFILE will have errors if any from just the latest run<br />## The EMAILARCFILE will have the cumulative errors <br />##</p><p>EMAILFILE=&quot;${LOG_DIR}/rman_bkup.$ORACLE_SID.email&quot; <br />EMAILARCFILE=&quot;${LOG_DIR}/rman_bkup.$ORACLE_SID.email.arc&quot; <br />## -----------------------------------------------------------------------------------<br />##<br />## -------------------- End of modifiable parameters -----------------------------<br />##<br />## ------------------------------------------------------------------------------------</p><p><br />##<br />## Make sure no other rman process is running for this ORACLE_SID<br />##</p><p>echo --------------------------------------------------------- &gt; $LOGFILE<br />date &gt;&gt; $LOGFILE<br />echo ---------------- rman_bkup.ksh started ------------------ &gt;&gt; $LOGFILE</p><p>while [ 1 ]<br />do</p><p><br />if [&nbsp; -e&nbsp; $LOCKFILE ]<br />then</p><p>##<br />## Some rman process is running. Check again after 3 minutes<br />##<br />&nbsp;echo &quot;$LOCKFILE exists. Will check again after 3 minutes&quot; &gt;&gt; $LOGFILE<br />&nbsp;echo&nbsp; &gt;&gt; $LOGFILE<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sleep 180</p><p>else</p><p>##<br />## No rman process is running. Create a lock file<br />##</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo Do not remove this file. This is a lock file for $ORACLE_SID &gt; $LOCKFILE<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break<br />fi</p><p>done</p><p>echo $ORACLE_SID &gt;&gt; $LOGFILE<br />whoami &gt;&gt; $LOGFILE<br />which rman &gt;&gt; $LOGFILE</p><p>rman &lt;&lt;EOF&nbsp;&nbsp; &gt;&gt; $LOGFILE</p><p>CONNECT TARGET /&nbsp; ;</p><p>SHOW ALL ;</p><p>BACKUP DATABASE FILESPERSET 1 PLUS ARCHIVELOG DELETE INPUT;<br />DELETE NOPROMPT OBSOLETE; </p><p>REPORT SCHEMA ;<br />REPORT UNRECOVERABLE ;</p><p>EXIT ;</p><p>EOF</p><p>rmanstatus=$?</p><p>if (( $rmanstatus &gt; 0 ))<br />then<br />&nbsp;if [ ! -e&nbsp; $EMAIL_INFO_FILE ]<br />&nbsp;then<br />##<br />## The following line is executed if the Email config file is not set up.<br />## Replace <a href="mailto:emailid@defaultemail.com">emailid@defaultemail.com</a> with the email id to where the email<br />## needs to be sent.<br />##<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;echo &quot;To:emailid@defaultemail.com&quot; &gt; $EMAIL_INFO_FILE<br />&nbsp;fi</p><p>&nbsp;cat $EMAIL_INFO_FILE &gt; $EMAILFILE<br />&nbsp;echo &quot;Subject: The $0 script failed for $ORACLE_SID !!!&quot; &gt;&gt; $EMAILFILE</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo &gt;&gt; $EMAILFILE<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; date &gt;&gt; $EMAILFILE<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo&nbsp; &quot;rman error!!! ...&quot; &gt;&gt; $EMAILFILE<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo&nbsp; &quot;Not removed the lock file : $LOCKFILE &quot; &gt;&gt; $EMAILFILE<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo&nbsp; &quot;Please fix the error and remove the lock file&quot; &gt;&gt; $EMAILFILE<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo&nbsp; &quot;before re-running the script again!!!&quot; &gt;&gt; $EMAILFILE<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo &gt;&gt; $EMAILFILE</p><p>&nbsp;grep -i 'RMAN-'&nbsp; $LOGFILE &gt;&gt; $EMAILFILE<br />&nbsp;grep -i 'ORA-'&nbsp;&nbsp; $LOGFILE &gt;&gt; $EMAILFILE<br />&nbsp;grep -i 'sbt'&nbsp;&nbsp;&nbsp; $LOGFILE &gt;&gt; $EMAILFILE<br />&nbsp;grep -i 'tsm'&nbsp;&nbsp;&nbsp; $LOGFILE &gt;&gt; $EMAILFILE</p><p>&nbsp;sendmail -F &quot;$SENDER&quot; -t &lt; $EMAILFILE</p><p>&nbsp;cat $EMAILFILE &gt;&gt; $EMAILARCFILE</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit 12<br />fi</p><p>echo --------------------------------------------------------- &gt;&gt; $LOGFILE<br />date &gt;&gt; $LOGFILE<br />echo ---------------- rman_bkup.ksh completed ---------------- &gt;&gt; $LOGFILE<br />echo &gt;&gt; $LOGFILE</p><p>cat $EMAIL_INFO_FILE &gt; $EMAILFILE<br />echo &quot;Subject: The $0 script completed successfully for $ORACLE_SID !!!&quot; &gt;&gt; $EMAILFILE<br />cat $LOGFILE &gt;&gt; $EMAILFILE</p><p>sendmail -F &quot;$SENDER&quot; -t &lt; $EMAILFILE</p><p>cat $EMAILFILE &gt;&gt; $EMAILARCFILE</p><p>cat $LOGFILE &gt;&gt; $LOGARCFILE</p><p>##<br />## Remove lock file to allow other rman processs for this ORACLE_SID to run, if any<br />##</p><p>rm $LOCKFILE</p><p>## ---------------------------------------------------------------------------------<br />## End of&nbsp; rman_bkup.ksh<br />## ---------------------------------------------------------------------------------</p>]]>
    </content>
</entry>
<entry>
    <title>SQL Tutorial for the beginners</title>
    <link rel="alternate" type="text/html" href="http://www.somberi.com/techblog/2007/07/sql_tutorial_for_the_beginers.php" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.somberi.com/nrk-mt/mt-atom.cgi/weblog/blog_id=5/entry_id=50" title="SQL Tutorial for the beginners" />
    <id>tag:somberi.com,2007:/techblog//5.50</id>
    
    <published>2007-07-01T13:42:15Z</published>
    <updated>2008-01-23T01:53:46Z</updated>
    
    <summary>This tutorial is aimed at giving the beginners a brief introduction to the Structured Query Language or SQL </summary>
    <author>
        <name>Ramakrishna Nemani</name>
        
    </author>
            <category term="Developer" />
            <category term="Oracle" />
            <category term="Ramakrishna Nemani" />
    
    <content type="html" xml:lang="en" xml:base="http://www.somberi.com/techblog/">
        This tutorial is aimed at giving a beginner a brief introduction to the Structured Query Language or SQL and get you started with using sqlplus to log on to Oracle and access and manipulate data.
        <![CDATA[<p>Give below is what you learn and can expect to be able to do after attending this tutorial&hellip;</p><p>&bull;&nbsp;Brief history and overview of SQL<br />&bull;&nbsp;Set-up environment variables to invoke sqlplus and log on to a Oracle database from a reflection session<br />&bull;&nbsp;Execute basic SQL queries<br />&bull;&nbsp;Get all the data in a table<br />&bull;&nbsp;Get named columns from a table <br />&bull;&nbsp;Get named columns from a table and order them<br />&bull;&nbsp;Perform arithmetic on column values<br />&bull;&nbsp;Prevent duplicate row selection<br />&bull;&nbsp;Selecting only data that meets a criteria with the WHERE clause<br />&bull;&nbsp;SQL operators in WHERE clauses<br />&bull;&nbsp;Multiple condition WHERE clauses<br />&bull;&nbsp;Group Functions<br />&bull;&nbsp;Sub-queries<br />&bull;&nbsp;Select data from multiple tables<br />&bull;&nbsp;Execute basic SQL DML commands<br />&bull;&nbsp;Insert<br />&bull;&nbsp;Update<br />&bull;&nbsp;Delete<br />&bull;&nbsp;Use basic DDL commands<br />&bull;&nbsp;create table<br />&bull;&nbsp;alter table<br />&bull;&nbsp;create index<br />&bull;&nbsp;truncate table<br />&bull;&nbsp;drop table<br />&bull;&nbsp;Use basic access control commands<br />&bull;&nbsp;grant<br />&bull;&nbsp;revoke<br />&bull;&nbsp;Modify sqlplus environment<br />&bull;&nbsp;Write and execute small SQL scripts<br />&nbsp;<br />Structured Query Language</p><p><br />Structured Query Language or SQL was originally developed by IBM for its System/R Project. IBM later used it in its products SQL/Data System (SQL/DS) and Database 2 (DB2). SQL today became a language of choice to access the data and structures within a relational database and is implemented and supported by most commercially available Relational Database Management System vendors. </p><p>SQL was designed to be an English like language using English phrases to manipulate the database. It is non procedural. You specify what you want done but not how to do it. The how part is taken care of by the RDBMS. Each RDBMS has an in-built query optimizer which parses your SQL statements and works out the best path to retrieve/manipulate the data. </p><p>SQL is designed to be used by a wide spectrum of users- DBA's, application developers, operators&nbsp; and end users.</p><p>It provides commands to do the following &hellip;</p><p>&bull;&nbsp;finding (querying) data<br />&bull;&nbsp;inserting, updating and deleting data<br />&bull;&nbsp;creating, modifying and deleting database objects<br />&bull;&nbsp;controlling access to the database and database objects<br />&bull;&nbsp;Transaction Control</p><p>The different SQL statements could be&nbsp; grouped into 4 different categories as explained below&hellip;</p><p>DATA QUERY LANGUAGE (DQL) -&nbsp; SQL statements&nbsp; to retrieve data from the database and transform it.&nbsp;&nbsp; SELECT statement falls into this category.</p><p>DATA MANIPULATION LANGUAGE (DML) - SQL statements to insert, change or delete data from the database. DELETE, INSERT, UPDATE&nbsp;&nbsp; statements&nbsp; fall into this category.</p><p>DATA DEFINITION LANGUAGE&nbsp; (DDL) - SQL statements to define or alter database structures. DROP, TRUNCATE, CREATE, ALTER&nbsp; statements&nbsp; fall into this category.</p><p>Access Control - SQL statements to either grant or revoke privileges to access and manipulate&nbsp; database objects.&nbsp; </p><p>REVOKE, GRANT statements&nbsp; fall into this category.</p><p>Transaction Control - SQL statements that commit or rollback changes to data.</p><p>COMMIT, ROLLBACK statements fall into this category.</p><p>To connect to an oracle database and execute sql commands you can use an oracle supplied tool called sqlplus. <br />&nbsp;<br />Environment set-up for invoking sqlplus and connect to an Oracle&nbsp; database</p><p>Add the following lines to your .profile after you login to your unix environment. After adding the following lines log out and log back in to make sure that the .profile is run.</p><p># Replace with the path at your installation<br />export ORACLE_HOME=/oracle/product/8.1.7<br /># Replace with sid name at your installation<br />ORACLE_SID=xyz<br />export ORACLE_SID<br />LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ORACLE_HOME/lib<br />export LD_LIBRARY_PATH<br />LIBPATH=$LIBPATH:/usr/lib:$ORACLE_HOME/lib<br />export LIBPATH<br />PATH=$PATH:$ORACLE_HOME/bin<br />export PATH</p><p>The above lines set-up paths for oracle binaries and libraries.</p><p>The ORACLE_SID environment variable identifies the database that you would connect to when you invoke sqlplus. In our case we would be connecting to a database named stgt.</p><p>After setting up the environment you can invoke sqlplus by entering sqlplus at your unix prompt as shown below. Enter your username and password when prompted. You will get SQL prompt if you login successfully. You can then enter and execute all your sql commands at the SQL prompt.</p><p>$ sqlplus</p><p>SQL*Plus: Release 8.1.7.0.0 - Production on Mon Aug 26 11:33:41 2002</p><p>(c) Copyright 2000 Oracle Corporation.&nbsp; All rights reserved.</p><p>Enter user-name: rnemani<br />Enter password: </p><p>Connected to:<br />Oracle8i Enterprise Edition Release 8.1.7.4.0 - Production<br />With the Partitioning option<br />JServer Release 8.1.7.4.0 - Production</p><p>SQL&gt;</p><p>If you want to terminate your sqlplus session you simply enter exit at your SQL prompt as shown below&hellip;</p><p>SQL&gt; exit<br />Disconnected from Oracle8i Enterprise Edition Release 8.1.7.4.0 - Production<br />With the Partitioning option<br />JServer Release 8.1.7.4.0 &ndash; Production</p><p>$ </p><p>&nbsp;</p><p>DATA QUERY LANGUAGE (DQL)</p><p>The SELECT statement is the most widely used command of SQL. It allows you to retrieve the data from the database. Most SQL statements will need a semi-colon &quot;;&quot; to indicate the end of the statement.</p><p>Get all the data&nbsp; in a table</p><p>Select * from price_list ;</p><p>Gets all the columns and all the rows in the table.</p><p>Get named columns from a table </p><p>Select&nbsp; division_no, article_nbr, price_list_price, price_list_price<br />From price_list ;</p><p>Get named columns from a table and order them</p><p>Select&nbsp; division_no, article_nbr, price_list_price<br />From price_list <br />Order by division_no, article_nbr ;</p><p>Perform arithmetic on column values</p><p>Select&nbsp; division_no, article_nbr, price_list_price, price_list_price*0.05<br />From price_list ;</p><p>Preventing duplicate row selection</p><p>Select&nbsp; distinct division_no From price_list ;</p><p>Selecting only data that meets a criteria&nbsp; with the WHERE clause</p><p>Select&nbsp; division_no, article_nbr, price_list_price<br />From price_list <br />Where division_no = 72 ;</p><p>SQL operators in WHERE clauses</p><p>Select&nbsp; division_no, article_nbr, price_list_price<br />From price_list <br />Where division_no in&nbsp; (71, 72)&nbsp; ;</p><p>Select&nbsp; division_no, article_nbr, price_list_price<br />From price_list <br />Where price_list_price &gt; 100 ;</p><p>Select&nbsp; division_no, article_nbr, price_list_price<br />From price_list <br />Where division_no&nbsp; not in&nbsp; (71, 72)&nbsp; ;</p><p>select * from division<br />where division_desc like 'T%' ;</p><p>Multiple condition WHERE clauses</p><p>Select * from price_list<br />Where division_no = 93<br />And basis_company_id = 66 ;</p><p>Select * from price_list<br />Where division_no = 93<br />or price_list_price &gt; 100 ;</p><p>Group Functions</p><p>Select count(*) from price_list ;</p><p>Select max(price_list_price)<br />From price_list ;</p><p>Select avg(price_list_price)<br />From price_list ;</p><p>Select division_no, count(*) <br />from price_list <br />group by division_no ;</p><p>Select division_no, max(price_list_price), min(price_list_price)<br />from price_list <br />group by division_no ;</p><p>Select division_no, max(price_list_price), min(price_list_price)<br />from price_list <br />group by division_no <br />having min(price_list_price) &gt; 10 ;</p><p>Select division_no, basis_company_id, count(*) <br />from price_list <br />group by division_no, basis_company_id ;</p><p>Selecting data from multiple tables (Join)</p><p>Select division_desc, outlet_name<br />From division a , outlet b<br />Where a.division_no = b.division_no ;</p><p>Select division_desc, outlet_name<br />From division a, outlet b<br />Where a.division_no = b.division_no<br />And a.division_no = 51 ;</p><p>Sub-queries</p><p>Select count(*) from price_list <br />Where division_no in ( <br />select division_no from division where price_group_user = 'Y'<br />) ;</p><p>Select count(*) from price_list <br />Where division_no not in ( <br />select division_no from division where price_group_user = 'Y'<br />) <br />;</p><p>Select count(*) from price_list&nbsp; a<br />Where exists in ( <br />select division_no <br />from division b <br />where b.price_group_user = 'Y'<br />and b.division_no = a.division_no<br />) <br />;</p><p>Select count(*) from price_list&nbsp; a<br />Where not exists in ( <br />select division_no <br />from division b <br />where b.price_group_user = 'Y'<br />and b.division_no = a.division_no<br />) <br />;<br />DATA MANIPULATION LANGUAGE (DML)</p><p>In order for us to be able to retrieve data from tables we need to first have them populated and properly maintained so that they contain the relevant data. This is exactly what the DML commands are used for.</p><p>INSERT</p><p>Insert command is used for inserting new data into a table.</p><p>insert into division<br />values (98, 'This is a New Dvsn','Y','Y','N')<br />;</p><p>The above statement will create a new row .</p><p>insert into division<br />(division_no,division_desc)<br />values (98, 'This is a New Dvsn') ;</p><p>The above statement will create a new row but with only division_no and division_desc columns populated with values and other columns set to NULL.</p><p>Insert into new_division_table<br />Select * from division ;</p><p>The above statement Inserts rows from division table into new_division_table table (provided the structure of new_division_table table is identical to the structure of division table).</p><p>You have to issue a commit statement if you want the data to be saved in the table permanently. Alternatively you can issue a rollback, if you do not want your changes to be saved to the database.</p><p>A commit or a rollback command should always be issued to commit or rollback a transaction. A transaction could be made up of one or more DML commands.</p><p>A commit statement looks as follows &hellip;</p><p>Commit ;</p><p>A rollback statement looks as follows &hellip;</p><p>Rollback ;</p><p>Make sure that you issue a commit or rollback before you exit your sqlplus session. Sqlplus will issue a commit by default when you exit.</p><p>UPDATE</p><p>The UPDATE command is used for updating the column values of an existing row in a table.</p><p>Following are some examples &hellip;</p><p>update division<br />set division_desc = 'My new division'<br />where division_no = 98 ;</p><p>update price_list<br />set price_list_price = price_list_price * 0.05<br />where price_list_price &lt; 1 ;</p><p>You can use a sub-query to update a column as shown below &hellip;</p><p>update new_division_table a<br />set division_desc = (select division_desc from division b <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; where b.division = a.division<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; )<br />;</p><p>DELETE</p><p>Delete command is used for removing data (rows) from a table.</p><p>delete from&nbsp; new_division_table ;</p><p>The above statement will delete all rows from new_division_table table.</p><p>delete from&nbsp; new_division_table<br />where division_no = 98 ;</p><p>The above statement will delete the row corresponding to the division_no 98 from the new_division_table table.</p><p>Some more examples &hellip;</p><p>delete from&nbsp; new_division_table<br />where division_no &gt;= 98 ;</p><p>delete from&nbsp; new_division_table<br />where division_no in (98, 99) ;</p><p>delete from&nbsp; new_division_table<br />where division_no != 98 ;</p><p>delete from&nbsp; new_division_table<br />where division_no not in (98, 99) ;</p><p>DATA DEFINITION LANGUAGE (DDL)</p><p>In order for us to be able to store and retrieve data from tables we need to first have them created. This is exactly what the DDL commands are used for.</p><p>Following is an example of &quot;create table &quot; command in its simplest form&hellip;</p><p>create table new_division_table<br />(&nbsp;DIVISION_NO &nbsp;NUMBER(2) NOT NULL, <br />DIVISION_DESC &nbsp;VARCHAR2(30), <br />PRICE_GROUP_USER &nbsp;VARCHAR2(1),<br />TRADE_GROUP_USER &nbsp;VARCHAR2(1), <br />SALES_TYPE_USER &nbsp;VARCHAR2(1)<br />) ;</p><p>The above command creates a table called new_division_table. It will be empty. The NOT NULL clause&nbsp; for division_no column is to make sure that division_no column must always have a value whenever data is inserted into this table and it can not be updated to a NULL value.</p><p>You can also create a table from an existing table as shown below&hellip;</p><p>create table new_division_table as <br />select * from division ;</p><p>The above command creates a table called new_division_table and populates it with data from division table.</p><p>create index x1_new_division_table<br />on new_division_table (division_no) ;</p><p>The above command creates an index called x1_new_division_table.</p><p>Alter table&nbsp; new_division_table<br />modify&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DIVISION_DESC &nbsp;VARCHAR2(40) ;</p><p>The above command alters the width of division_desc column to 40 from 30.</p><p>truncate table new_division_table ;</p><p>The above command deletes all data in the table</p><p>drop table new_division_table ;</p><p>The above command drops the table from the database. All the data within the table is permanently lost. So do exercise caution when using this command. I have one suggestion to avoid mistakes with DROP command &ndash; DO NOT USE IT in the first place.</p><p>Note : DDL commands do not need a commit because they issue an implicit commit. This means that we can not rollback any DDL once it is executed.</p><p>There are a number of other DDL commands which I think are the beyond the scope of this brief introduction to SQL.<br />&nbsp;<br />Access Control Commands</p><p>When a user creates a database object such as a table, it gets created under the ownership (schema) of the user creating it. The user who created the table owns the table.&nbsp; In order for others to be able to access or store data in this table the owner has to grant appropriate privileges to other users.</p><p>Following are some examples but first the disclaimer&hellip;</p><p>&quot;Following examples are based on fictitious situations. Any resemblance to any names of any persons or projects or places is purely coincidental. &quot; </p><p>Example 1.</p><p>Tom and Harry work in the IT department for a major bottling company and are working on a new project (actually cleaning up an old project) which requires them to work on an Oracle database and deal with tables etc...</p><p>During the course working on this project, Tom creates a table called new_division_table and he wants Harry to be able to select data from this table. So he executes the following command&hellip;</p><p>grant select on new_division_table to Harry ;</p><p>Now Harry can access data from this table as follows..</p><p>select *&nbsp; from Tom.new_division_table ; </p><p>Note that the username of the owner of the table has to be prepended to the table name, if the table is not owned by the user trying to access the table. </p><p>Example 2.</p><p>Harry tells Tom that he wants to be able to do more than mere selecting of data from the table.</p><p>Tom then executes the following GRANT command to give Harry more privileges&hellip;</p><p>grant insert, update, delete on new_division_table&nbsp; to Harry ;</p><p>Harry then tests his newly granted privileges on the table as follows&hellip;</p><p>delete from&nbsp; Tom.new_division_table ;<br />commit ;</p><p>Example 3.</p><p>Now Tom is mad and wants to take away all but SELECT privilege from Harry on the new_division_table. He executes the following command &hellip;</p><p>revoke&nbsp;&nbsp; insert,update, delete on new_division_table from Harry ;</p><p>I Hope the above examples clarify the use of Access control commands.<br /></p><p>Changing sqlplus environment</p><p>You can change the default behaviour of how the results are displayed within sqlplus. You can do this by using the set command of sqlplus.</p><p>set pagesize 80</p><p>The above command makes sure columns headings are repeated&nbsp; after every 80 lines of the results.</p><p>set pagesize 0</p><p>The above command supresses printing of headings.</p><p>set linesize&nbsp; 70</p><p>Above command sets the line size to 70.</p><p>spool /home/rnemani/division.list<br />select * from division ;<br />spool off</p><p>The above commands create a text file called division.lst in /home/patuser directory. This file would contain the output of division table.</p><p>If you want see your current sqlplus environment settings give the following command </p><p>show all</p><p>There are a number of useful set commands that you could use and would use as you start using sqlplus regularly.</p><p>Using SQL scripts</p><p>You can save regularly used sql commands in a sql script using a text editor such as vi.</p><p>For example you can save the following commands in a&nbsp; script file called get_div.sql&nbsp; using vi.</p><p>spool /home/rnemani/division.list<br />select * from division ;<br />spool off</p><p>You can then start up a sql session and execute the script at the sql prompt as shown below.</p><p>SQL&gt; @get_div.sql</p><p>The above command would execute all the commands in the script as if they were entered at SQL prompt.</p><p>You can know the structure (column names, data types etc&hellip;) of any table, by using the following command</p><p>DESC table_name</p><p>for example&hellip;</p><p>SQL&gt; desc division<br />&nbsp;Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Null?&nbsp;&nbsp;&nbsp; Type<br />&nbsp;----------------------------------- -------- --------------------<br />&nbsp;DIVISION_NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NOT NULL NUMBER(2)<br />&nbsp;DIVISION_DESC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VARCHAR2(30)<br />&nbsp;PRICE_GROUP_USER&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VARCHAR2(1)<br />&nbsp;TRADE_GROUP_USER&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VARCHAR2(1)<br />&nbsp;SALES_TYPE_USER&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VARCHAR2(1)</p><p>SQL&gt;</p><p>Oracle returns errors when you execute your sql statements, if there is a syntax error(s) or if it is unable to find the objects that are referred to in the SQL statement. Given below is an example&hellip;</p><p>SQL&gt; select count(*) from rkn_branch_extension ;<br />select count(*) from rkn_branch_extension<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<br />ERROR at line 1:<br />ORA-00942: table or view does not exist</p><p>If you want know more about this error then you can issue the following command at your UNIX prompt.</p><p>$ oerr ORA 942<br /></p><h5>Conclusion</h5><p>As you can see SQL is very easy to use and intuitive. One other good thing about SQL is that it is portable for the most part across databases that support it. I hope this tutorial gave you enough information to get started with SQL.</p>]]>
    </content>
</entry>
<entry>
    <title>Writing Efficient SQL Code for Oracle - Part 2</title>
    <link rel="alternate" type="text/html" href="http://www.somberi.com/techblog/2007/06/writing_efficient_sql_code_for_1.php" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.somberi.com/nrk-mt/mt-atom.cgi/weblog/blog_id=5/entry_id=48" title="Writing Efficient SQL Code for Oracle - Part 2" />
    <id>tag:somberi.com,2007:/techblog//5.48</id>
    
    <published>2007-07-01T01:52:49Z</published>
    <updated>2008-01-23T02:13:41Z</updated>
    
    <summary>Part 2 of this article deals with writing Efficient SQL Code for the OLTP environment.


</summary>
    <author>
        <name>Ramakrishna Nemani</name>
        
    </author>
            <category term="Developer" />
            <category term="Oracle" />
            <category term="Ramakrishna Nemani" />
    
    <content type="html" xml:lang="en" xml:base="http://www.somberi.com/techblog/">
        <![CDATA[<span style="font-family: 'Courier New'"><em><h5 class="MsoNormal" style="margin: 0in 0in 0pt" align="left"><em>Introduction</em></h5></em></span><p>In part 2 of this article I cover writing Efficient SQL Code for the OLTP environment.<br /></p><span style="font-family: 'Courier New'">Following topics are covered <ul><li><span style="font-family: 'Courier New'">Correlated Queries </span></li><li><span style="font-family: 'Courier New'"><span style="font-family: 'Courier New'">Implicit data type conversions </span><li><span style="font-family: 'Courier New'"><span style="font-family: 'Courier New'">Making sure indexes are considered by the Optimizer</span> <li><span style="font-family: 'Courier New'"><span style="font-family: 'Courier New'">Reduce the network traffic</span></span></li></span></li></span></li></ul></span>]]>
        <![CDATA[<h5><span><em>Correlated Queries<br /></em></span><span>&nbsp;</span></h5><span>Exercise caution while writing SQL statements using correlated queries. <br /></span><span>If you use lot of<span>&nbsp; </span>correlated queries in your code and if they get executed frequently<span>&nbsp; </span>then<span>&nbsp; </span>you might want to re-examine them. </span><span>Correlated queries could get very expensive in terms of resources as explained in the next few slides with the help of an example. <br /></span><span>The query shown next lists employees that have been hired between Jan 2002 and March 2002 and have been employed the longest in each division. <br /></span><span><span><span>SQL&gt; select emp_no, emp_division,<span>&nbsp; </span>(emp_term_dt - emp_hire_dt) emp_span<br /></span><span><span>&nbsp; </span>2<span>&nbsp; </span>from emp o<br /></span><span><span>&nbsp; </span>3<span>&nbsp; </span>where emp_hire_dt &gt;= '01-JAN-2002'<br /></span><span><span>&nbsp; </span>4<span>&nbsp; </span>and emp_hire_dt &lt; '31-MAR-2002'<br /></span><span><span>&nbsp; </span>5<span>&nbsp; </span>and (o.emp_term_dt - o.emp_hire_dt)<br /></span><span><span>&nbsp; </span>6<span>&nbsp; </span>in<br /></span><span><span>&nbsp; </span>7<span>&nbsp; </span>( select max(i.emp_term_dt - i.emp_hire_dt)<br /></span><span><span>&nbsp; </span>8<span>&nbsp; </span>from emp i<br /></span><span><span>&nbsp; </span>9<span>&nbsp; </span>where i.emp_division = o.emp_division<br /></span><span><span>&nbsp;</span>10<span>&nbsp; </span>and emp_hire_dt &gt;= '01-JAN-2002'<br /></span><span><span>&nbsp;</span>11<span>&nbsp; </span>and emp_hire_dt &lt; '31-MAR-2002' )<span>&nbsp; </span>;<br /></span><span>62 rows selected.<br /></span><span><span><span>Elapsed:<strong> 00:00:43.58<br /></strong></span><span>Statistics<br /></span><span>-------------------------------------------<br /></span><strong><span><span>&nbsp;</span>977818</span></strong><span><span>&nbsp; </span>physical reads<br /></span><span>The above sql is a correlated query. The output from the query is not shown here. Notice the execution time and physical reads.Next slide will show this query re-written without using the correlated sub query<br /></span><span><span><span>The same sql re-written as shown below and<span>&nbsp; </span>it does not use correlated sub query. Output from the query is not shown here. Notice the drastic reduction in the execution time and the physical reads<br /></span><p><span>SQL&gt; select a.emp_division, a.emp_no, b.emp_span<br /></span><span><span>&nbsp; </span>2<span>&nbsp; </span>from emp a<br /></span><span><span>&nbsp; </span>3<span>&nbsp; </span>, (<span>&nbsp;&nbsp;&nbsp;&nbsp; </span>select<span>&nbsp; </span>emp_division, max(i.emp_term_dt - i.emp_hire_dt) emp_span<br /></span><span><span>&nbsp; </span>4<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>from emp i<br /></span><span><span>&nbsp; </span>5<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>where emp_hire_dt &gt;= '01-JAN-2002'<br /></span><span><span>&nbsp; </span>6<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>and emp_hire_dt &lt; '31-MAR-2002'<br /></span><span><span>&nbsp; </span>7<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>group by emp_division ) b<br /></span><span><span>&nbsp; </span>8<span>&nbsp; </span>where <span>a.emp_division = b.emp_division<br /></span><span><span>&nbsp; </span>9<span>&nbsp; </span>and <span>&nbsp;&nbsp; </span>(a.emp_term_dt - a.emp_hire_dt) = b.emp_span<br /></span><span><span>&nbsp;</span>10<span>&nbsp; </span>and <span>&nbsp;&nbsp; </span>a.emp_hire_dt &gt;= '01-JAN-2002'<br /></span><span><span>&nbsp;</span>11<span>&nbsp; </span>and <span>&nbsp;&nbsp; </span>a.emp_hire_dt &lt; '31-MAR-2002' ;<br /></span><span>&nbsp;</span></span></p><span><span>62 rows selected.<br /></span><span>Elapsed: <strong>00:00:01.82<br /></strong></span><span>Statistics<br /></span><span>----------------------------------<br /></span><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong>28725</strong><span>&nbsp; </span>physical reads<br /></span></span><span><span><span>Let us modify the query to consider the whole emp table. <br /></span><span><span><span>Select statement with a correlated subquery<br /></span><span>SQL&gt; select a.emp_division, a.emp_no, (a.emp_term_dt - a.emp_hire_dt) emp_span<br /></span><span><span>&nbsp; </span>2<span>&nbsp; </span>from emp a<br /></span><span><span>&nbsp; </span>3<span>&nbsp; </span>, (<span>&nbsp;&nbsp; </span>select emp_division, max(i.emp_term_dt - i.emp_hire_dt) max_span<br /></span><span><span>&nbsp; </span>4<span>&nbsp; </span>from emp i<br /></span><span><span>&nbsp; </span>5<span>&nbsp; </span>group by emp_division<span>&nbsp;&nbsp; </span>) b<br /></span><span><span>&nbsp; </span>6<span>&nbsp; </span>where<span>&nbsp;&nbsp; </span>a.emp_division = b. emp_division<br /></span><span><span>&nbsp; </span>7<span>&nbsp; </span>and<span>&nbsp;&nbsp;&nbsp;&nbsp; </span>(a.emp_term_dt - a.emp_hire_dt) = b.max_span<br /></span><span><span>&nbsp; </span>8<span>&nbsp; </span>order by emp_span<span>&nbsp; </span>;<br /></span><span><span>&nbsp;</span><br /></span><span>305 rows selected.<br /></span><span>Elapsed: <strong>00:29:08.75<br /></strong></span><span>Statistics<br /></span><span>----------------------------------------------------------<br /></span><span><span>&nbsp;&nbsp; </span><strong>39094846</strong><span>&nbsp; </span>physical reads<br /></span><span><span><span>As can be seen above, the resource intensive nature of Correlated queries becomes very evident as the size of the driving table in the outer query increases.<span>&nbsp; </span>Now the above correlated sub query took<span>&nbsp; </span>more than 29 minutes and a huge number of physical reads.<br /></span><span>The above query is re-written as shown below and does not use the correlated sub query and notice that the execution time and physical reads still are very low although now we are considering the entire emp table<br /></span><span><span><p><span>SQL&gt; select<span>&nbsp; </span>a.emp_division, a.emp_no, b.emp_span<br /></span><span><span>&nbsp; </span>2<span>&nbsp; </span>from<span>&nbsp;&nbsp; </span>emp a<br /></span><span><span>&nbsp; </span>3<span>&nbsp; </span>, ( select<span>&nbsp; </span>emp_division<br /></span><span><span>&nbsp; </span>4<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>, max(i.emp_term_dt - i.emp_hire_dt) emp_span<br /></span><span><span>&nbsp; </span>5<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>from emp i<br /></span><span><span>&nbsp; </span>6<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>group by emp_division ) b<br /></span><span><span>&nbsp; </span>7<span>&nbsp; </span>where <span>a.emp_division = b.emp_division<br /></span><span><span>&nbsp; </span>8<span>&nbsp; </span>and <span>&nbsp;&nbsp; </span>(a.emp_term_dt - a.emp_hire_dt) = b.emp_span ;<br /></span><span>&nbsp;</span></span></p></span><span><span>305 rows selected.<br /></span><span>Elapsed: <strong>00:00:02.84<br /></strong></span><span>Statistics<br /></span><span>-----------------------------------<br /></span><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong>28726</strong><span>&nbsp; </span>physical reads</span></span><span><span><span><span> <h5><span><em>Making sure indexes are considered by the Optimizer<br /></em></span></h5><p><span><span>Oracle optimizer may not consider the indexes<span>&nbsp; </span>when evaluating query plans if the columns in the where clause have any kind of transformation done on them.<br /></span><span><span>For<span>&nbsp; </span>example in the following select statement notice how the ename column is<span>&nbsp; </span>transformed.<br /></span><span><span>Select * from emp<br /></span><span>Where upper(ename) = &lsquo;&amp;ename&rsquo;<br /></span><span><span>If an index exists on<span>&nbsp; </span>ename column Oracle optimizer will not consider<span>&nbsp; </span>it when evaluating the access paths for executing the above statement.<br /></span><span><span>Next I <span>&nbsp;</span>explain with<span>&nbsp; </span>an example how we can make sure that<span>&nbsp; </span>indexes are considered by the Optimizer.<br /></span><span><span>Consider<span>&nbsp; </span>the emp table that we used in the previous examples.<span>&nbsp; </span>This table has an index on hiredate column.<span>&nbsp; </span></span></span></span></span></span></span></span></p><span><span><span><span><span><span><span><span>Some of the columns of emp table are shown below&hellip;<br /></span><span><span><span>&nbsp; </span>Name<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Type<br /></span><span><span>&nbsp;</span>--------------<span>&nbsp; </span>------------<br /></span><span><span>&nbsp;</span>EMPNO<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>NUMBER(6)<br /></span><span><span>&nbsp;</span>ENAME<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>VARCHAR2(10)<br /></span><span><span>&nbsp;</span>HIREDATE<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>DATE<br /></span><span><span>&nbsp;</span>DEPTNO<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>NUMBER(2)<br /></span><span><span>Following select statement retrieves the data for all employees hired yesterday.<br /></span><span><span>Select<span>&nbsp; </span>*<span>&nbsp; </span>from<span>&nbsp; </span>emp<br /></span><span>where hiredate + 1 =<span>&nbsp; </span>sysdate ; *<br /></span><span><span>When evaluating the access paths<span>&nbsp;&nbsp; </span>optimizer does not consider the hiredate index, instead it looks for an index on hiredate+10 and does not find one. <br /></span><span><span>* Actually Oracle date columns have time component also, but I am ignoring that to keep this example simple.<br /></span><span><span>If you want the optimizer to use the index then you have to rewrite the above select statement as shown below &hellip;<br /></span><span><span>Select<span>&nbsp; </span>*<span>&nbsp; </span>from<span>&nbsp; </span>emp<br /></span><span>where hiredate<span>&nbsp; </span>=<span>&nbsp; </span>sysdate -1 ;<br /></span><span><span>Now the optimizer looks for an index on hiredate and<span>&nbsp; </span>finds one and uses it, if that gives a better access path.<br /></span><span><span>To summarize, if you do any transformations on columns in the where clause of your SQL statement, then indexes (if any) on those columns would not be considered by Oracle optimizer while evaluating access paths.<br /></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><h5><span><em>Avoid implicit data type conversions<br /></em></span></h5><p><span><span>What is implicit data type conversion? <br /></span><span><span>Implicit data type conversion occurs when the database converts the data types<span>&nbsp; </span>while applying a condition in the where clause during the execution of a query.<br /></span><span><span>Consider the following table<br /></span><span><span>&nbsp;</span></span></span></span></span></p><p><span><span><span><span><span>SQL&gt; describe<span>&nbsp; </span>SALESCENTER_CHANNEL_SUMMARY<br /></span><span><span>&nbsp;</span>Name<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Null?<span>&nbsp;&nbsp;&nbsp; </span>Type<br /></span><span><span>&nbsp;</span>----------------------------------- -------- -----------<br /></span><span><span>&nbsp;</span>SALES_CENTER_NUM<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>NOT NULL VARCHAR2(6)<br /></span><span><span>&nbsp;</span>CHANNEL_NBR<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>NOT NULL NUMBER(3)<br /></span><span><span>&nbsp;</span>DIVISION_NO<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>NOT NULL NUMBER(2)<br /></span><span><span>&nbsp;</span>SALES<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>NOT NULL NUMBER<br /></span><span><span>&nbsp;</span></span></span></span></span></span></p><p><span><span><span><span><span><span>SALES_CENTER_NUM column is defined as datatype VARCHAR2(6) in the above table.<br /></span><span><span>&nbsp;</span></span></span></span></span></span></span></p><p><span><span><span><span><span><span><span>select<span>&nbsp; </span>count(*)<br /></span><span>from<span>&nbsp;&nbsp;&nbsp; </span>SALESCENTER_CHANNEL_SUMMARY<br /></span><span>where<span>&nbsp;&nbsp; </span>SALES_CENTER_NUM = 213502 ;<br /></span><span><span><span>&nbsp; </span>COUNT(*)<br /></span><span>----------<br /></span><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>37<br /></span><span>The above select statement<span>&nbsp;&nbsp; </span>worked because Oracle did the data type<span>&nbsp; </span>conversion for us when it executed the query. And because the sales_center_num data in the table happened<span>&nbsp; </span>to contain only numeric values.<br /></span><span><span>&nbsp;</span></span></span></span></span></span></span></span></span></p><p><span><span><span><span><span><span><span><span><span>If you looked at what Oracle did behind the scenes for this query, it would be<br /></span><span><span>&nbsp;</span></span></span></span></span></span></span></span></span></span></p><p><span><span><span><span><span><span><span><span><span><span>1. For each row of SALESCENTER_CHANNEL_SUMMARY <br /></span><span>apply the where clause condition SALES_CENTER_NUM = 213502<br /></span><span>by first converting the SALES_CENTER_NUM<br /></span><span>into a number and then comparing against the value 213502<br /></span><span>2. Return the filtered result set from step 1<br /></span><span><span>In effect, it is as if<span>&nbsp;&nbsp; </span>your query is rewritten as follows&hellip;<br /></span><span><span>select<span>&nbsp; </span>count(*)<br /></span><span>from<span>&nbsp;&nbsp;&nbsp; </span>SALESCENTER_CHANNEL_SUMMARY<br /></span><span>where<span>&nbsp;&nbsp; </span>to_number(SALES_CENTER_NUM) = 213502 ;<br /></span><span><span><br /></span><span><br /></span><span>Now let us add another row to the table<span>&nbsp; </span>that has a non numeric values for sales_center num column as shown below.<br /></span><span><span>SALES_ CHANNEL_NBR DIVISION_NO BASIS_COMPANY_ID BA<br /></span><span>------ ----------- ----------- ---------------- --<br /></span><span>4070ZP<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>14<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;</span>40<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>70 ZP<br /></span><span><span>Now when we execute the same<span>&nbsp; </span>query again we get the following error<br /></span><span><span>SQL&gt; select<span>&nbsp; </span>count(*)<br /></span><span><span>&nbsp; </span>2<span>&nbsp; </span>from<span>&nbsp;&nbsp;&nbsp; </span>SALESCENTER_CHANNEL_SUMMARY<br /></span><span><span>&nbsp; </span>3<span>&nbsp; </span>where<span>&nbsp;&nbsp; </span>SALES_CENTER_NUM = 213502 ;<br /></span><span><span>where<span>&nbsp;&nbsp; </span>SALES_CENTER_NUM = 213502<br /></span><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>*<br /></span><span>ERROR at line 3:<br /></span><span>ORA-01722: invalid number<br /></span><span><span>&nbsp;</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p><p><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span>We got an error because now there is a sales center<span>&nbsp; </span>4070ZP in the data<span>&nbsp; </span>that could not be converted into a number. The query worked as long as the data values could be implicitly converted but<span>&nbsp; </span>failed when there is a data value that could not be converted.<br /></span><span>Moral of the story : Do not depend on implicit data conversions.<br /></span><span><span>&nbsp;</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span>There is a side effect to implicit conversions that needs to be mentioned also. Implicit conversions prevent the optimizer from choosing the index even if there is an index existing for that column. Implicit data conversions almost always result in full table scans. </span><span><span>That is another reason why we should not depend on implicit data conversions. <br /></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><h5><span><em>Reduce the network traffic<br /></em></span></h5><p><span><span>High network traffic saturates the available network bandwidth in a WAN causing severe performance problems.</span></span></p><span><span><p><br /><span><span>So we need to minimize the network traffic<span>&nbsp; </span>between </span></span><span><span><span><br /></span><span><span>-<span>&nbsp; </span>the client application and database server if it is a two tier architecture<br /></span><span>-<span>&nbsp; </span>the App server and the database server if it is a three tier architecture<br /></span><span><span>&nbsp;</span></span></span></span></span></p></span></span><p><span><span><span><span><span>Network traffic<span>&nbsp; </span>consists of<br /></span><span><span>1. Sql statements sent from the application to the database server<br /></span><span>2. Results sent from<span>&nbsp; </span>the database server<span>&nbsp; </span>to<span>&nbsp; </span>the<span>&nbsp; </span>application<br /></span><span><span>&nbsp;</span></span></span></span></span></span></span></p><p><span><span><span><span><span><span><span>Minimizing traffic from the application to the database server<br /></span><span><span>&nbsp;</span></span></span></span></span></span></span></span></p><p><span><span><span><span><span><span><span><span>To do this we need to minimize the amount of data going from from the application to the database server. <br /></span><span><span>&nbsp;</span></span></span></span></span></span></span></span></span></p><p><span><span><span><span><span><span><span><span><span>This can<span>&nbsp; </span>be done by moving<span>&nbsp; </span>the sql statements from the application to the database stored procedures. This means instead of sending lengthy sql statements across the network, application<span>&nbsp; </span>just invokes database stored procedures with appropriate parameters.<span>&nbsp; </span><br /></span><span><span>This results is far less traffic being generated from the application to the database server. <br /></span><span><span>This approach has another benefit as well,<span>&nbsp; </span>it reduces the parsing activity<span>&nbsp; </span>to<span>&nbsp; </span>a minimum &ndash; because stored procedures are pre-parsed and can be pinned in the memory. Since parsing is a very CPU intensive activity, less parsing means less load on the CPU.<br /></span><span><span>Minimizing traffic from the database server to the application<br /></span><span><span>In this case, we can not minimize the amount of data sent from<span>&nbsp; </span>the database server to the application.<span>&nbsp; </span>But we can still reduce the traffic by packing<span>&nbsp; </span>more data in each of the tcp/ip packets which results in<span>&nbsp; </span>less number of packets<span>&nbsp; </span>going across the network. <br /></span><span><span>This can be done by tweaking the sqlnet<span>&nbsp; </span>ARRAYSIZE.<span>&nbsp; </span>I am not going into details here but<span>&nbsp; </span>just know that it is possible to tweak it and take the help of your DBA to do that.<br /></span><span><h5><span><em>Conclusion<br /></em></span></h5><span><span>Many applications fail to scale because of the SQL code that is not efficient. Writing<span>&nbsp; </span>SQL code<span>&nbsp; </span>that works alone is not enough. It is important to make sure that your SQL code does what it does very efficiently. <br /></span><span><span>I have used the techniques described here very successfully to solve many tuning problems over the last several years.<span>&nbsp; </span>I hope you find the information presented here useful.<br /></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p><p>&nbsp;</p></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span>]]>
    </content>
</entry>
<entry>
    <title>Writing Efficient SQL Code for Oracle - Part 1</title>
    <link rel="alternate" type="text/html" href="http://www.somberi.com/techblog/2007/06/writing_efficient_sql_code_for_2.php" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.somberi.com/nrk-mt/mt-atom.cgi/weblog/blog_id=5/entry_id=47" title="Writing Efficient SQL Code for Oracle - Part 1" />
    <id>tag:www.somberi.com,2007:/techblog//5.47</id>
    
    <published>2007-06-30T23:22:54Z</published>
    <updated>2008-01-31T01:32:27Z</updated>
    
    <summary>This article aims to provide you with information and tips that will help you write efficient SQL code for Oracle databases.Part 1 of this article deals with writing Efficient SQL Code for the Batch environment. 
</summary>
    <author>
        <name>Ramakrishna Nemani</name>
        
    </author>
            <category term="Developer" />
            <category term="Oracle" />
            <category term="Ramakrishna Nemani" />
    
    <content type="html" xml:lang="en" xml:base="http://www.somberi.com/techblog/">
        <![CDATA[<h5><span>Introduction<br /></span></h5><p><span>This article aims to provide you with information and tips that will help you write efficient SQL code for Oracle databases. Part 1 covers batch environment.</span></p><p><span><strong><em>Why is writing efficient SQL code important?<br /></em></strong></span><span>If you would like your application to scale well, then you would need to have SQL code that executes efficiently.<span>&nbsp;&nbsp;</span></span></p><p><span><strong><em>How do you define efficient SQL code?<br /></em></strong></span><span>Any SQL code that does what it does, using minimum resources and in minimum possible time.</span></p>]]>
        <![CDATA[<p>In part 1 of this article I cover the following areas where one can achieve big efficiency gains by writing efficient sql for batch environment.</p><p>Huge Inserts<br />Huge Updates<br />Huge Deletes<br />Efficient elimination of duplicates<br />Efficient verification of&nbsp; foreign keys</p><p>Oracle does the following when you issue a DML<br />After the normal syntax, semantics and security checking etc...<br />it would...<br />&nbsp;&nbsp;&nbsp;&nbsp; 1. Insert/modify the data into database buffers<br />&nbsp;&nbsp;&nbsp;&nbsp; - This is the actual data that would subsequently be written to data&nbsp; files on the disks<br />&nbsp;&nbsp;&nbsp;&nbsp; 2. Create redo log records<br />&nbsp;&nbsp;&nbsp;&nbsp; - These records are written to redo log files <br />&nbsp;&nbsp;&nbsp;&nbsp; - These are used to recover from an instance failure or crash<br />&nbsp;&nbsp;&nbsp;&nbsp; 3. Create undo records (Rollback info)<br />&nbsp;&nbsp;&nbsp;&nbsp; - These records are written to rollback segments <br />&nbsp;&nbsp;&nbsp;&nbsp; - These records are used in case you decide to rollback</p><p>So, as you can see each DML, results in a flurry of activity which means batch jobs that deal with huge amounts of data would have unacceptable performance unless special measures are taken as described next.</p><p><strong>Handling huge inserts <br /></strong>Normal insert<br />SQL&gt; insert<br />2&nbsp; into abc<br />3&nbsp; select * from xyz&nbsp; ;</p><p>&nbsp;978816 rows created. </p><p>Elapsed: 00:08:18.08</p><p>Statistics<br />-------------------------------------------------<br />&nbsp; 106586580&nbsp; redo size</p><p>&nbsp;Obviously the above insert is not very efficient. It took about 8+ minutes to insert just under a million rows.</p><p>Now let us look at a turbo charged version of insert command called&nbsp; <strong>Direct Load Insert</strong> </p><p>SQL&gt; insert /*+ append */<br />2&nbsp; into abc<br />3&nbsp; select * from xyz<br />4&nbsp; nologging&nbsp; ;</p><p>978816 rows created.</p><p>Elapsed: 00:00:12.30</p><p>Statistics<br />----------------------------------------------------------<br />&nbsp;&nbsp;&nbsp;&nbsp; 241716&nbsp; redo size</p><p>&ldquo;<strong>Direct load insert</strong>&rdquo; works differently than a Normal insert. It completely by passes the 3 steps (mentioned previously) that occur for a normal DML and directly writes to the data files of the oracle database.</p><p>You should use &ldquo;<strong>Direct load insert</strong>&rdquo; whenever you do huge inserts.</p><p><strong>Handling large Updates</strong></p><p>Say you have a 30 million row table and your update affects 5 Millions rows - How would you do it ?<br />The normal approach&nbsp; would be to execute an update statement similar to the one shown in the example below</p><p>update&nbsp; aBigTable<br />set column1 = column1 + column1 * 0.10<br />where column3 = 'Y'<br />;</p><p>What do you think will happen if you executed the previous update? </p><p><strong>Best case scenario<br /></strong>1. Your update finishes after running zillion hours without actually running out of rollback segment space<br />2. Because your update brought everything else to a grinding halt&nbsp; - Help desk gets inundated by calls from other users of the database wanting to know if the database has left the building!!!.</p><p><strong>Worst case scenario<br /></strong>1. Your update takes zillion hours and then fails after running out of rollback segment space<br />2. Because your update brought everything else to a grinding halt&nbsp; - Help desk gets inundated by calls from other users of the database .<br />3. Your access privileges to the database may get revoked <br />As you can see even the best case scenario is not particularly good&hellip;<br />let us look at a better way of doing large updates<br />--<br />-- Create an empty table<br />--<br />create table aBigTable_temp<br />nologging <br />as select * from aBigTable where rownum &lt; 1 ;<br />insert /*+ append */<br />into aBigTable_temp (column1,column2,column3)<br />select decode (column3, 'Y', (column1 + column1 * 0.10), column1)<br />, column2<br />, column3<br />from aBigTable ;<br />commit ;<br />rename&nbsp; aBigTable to aBigTable_old ;<br />rename&nbsp; aBigTable_temp&nbsp; to aBigTable ;<br />--<br />-- Notice how column1 is handled in the select clause of the insert ..select .. statement<br />--<br />--<br />-- create any needed indices on aBigTable<br />--<br />Your index creation statements go here.<br />--<br />-- Check if data in table aBigTable is OK and drop aBigTable_old<br />--<br />drop table aBigTable_old ;</p><p>The above steps would complete in far less time than it takes the normal update</p><p><strong>Handling large Deletes<br /></strong>Say you have a 30 million row table and you need to delete&nbsp; 5 Millions rows - How would you do it <br />The normal approach&nbsp; would be to execute the following sql statement<br />&nbsp;<br />Delete&nbsp; from xyz<br />where column3 = 'Y&lsquo; ;</p><p>What do you think will happen ?<br />The best and worst case scenarios would be more or less the same as that for an update described previously.<br /></p><p>Recommended approach<br />--<br />-- Create an empty table<br />--<br />create table temp_table<br />nologging <br />as select * from xyz where rownum &lt; 1 ;<br />--<br />-- Load the rows that you want to keep in the temp table<br />--<br />insert /*+ append */<br />into temp_table (column1,column2,column3)<br />select column1 , column2 , column3<br />from xyz<br />where column3 != 'Y&lsquo;&nbsp; ;<br />commit ;</p><p>rename xyz&nbsp; xyz_old&nbsp; ;<br />rename xyz_temp&nbsp; xyz&nbsp; ;<br />--<br />-- create any needed indices on xyz<br />--<br />Your index creation code goes here.<br />--<br />-- Check if data in table xyz is OK and drop xyz_old<br />--<br />drop table xyz_old ;</p><p><strong>Efficient Duplicates elimination</strong></p><p>Many times we are faced with situations that require us to design a load script that loads data with duplicates.</p><p><strong>Normal method of eliminating duplicates<br /></strong>1.Define a unique index on the table&nbsp; and load data. <br />2.Load the data using sqlldr conventional path (direct path load can not&nbsp; be used because of the index)<br />sqlldr rejects Duplicate rows and writes them to badfile. But this unique key checking incurs a very big performance penalty. For example in my testing sqlldr took 28 minutes to load&nbsp; little over a million rows&nbsp; with one duplicate row. Using the normal method, the time it takes to eliminate duplicates grows exponentially with the size of data. So this method is not practical for bulk data loading.</p><p><strong>Method to eliminate duplicates efficiently<br /></strong>Oracle assigns a unique rowid to each row in a table.&nbsp;&nbsp; So each row in a table has unique rowid even if the data within the row is duplicated. <br />In oracle the fastest path to data is the path that uses rowids. So if we can identify the rowids of duplicates then we can use those rowids to delete them from the table very fast.<br />The sample delete statement&nbsp; given&nbsp; next , identifies the duplicates and deletes them.&nbsp;&nbsp; </p><p>This sample delete statement is explained using an&nbsp; example in subsequent slides </p><p>delete&nbsp; from xyz<br />where&nbsp;&nbsp;&nbsp;&nbsp; rowid in<br />(<br />--<br />-- This&nbsp; select gets all the rowids <br />--<br />&nbsp;&nbsp;&nbsp;&nbsp; select&nbsp;&nbsp;&nbsp; a.rowid<br />&nbsp;&nbsp;&nbsp;&nbsp; from&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xyz<br />&nbsp;&nbsp;&nbsp;&nbsp; minus<br />--<br />-- This select gets&nbsp; rowids of the first row for each duplicated value for the <br />-- column in the group by clause<br />--<br />&nbsp;&nbsp;&nbsp;&nbsp; select&nbsp;&nbsp;&nbsp; min(rowid)<br />&nbsp;&nbsp;&nbsp;&nbsp; from&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xyz<br />&nbsp;&nbsp;&nbsp;&nbsp; group by unique_key_col<br />) ;</p><p>The minus operation gives us the&nbsp; row ids of all the duplicates that can be&nbsp; deleted from the table. Thus, we&nbsp; will have only one row for each set of duplicates in the table after the deletion thus ridding the table of duplicates.</p><p>I use a table called emp_sal to explain the above delete statement whose contents are shown below<br />&nbsp;&nbsp;&nbsp; EMPID DEPTID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SAL<br />&nbsp;---------- ----------&nbsp;&nbsp;&nbsp;&nbsp; ----------<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1 SALES&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 36000<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2 SALES&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 38000<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3 SALES&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 42000<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4 ACCTS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 36000<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5 ACCTS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 38000<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5 ACCTS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 42000<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5 ACCTS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 42000<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5 ACCTS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 38000<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 7 SALES&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 42000<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 7 SALES&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 35000<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 9 IT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 42000<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 10 IT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 45000<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 11 IT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 52000<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 12 IT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 55000<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 13 SALES&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 35000<br />15 rows selected.</p><p>This gives all rows including duplicates</p><p>SQL&gt; select a.rowid , a.empid from emp_sal a<br />&nbsp; 2&nbsp; order by empid&nbsp;&nbsp; ;<br />ROWID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EMPID <br />------------------&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ---------- <br />AAAYPOAAJAABio4AAA&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1 <br />AAAYPOAAJAABio4AAB&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2 <br />AAAYPOAAJAABio4AAC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3 <br />AAAYPOAAJAABio4AAD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4 <br />AAAYPOAAJAABio4AAE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5 <br />AAAYPOAAJAABio4AAF&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5 <br />AAAYPOAAJAABio4AAO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5 <br />AAAYPOAAJAABio4AAN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5 <br />AAAYPOAAJAABio4AAG&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 7 <br />AAAYPOAAJAABio4AAH&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 7 <br />AAAYPOAAJAABio4AAI&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 9 <br />AAAYPOAAJAABio4AAJ&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 10 <br />AAAYPOAAJAABio4AAK&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 11 <br />AAAYPOAAJAABio4AAL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 12 <br />AAAYPOAAJAABio4AAM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 13 <br />15 rows selected.</p><p>The following select statement&nbsp; gives all rows but with only one row per duplicated data</p><p>SQL&gt; select min(a.rowid) min_rowid, a.empid<br />&nbsp; 2&nbsp; from emp_sal a<br />&nbsp; 3&nbsp; group by empid&nbsp;&nbsp;&nbsp; ;</p><p>MIN_ROWID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EMPID<br />------------------&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ----------<br />AAAYPOAAJAABio4AAA&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1<br />AAAYPOAAJAABio4AAB&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2<br />AAAYPOAAJAABio4AAC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3<br />AAAYPOAAJAABio4AAD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4<br />AAAYPOAAJAABio4AAE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5<br />AAAYPOAAJAABio4AAG&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 7<br />AAAYPOAAJAABio4AAI&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 9<br />AAAYPOAAJAABio4AAJ&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 10<br />AAAYPOAAJAABio4AAK&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 11<br />AAAYPOAAJAABio4AAL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 12<br />AAAYPOAAJAABio4AAM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 13<br />11 rows selected.</p><p>If&nbsp; we do a diff (minus operation) on the above two sets of data&nbsp; then we get the rowids of the duplicates which we use for deleting.</p><p>SQL&gt; select a.rowid , a.empid from emp_sal a<br />&nbsp; 2&nbsp; minus<br />&nbsp; 3&nbsp; select min(a.rowid) , a.empid<br />&nbsp; 4&nbsp; from emp_sal a<br />&nbsp; 5&nbsp; group by empid<br />&nbsp; 6&nbsp; order by empid&nbsp;&nbsp; ;</p><p>ROWID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EMPID<br />------------------&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ----------<br />AAAYPOAAJAABio4AAF&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5<br />AAAYPOAAJAABio4AAN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5<br />AAAYPOAAJAABio4AAO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5<br />AAAYPOAAJAABio4AAH&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 7<br />4 rows selected.</p><p>Here is the delete (With all components combined) &hellip;</p><p>SQL&gt; delete from emp_sal<br />&nbsp; 2&nbsp; where rowid in<br />&nbsp; 3&nbsp; (<br />&nbsp; 4&nbsp; select a.rowid<br />&nbsp; 5&nbsp; from emp_sal a<br />&nbsp; 6&nbsp; minus<br />&nbsp; 7&nbsp; select min(a.rowid)<br />&nbsp; 8&nbsp; from emp_sal a<br />&nbsp; 9&nbsp; group by empid<br />&nbsp;10&nbsp; )&nbsp;&nbsp; ;<br />4 rows deleted.</p><p>So in this method you </p><p>1. Load the table using sqlldr direct path<br />2. Use a delete statement similar to the one shown on the previous slide&nbsp; to eliminate duplicates</p><p>Using this method I repeated the test of loading&nbsp; a little over million rows&nbsp; with one duplicate row</p><p>1.sqlldr took 58 seconds to load 1065393 rows<br />2.delete statement took 46 seconds.</p><p>So it took less than 2 minutes to&nbsp; load the table and eliminate the duplicates</p><p><strong>Efficient Verification of Foreign Key</strong></p><p>This is another area that causes performance problems in batch environment.<br />If you have a&nbsp; foreign key constraint defined for a column in a table, then all the inserts and updates cause Oracle to do a foreign Key checking to make sure that referential integrity is maintained.&nbsp; This means for each insert, Oracle would query the referenced table (parent table) to make sure FK constraint is satisfied. This does not pose a problem if you are dealing with low volumes of data. But this becomes a big issue if you do huge data loads.</p><p>So how do you&nbsp; load millions of rows into a table that has foreign keys defined ?<br /></p><p>Following two methods are the most widely used but inefficient methods.<br />Do the load with foreign keys enabled and only rows that satisfy&nbsp; fk constraints get loaded<br />or <br />Do the load&nbsp; with foreign keys disabled.</p><p>Then try enabling the fk with a statement similar to the one below</p><p>ALTER TABLE emp<br />&nbsp;&nbsp; ENABLE VALIDATE CONSTRAINT fk_deptno<br />&nbsp;&nbsp; EXCEPTIONS INTO exceptions_table</p><p>Both of the above methods are very inefficient and would require&nbsp; big batch windows.</p><p>The following method is very efficient for loading tables with FK constraints. It involves 3 steps&hellip;<br />1. Load the table with FK disabled (This will be quick since no FK checking is done)<br />2. Identify the rows that do not satisfy the FK constraint and delete them<br />3. Enable foreign key without validating (This will be quick since no FK checking is done)<br />Following example illustrates the use of&nbsp; the above method.</p><p>Desc emp <br />&nbsp;Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Type<br />&nbsp;--------------&nbsp; ------------<br />&nbsp;EMPNO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NUMBER(6)<br />&nbsp;ENAME&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VARCHAR2(10)<br />&nbsp;JOB&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VARCHAR2(9)<br />&nbsp;MGR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NUMBER(6)<br />&nbsp;HIREDATE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DATE<br />&nbsp;SAL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NUMBER(7,2)<br />&nbsp;COMM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NUMBER(7,2)<br />&nbsp;DEPTNO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NUMBER(2)</p><p>Desc dept<br />&nbsp;<br />Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Type<br />&nbsp;--------------&nbsp; -------------<br />&nbsp;DEPTNO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NUMBER(2)<br />&nbsp;DNAME&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VARCHAR2(14)<br />&nbsp;LOC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VARCHAR2(13)</p><p>Deptno in EMP table references Deptno in DEPT table.<br />So any new rows inserted into EMP table should have a DEPTNO value that exists in DEPT table.<br />Now to do a huge data load into EMP table<br />First Load the data into EMP table with FK disabled.<br />Then Delete from EMP table deptno values that do not exist&nbsp; in DEPT table&nbsp;&nbsp;&nbsp; as shown next <br />delete from emp<br />where rowid in<br />(-- This gets us the rowids that need to be deleted<br />&nbsp;&nbsp;&nbsp;&nbsp; select rowid <br />&nbsp;&nbsp;&nbsp;&nbsp; from emp <br />&nbsp;&nbsp;&nbsp;&nbsp; where dept_no in&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp; ( -- This identifes deptno values that do not exist in DEPT table<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; select distinct deptno <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; from emp<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; minus <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; select deptno<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; from dept<br />&nbsp;&nbsp;&nbsp;&nbsp; )<br />) ;</p><p>After the above step, You can&nbsp; re-enable the foreign key constraint on EMP table&nbsp;&nbsp;&nbsp; without validating. This is because we know that EMP table will have only&nbsp;&nbsp;&nbsp; valid deptno values after the above delete</p><p>ALTER TABLE emp<br />&nbsp;&nbsp; ENABLE NOVALIDATE CONSTRAINT fk_deptno ;</p><p>This concludes part 1. I have used all the techniques that were described here to make Oracle batch environment perform optimally. I hope you find these techniques useful.</p><p>&nbsp;</p>]]>
    </content>
</entry>
<entry>
    <title>Output log of restore_datafile_new.ksh</title>
    <link rel="alternate" type="text/html" href="http://www.somberi.com/techblog/2007/06/output_log_of_restore_datafile_1.php" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.somberi.com/nrk-mt/mt-atom.cgi/weblog/blog_id=5/entry_id=85" title="Output log of restore_datafile_new.ksh" />
    <id>tag:somberi.com,2007:/techblog//5.85</id>
    
    <published>2007-06-17T23:19:22Z</published>
    <updated>2008-01-23T02:15:58Z</updated>
    
    <summary>Output log of restore_datafile_new.ksh. read this along with restore_datafile_new.ksh script</summary>
    <author>
        <name>Ramakrishna Nemani</name>
        
    </author>
            <category term="DBA" />
            <category term="Oracle" />
            <category term="Ramakrishna Nemani" />
            <category term="rman output logs" />
    
    <content type="html" xml:lang="en" xml:base="http://www.somberi.com/techblog/">
        Output log of restore_datafile_new.ksh. read this along with restore_datafile_new.ksh script
        <![CDATA[<p>Recovery Manager: Release 10.2.0.1.0 - Production on Tue Jul 17 16:15:13 2007</p><p>Copyright (c) 1982, 2005, Oracle.&nbsp; All rights reserved.</p><p>RMAN&gt; <br />RMAN&gt; <br />connected to target database: slsd (DBID=3183102432)</p><p>RMAN&gt; <br />RMAN&gt; 2&gt; 3&gt; 4&gt; 5&gt; 6&gt; 7&gt; 8&gt; 9&gt; 10&gt; 11&gt; 12&gt; 13&gt; 14&gt; 15&gt; <br />using target database control file instead of recovery catalog<br />allocated channel: disk_1<br />channel disk_1: sid=41 devtype=DISK</p><p>sql statement: alter database datafile 6 offline</p><p>executing command: SET NEWNAME</p><p>Starting restore at 17-JUL-07</p><p>channel disk_1: starting datafile backupset restore<br />channel disk_1: specifying datafile(s) to restore from backup set<br />restoring datafile 00006 to /u02/oradata/slsd/new_users01.dbf<br />channel disk_1: reading from backup piece /u06/flash_recovery_area/slsd/backupset/2007_07_13/o1_mf_nnndf_TAG20070713T142343_39hjzqbh_.bkp<br />channel disk_1: restored backup piece 1<br />piece handle=/u06/flash_recovery_area/slsd/backupset/2007_07_13/o1_mf_nnndf_TAG20070713T142343_39hjzqbh_.bkp tag=TAG20070713T142343<br />channel disk_1: restore complete, elapsed time: 00:00:08<br />Finished restore at 17-JUL-07</p><p>datafile 6 switched to datafile copy<br />input datafile copy recid=10 stamp=628186526 filename=/u02/oradata/slsd/new_users01.dbf</p><p>Starting recover at 17-JUL-07</p><p>starting media recovery</p><p>archive log thread 1 sequence 3 is already on disk as file /u06/flash_recovery_area/slsd/archivelog/2007_07_14/o1_mf_1_3_39kwb3tf_.arc<br />archive log thread 1 sequence 4 is already on disk as file /u06/flash_recovery_area/slsd/archivelog/2007_07_15/o1_mf_1_4_39ogg8pf_.arc<br />archive log thread 1 sequence 5 is already on disk as file /u06/flash_recovery_area/slsd/archivelog/2007_07_15/o1_mf_1_5_39ogtt12_.arc<br />archive log thread 1 sequence 6 is already on disk as file /u06/flash_recovery_area/slsd/archivelog/2007_07_15/o1_mf_1_6_39ogtvj5_.arc<br />archive log thread 1 sequence 7 is already on disk as file /u06/flash_recovery_area/slsd/archivelog/2007_07_15/o1_mf_1_7_39ogtxon_.arc<br />archive log thread 1 sequence 8 is already on disk as file /u06/flash_recovery_area/slsd/archivelog/2007_07_16/o1_mf_1_8_39rb0ylf_.arc<br />channel disk_1: starting archive log restore to default destination<br />channel disk_1: restoring archive log<br />archive log thread=1 sequence=2<br />channel disk_1: reading from backup piece /u06/flash_recovery_area/slsd/backupset/2007_07_13/o1_mf_annnn_TAG20070713T143007_39hk5kjq_.bkp<br />channel disk_1: restored backup piece 1<br />piece handle=/u06/flash_recovery_area/slsd/backupset/2007_07_13/o1_mf_annnn_TAG20070713T143007_39hk5kjq_.bkp tag=TAG20070713T143007<br />channel disk_1: restore complete, elapsed time: 00:00:02<br />archive log filename=/u06/flash_recovery_area/slsd/archivelog/2007_07_17/o1_mf_1_2_39t8v19h_.arc thread=1 sequence=2<br />channel default: deleting archive log(s)<br />archive log filename=/u06/flash_recovery_area/slsd/archivelog/2007_07_17/o1_mf_1_2_39t8v19h_.arc recid=60 stamp=628186529<br />archive log filename=/u06/flash_recovery_area/slsd/archivelog/2007_07_14/o1_mf_1_3_39kwb3tf_.arc thread=1 sequence=3<br />archive log filename=/u06/flash_recovery_area/slsd/archivelog/2007_07_15/o1_mf_1_4_39ogg8pf_.arc thread=1 sequence=4<br />archive log filename=/u06/flash_recovery_area/slsd/archivelog/2007_07_15/o1_mf_1_5_39ogtt12_.arc thread=1 sequence=5<br />archive log filename=/u06/flash_recovery_area/slsd/archivelog/2007_07_15/o1_mf_1_6_39ogtvj5_.arc thread=1 sequence=6<br />media recovery complete, elapsed time: 00:00:04<br />Finished recover at 17-JUL-07</p><p>sql statement: alter database datafile 6 online<br />released channel: disk_1</p><p>RMAN&gt; <br />RMAN&gt; </p><p>Recovery Manager complete.</p>]]>
    </content>
</entry>
<entry>
    <title>restore_datafile_new.ksh</title>
    <link rel="alternate" type="text/html" href="http://www.somberi.com/techblog/2007/06/restore_datafile_newksh.php" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.somberi.com/nrk-mt/mt-atom.cgi/weblog/blog_id=5/entry_id=84" title="restore_datafile_new.ksh" />
    <id>tag:somberi.com,2007:/techblog//5.84</id>
    
    <published>2007-06-17T22:58:40Z</published>
    <updated>2008-01-23T02:16:51Z</updated>
    
    <summary>This script is for restoring datafile to a new location/name and recovering it.</summary>
    <author>
        <name>Ramakrishna Nemani</name>
        
    </author>
            <category term="DBA" />
            <category term="Oracle" />
            <category term="Ramakrishna Nemani" />
            <category term="rman scripts" />
    
    <content type="html" xml:lang="en" xml:base="http://www.somberi.com/techblog/">
        This script is for restoring datafile to a new location/name and recovering it.
        <![CDATA[<p>#!/bin/ksh<br />. ~/.profile</p><p>##<br />## script name : restore_datafile_new.ksh<br />## Author&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Ramakrishna Nemani<br />## <br />## Purpose :<br />## This script is for restoring datafile to a new location/name<br />## and recovering it.<br />##<br />## Note :<br />## To execute this script You need login as a unix id that belongs to DBA group.<br />## Make sure you have configured the rman automatic channels etc..<br />## I have tested this script on UNIX/LINUX platform using Oracle 10g. <br />## Use it at your own risk.<br />##<br />## This is an example or sample script<br />##</p><p>export ORACLE_SID=slsd</p><p>rman &lt;&lt; EOF &gt; ./rstr_datafile_new.log</p><p>connect target /</p><p>##<br />## Specify the datafile# to be restored and recovered<br />## Specify new location/name<br />##</p><p>run<br />{<br />allocate channel disk_1 device type disk ;<br />sql &quot;alter database datafile 6 offline&quot; ;<br />set newname for datafile '/u02/oradata/slsd/users01.dbf' TO '/u02/oradata/slsd/new_users01.dbf' ;<br />restore datafile 6 ;<br />switch datafile 6 ;<br />recover datafile 6 ;<br />sql &quot;alter database datafile 6 online&quot; ;<br />}</p><p>EOF</p>]]>
    </content>
</entry>
<entry>
    <title>Output log of restore_datafile.ksh</title>
    <link rel="alternate" type="text/html" href="http://www.somberi.com/techblog/2007/06/output_log_of_restore_datafile.php" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.somberi.com/nrk-mt/mt-atom.cgi/weblog/blog_id=5/entry_id=82" title="Output log of restore_datafile.ksh" />
    <id>tag:somberi.com,2007:/techblog//5.82</id>
    
    <published>2007-06-17T03:00:53Z</published>
    <updated>2008-01-23T02:17:50Z</updated>
    
    <summary>This is the output log of restore_datafile.ksh. </summary>
    <author>
        <name>Ramakrishna Nemani</name>
        
    </author>
            <category term="DBA" />
            <category term="Oracle" />
            <category term="Ramakrishna Nemani" />
            <category term="rman output logs" />
    
    <content type="html" xml:lang="en" xml:base="http://www.somberi.com/techblog/">
        This is the output log of restore_datafile.ksh. Read this along with restore_datafile.ksh
        <![CDATA[<p><br />Recovery Manager: Release 10.2.0.1.0 - Production on Mon Jul 16 15:58:15 2007</p><p>Copyright (c) 1982, 2005, Oracle.&nbsp; All rights reserved.</p><p>RMAN&gt; <br />RMAN&gt; <br />connected to target database: slsd (DBID=3183102432)</p><p>RMAN&gt; <br />RMAN&gt; 2&gt; 3&gt; 4&gt; <br />using target database control file instead of recovery catalog<br />sql statement: alter database datafile 6 offline</p><p>RMAN&gt; <br />Starting restore at 16-JUL-07<br />allocated channel: ORA_DISK_1<br />channel ORA_DISK_1: sid=39 devtype=DISK<br />allocated channel: ORA_DISK_2<br />channel ORA_DISK_2: sid=58 devtype=DISK<br />allocated channel: ORA_DISK_3<br />channel ORA_DISK_3: sid=40 devtype=DISK<br />allocated channel: ORA_DISK_4<br />channel ORA_DISK_4: sid=41 devtype=DISK<br />allocated channel: ORA_SBT_TAPE_1<br />channel ORA_SBT_TAPE_1: sid=55 devtype=SBT_TAPE<br />channel ORA_SBT_TAPE_1: Tivoli Data Protection for Oracle: version 5.2.0.0<br />allocated channel: ORA_SBT_TAPE_2<br />channel ORA_SBT_TAPE_2: sid=42 devtype=SBT_TAPE<br />channel ORA_SBT_TAPE_2: Tivoli Data Protection for Oracle: version 5.2.0.0<br />allocated channel: ORA_SBT_TAPE_3<br />channel ORA_SBT_TAPE_3: sid=63 devtype=SBT_TAPE<br />channel ORA_SBT_TAPE_3: Tivoli Data Protection for Oracle: version 5.2.0.0<br />allocated channel: ORA_SBT_TAPE_4<br />channel ORA_SBT_TAPE_4: sid=56 devtype=SBT_TAPE<br />channel ORA_SBT_TAPE_4: Tivoli Data Protection for Oracle: version 5.2.0.0</p><p>channel ORA_DISK_1: starting datafile backupset restore<br />channel ORA_DISK_1: specifying datafile(s) to restore from backup set<br />restoring datafile 00006 to /u02/oradata/slsd/users01.dbf<br />channel ORA_DISK_1: reading from backup piece /u06/flash_recovery_area/slsd/back<br />upset/2007_07_13/o1_mf_nnndf_TAG20070713T142343_39hjzqbh_.bkp<br />channel ORA_DISK_1: restored backup piece 1<br />piece handle=/u06/flash_recovery_area/slsd/backupset/2007_07_13/o1_mf_nnndf_TAG2<br />0070713T142343_39hjzqbh_.bkp tag=TAG20070713T142343<br />channel ORA_DISK_1: restore complete, elapsed time: 00:00:08<br />Finished restore at 16-JUL-07</p><p>RMAN&gt; <br />Starting recover at 16-JUL-07<br />using channel ORA_DISK_1<br />using channel ORA_D