Wednesday, January 29, 2014

How to group output using GROUPING SETS.

Following up with the table from my previous post "How to use the MERGE statement with a subquery", here is an example on how to group the information using the GROUPING SETS functionality in SQL:

The query
SELECT MAJOR,COURSE,TEACHER,SUM(CREDITS) "Total Credits"
FROM  COURSE_CATALOG
GROUP BY GROUPING SETS( (MAJOR,COURSE,TEACHER),(COURSE,TEACHER), (MAJOR,TEACHER),NULL );
The NULL directive tells SQL to generate a grand total at the end of the grouping.
Notice how the GROUPING SETS translates directly into the equivalent of grouping the rows three separate times

First by using

GROUP BY MAJOR, COURSE, TEACHER

then by using

GROUP BY COURSE,TEACHER

and finally by using

GROUP BY MAJOR, TEACHER

MAJOR COURSE TEACHER Total Credits
English Literature Ex. Phil A.Peterson 8
Nuclear Science Physics A Goodman 8
Nuclear Science Physics A A. Brown 8
Nuclear Science Physics A R. Franklin 8
Nuclear Science Mathematics A M. Stevens 8
English Literature Greek Mythology D.Simmons 10
Nuclear Science Advanced Algebra K.Wise 10
English Literature Early British Lit A.Peterson 8
  Ex. Phil A.Peterson 8
  Physics A Goodman 8
  Physics A A. Brown 8
  Physics A R. Franklin 8
  Mathematics A M. Stevens 8
  Greek Mythology D.Simmons 10
  Advanced Algebra K.Wise 10
  Early British Lit A.Peterson 8
Nuclear Science   M. Stevens 8
Nuclear Science   A. Brown 8
English Literature   D.Simmons 10
Nuclear Science   Goodman 8
Nuclear Science   R. Franklin 8
Nuclear Science   K.Wise 10
English Literature   A.Peterson 16
      68

How to use the MERGE statement with a subquery

Here is an example on how to use the MERGE statement to update a table, using a self-referencing subquery. One of many ways to clean up unstructured data

Tables look as follows:
MAJOR COURSE CLASS CREDITS ROOM_NO TEACHER
Nuclear Science Physics A A. Brown, Room 208 8    
Nuclear Science Mathematics A M. Stevens, Room 56 8    
Nuclear Science Advanced Algebra K.Wise, Audit. 20 10    
English Literature Ex. Phil A.Peterson, Room 208 8    
English Literature Early British Lit A.Peterson, Room 208 8    
English Literature Greek Mythology D.Simmons, Room 206 10    
Nuclear Science Physics A Goodman, Room 208 8    

To populate the ROOM_NO and TEACHER columns, I used the following query:
MERGE INTO COURSE_CATALOG A
USING 
(SELECT CLASS FROM COURSE_CATALOG) B
ON (A.ROWID = B.ROWID)
WHEN MATCHED THEN
    UPDATE SET A.TEACHER = REGEXP_REPLACE(REGEXP_SUBSTR(CLASS, '[[:alpha:]]+.{1,}[^[:digit:]]',1,1,'i'), ', Room |, Audit.', ''),
               A.ROOM_NO = REGEXP_SUBSTR(B.CLASS,'[[:digit:]]+'),
               A.CLASS = NULL
               
;
COMMIT;
Result:
MAJOR COURSE CLASS CREDITS ROOM_NO TEACHER
Nuclear Science Physics A   8 208 A. Brown
Nuclear Science Mathematics A   8 56 M. Stevens
Nuclear Science Advanced Algebra   10 20 K.Wise
English Literature Ex. Phil   8 208 A.Peterson
English Literature Early British Lit   8 208 A.Peterson
English Literature Greek Mythology   10 206 D.Simmons
Nuclear Science Physics A   8 208 Goodman

Tuesday, January 28, 2014

How to deregister a database from a Recovery Catalog

Log on to the target database:
SQL*Plus: Release 11.2.0.2.0 Production on Tue Jan 28 14:00:50 2014

Copyright (c) 1982, 2010, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management, Oracle Label Security,
OLAP, Data Mining, Oracle Database Vault and Real Application Testing options

SQL> select dbid,name from v$database;

      DBID NAME
---------- ---------
 305453026 PRODDB01
connect to the recovery catalog through sqlplus:
sqlplus uid/pwd@RMANCAT

SQL*Plus: Release 11.2.0.2.0 Production on Tue Jan 28 14:01:33 2014

Copyright (c) 1982, 2010, Oracle.  All rights reserved.

Connected to:
Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - 64bit Production
With the Partitioning, Oracle Label Security, OLAP, Data Mining
and Real Application Testing options

SQL> select db_key,dbid,name from rc_database
  2  where dbid=305453026;

    DB_KEY       DBID NAME
---------- ---------- --------
         1  305453026 PRODDB01
Finally, execute the procedure dbms_rcvcat.unregisterdatabase, passing in the parameters db_key and dbid:

SQL> execute dbms_rcvcat.unregisterdatabase(1,305453026);

PL/SQL procedure successfully completed.

How to set a column to UNUSED

Setting a column to UNUSED can be a solution when you cannot or should not attempt to drop a column due to performance reasons.

Syntax:
ALTER TABLE [table name] SET UNUSED (col1, col2, ... col n);
or
ALTER TABLE [table name] SET UNUSED COLUMN (col1);
Example:
ALTER TABLE MYTABLE
SET UNUSED COLUMN MODIFIED_DATE;

Verify that the columns were set to UNUSED:
SELECT * 
FROM USER_UNUSED_COL_TABS;

Result:
TABLE_NAME COUNT
MYTABLE 1
INVOICES_TMP 1

ALTER TABLE MYTABLE
DROP UNUSED COLUMNS;

The column is now gone:

SELECT * 
FROM USER_UNUSED_COL_TABS;
TABLE_NAME COUNT
INVOICES_TMP 1

You can also use the keyword CHECKPOINT when dropping the unused columns:
ALTER TABLE MYTABLE
DROP UNUSED COLUMNS CHECKPOINT 1000;

Oracle explains about the CHECKPOINT clause:

"This clause causes a checkpoint to be applied after processing the specified number of rows"
and
"Checkpointing cuts down on the amount of undo logs accumulated during the drop column operation to avoid a potential exhaustion of undo Space."

Note that:
Setting a column to UNUSED will drop constraints and indexes on the column
An UNUSED column cannot be accessed, nor recovered.
You can however, add a new column with the same name as any UNUSED column for the table.

Sources:
Oracle Documentation: Marking columns unused
Oracle Documentation: ALTER TABLE

Important files and directories in a Netbackup setup

Important netbackup files and directories on a typcial unix server:

/usr/openv/netbackup/version --> displays the netbackup version
/usr/openv/netbackup/bp.conf --> displays important settings such as SERVER, MEDIA_SERVER, CLIENT_NAME
/usr/openv/netbackup/logs/user_ops/dbext/logs --> log files for rman backups

Example of bp.conf

SERVER = backupserver1.mydomain.com
MEDIA_SERVER = server1-bkp.mydomain.com
CLIENT_NAME = server1-bkp.mydomain.com
REQUIRED_INTERFACE = server1-bkp.mydomain.com

Note that the CLIENT_NAME used above translates into the NB_ORA_CLIENT typically used in when sending backups to tape using Netbackup:

NB_ORA_CLIENT=server1-bkp.mydomain.com

How to save a value in a bind variable

Useful for tracing or explaining queries that use bind variables:
connect scott/tiger
var leom char(10);
var eod char(10);

exec :leom := to_date('30.09.2013','DD.MM.YYYY');
exec  :eod := to_date('31.10.2013','DD.MM.YYYY');

SELECT col1, col2 ....col n
FROM   TABLE1
WHERE  START_DATE <= :eod
AND    END_DATE   <= :leom;

Friday, January 24, 2014

How to shrink a datafile in a temporary tablespace

alter tablespace TEMP shrink tempfile '/data/oracle/PRODDB01/datafiles/temp_20.dbf' KEEP 8G;

This feature was introduced in Oracle 11g.

How to create a temporary tablespace and assign it as the database default


CREATE TEMPORARY TABLESPACE TMP TEMPFILE
  '/data/oracle/u01/PRODDB01/datafile/tmp_01.dbf' SIZE 128M AUTOEXTEND ON NEXT 32M MAXSIZE UNLIMITED
TABLESPACE GROUP ''
EXTENT MANAGEMENT LOCAL UNIFORM SIZE 1M;

ALTER DATABASE DEFAULT TEMPORARY TABLESPACE TMP;

Tuesday, January 21, 2014

How to restore a sequence of archivelogs back to their original location

connect catalog catowner/*********@RMANCAT
connect target
run {
allocate channel t1 type sbt PARMS="BLKSIZE=1048576"  maxopenfiles 64;
allocate channel t2 type sbt PARMS="BLKSIZE=1048576"  maxopenfiles 64;
send 'NB_ORA_POLICY=ora_dbserver1_00_netwzone1,NB_ORA_CLIENT=dbserver1-bkp.mydomain.com,NB_ORA_SCHED=ora_dbserver1_00_netwzone1_user';
restore archivelog from logseq 412594 until logseq 412656;
release channel t1;
release channel t2;
}

SQL: standby database information


This script is validated against Oracle 11g.

Run this script on the standby database to obtain basic information about the database state and the managed recovery processes:

set linesize 300
set pagesize 100
col "controlfile type" format a30
col "Unique name" format a12
col "Open Mode" format a12
col "Flashback on" format a15
col "Protection Mode" format a30
col "Current SCN" format 9999999999999
col "Database Role" format a20
col "Log Mode" format a20
col "DG broker" format a20
col "Destination name" format a20
col "Destination" format a20
col member format a70
col type format a20
col units format a20
col name format a15
set feedback off
alter session set NLS_DATE_FORMAT='DD-MM-YYYY HH24:SS:MI';
Prompt
Prompt ======================================================================================================================
prompt General information:
select name,db_unique_name as "Unique name",created,open_mode as "Open Mode",flashback_on as "Flashback on",resetlogs_time as "Resetlogs time",current_scn as "Current SCN"
from v$database
/
Prompt ======================================================================================================================
prompt Standby database information, if relevant:
select database_role as "Database Role",log_mode as "Log Mode",controlfile_type as "Controlfile type",protection_mode as "Protection Mode"
from v$database
/
Prompt ======================================================================================================================
select dest_name as "Destination Name",status,type,database_mode,recovery_mode,destination,archived_seq#,applied_seq#
from v$archive_dest_status
where status <> 'INACTIVE'
/
Prompt ======================================================================================================================
prompt Is the MRP process running?
select process, status from v$managed_standby
where process like '%MRP%'
/
Prompt ======================================================================================================================
Prompt Are there standby redo logs configured?
select s.group#,s.thread#,s.sequence#,s.archived,s.status,f.member, f.type
from v$standby_log s, v$logfile f
where f.type = 'STANDBY'
and s.group# = f.group#
/
Prompt ======================================================================================================================
Prompt Check the recovery progress:
select START_TIME
,TYPE
,ITEM
,UNITS
,SOFAR
,TOTAL
,TIMESTAMP
from v$recovery_progress
/
Prompt ======================================================================================================================
prompt Data guard broker information, if relevant:
select dataguard_broker as "DG broker"
from v$database
/
Prompt ======================================================================================================================
exit


Example output. Note particularly the output in red. When the archived_seq# and the applied_seq# match, together with an MRP process that is in status "WAITING_FOR_LOG", your standby database is in synch with the primary.
======================================================================================================================
General information:

NAME            Unique name  CREATED             Open Mode    Flashback on    Resetlogs time         Current SCN
--------------- ------------ ------------------- ------------ --------------- ------------------- --------------
PRODDB01        STBDB01      19-01-2009 15:25:32 MOUNTED      YES             17-11-2012 13:17:40  7203583291843
======================================================================================================================
Standby database information, if relevant:

Database Role        Log Mode             Controlfile type               Protection Mode
-------------------- -------------------- ------------------------------ ------------------------------
PHYSICAL STANDBY     ARCHIVELOG           STANDBY                        MAXIMUM PERFORMANCE
======================================================================================================================

Destination Name     STATUS    TYPE                 DATABASE_MODE   RECOVERY_MODE  DESTINATION  ARCHIVED_SEQ# APPLIED_SEQ#
-------------------- --------- -------------------- --------------- -------------- ------------ ------------- ------------
LOG_ARCHIVE_DEST_2   DEFERRED  PHYSICAL             MOUNTED-STANDBY MANAGED        PRODDB01      0                0
LOG_ARCHIVE_DEST_10  VALID     PHYSICAL             MOUNTED-STANDBY MANAGED                      48610            0
STANDBY_ARCHIVE_DEST VALID     PHYSICAL             MOUNTED-STANDBY MANAGED                      48609         48609
======================================================================================================================
Is the MRP process running?

PROCESS   STATUS
--------- ------------
MRP0      WAIT_FOR_LOG
======================================================================================================================
Are there standby redo logs configured?

    GROUP#    THREAD#  SEQUENCE# ARC STATUS     MEMBER                                                                 TYPE
---------- ---------- ---------- --- ---------- ---------------------------------------------------------------------- --------------------
         6          1      48611 YES ACTIVE     /data/oracle/u01/STBDB01/stb_redo_6a.dbf                              STANDBY
         6          1      48611 YES ACTIVE     /data/oracle/u01/STBDB01/stb_redo_6b.dbf                              STANDBY
         7          1          0 NO  UNASSIGNED /data/oracle/u01/STBDB01/stb_redo_7a.dbf                              STANDBY
         7          1          0 NO  UNASSIGNED /data/oracle/u01/STBDB01/stb_redo_7b.dbf                              STANDBY
         8          1          0 NO  UNASSIGNED /data/oracle/u01/STBDB01/stb_redo_8a.dbf                              STANDBY
         8          1          0 NO  UNASSIGNED /data/oracle/u01/STBDB01/stb_redo_8b.dbf                              STANDBY
         9          1          0 NO  UNASSIGNED /data/oracle/u01/STBDB01/stb_redo_9a.dbf                              STANDBY
         9          1          0 NO  UNASSIGNED /data/oracle/u01/STBDB01/stb_redo_9b.dbf                              STANDBY
        10          1          0 NO  UNASSIGNED /data/oracle/u01/STBDB01/stb_redo_10a.dbf                             STANDBY
        10          1          0 NO  UNASSIGNED /data/oracle/u01/STBDB01/stb_redo_10b.dbf                             STANDBY
        11          1          0 NO  UNASSIGNED /data/oracle/u01/STBDB01/stb_redo_11a.dbf                             STANDBY
        11          1          0 NO  UNASSIGNED /data/oracle/u01/STBDB01/stb_redo_11b.dbf                             STANDBY
======================================================================================================================
Check the recovery progress:

START_TIME          TYPE                 ITEM                             UNITS                     SOFAR      TOTAL TIMESTAMP
------------------- -------------------- -------------------------------- -------------------- ---------- ---------- -------------------
15-11-2013 17:11:58 Media Recovery       Log Files                        Files                      7571          0
15-11-2013 17:11:58 Media Recovery       Active Apply Rate                KB/sec                     8118          0
15-11-2013 17:11:58 Media Recovery       Average Apply Rate               KB/sec                      110          0
15-11-2013 17:11:58 Media Recovery       Redo Applied                     Megabytes                620510          0
15-11-2013 17:11:58 Media Recovery       Last Applied Redo                SCN+Time              923136452          0 21-01-2014 12:00:08
15-11-2013 17:11:58 Media Recovery       Active Time                      Seconds                   80785          0
15-11-2013 17:11:58 Media Recovery       Apply Time per Log               Seconds                       8          0
15-11-2013 17:11:58 Media Recovery       Checkpoint Time per Log          Seconds                       1          0
15-11-2013 17:11:58 Media Recovery       Elapsed Time                     Seconds                 5767807          0
======================================================================================================================
Data guard broker information, if relevant:

DG broker
--------------------
DISABLED
======================================================================================================================

How to use the DUPLICATE ... FOR STANDBY command to create a physical standby database

run {
allocate auxiliary channel t1 type sbt PARMS="BLKSIZE=1048576" maxpiecesize 32G maxopenfiles 64;
allocate auxiliary channel t2 type sbt PARMS="BLKSIZE=1048576" maxpiecesize 32G maxopenfiles 64;
send 'NB_ORA_POLICY=mypolicy,NB_ORA_CLIENT=myclient-bkp.mydomain,NB_ORA_SCHED=my_schedule';
allocate auxiliary channel aux1 device type disk;
set until logseq=l2345 thread=1;
duplicate target database for standby dorecover;
release channel t1;
release channel t2;
}
Note that the parameters db_file_name_convert and log_file_name_convert must be set in order to use this simplified syntax.
If not, you must specify file location for all the involved files and redo log members.

How to use ssh to a Solaris 8 box - overcoming file size limitation

When transferring files to a Solaris 8 server, I have had some difficulties with files larger than 2 GB. The ssh process will simply abort after it has reached the limit.
To work around this problem, use the following syntax instead:

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# NOTE: if you are transfering dump files to a Solaris 8 box,
# you need to tar and pipe the files to the receiving server.
# Make sure you cd to the directory first, before attempting
# to tar and ssh them.
# Vegard K, 25.02.2010
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#!/usr/bin/bash

cd /oracle/datapump/

tar cEf - dmpfile_01.dmp | ssh prodserver1 "cd /oracle/backup/datapump; tar xf -"

exit $?

How to use RMANs RESTORE...VALIDATE command


The RESTORE ... VALIDATE and VALIDATE BACKUPSET commands test whether you can restore from your backups:

RESTORE CONTROLFILE VALIDATE;
RESTORE TABLESPACE SYSTEM VALIDATE;
RESTORE ARCHIVELOG ALL VALIDATE;
This example validates the restore of backup sets 56 and 57:
VALIDATE BACKUPSET 56,57;
Same thing, but for individual datafiles:
RESTORE DATAFILE 4,5,6 VALIDATE;

In addition to listing the files needed for restore and recovery, the RESTORE ... VALIDATE HEADER command validates the backup file headers to determine whether the files on disk or in the media management catalog correspond to the metadata in the RMAN repository:

RESTORE DATABASE VALIDATE HEADER;

How to use RMANs RESTORE PREVIEW command

The RESTORE PRIVIEWS: identifies the backups (backup sets or image copies, on disk or sequential media like tapes) required to carry
out a given restore operation, based on the information in the RMAN repository.

These commands are brilliant for planning restore and recovery operations, for example

  • ensuring that all required backups are available
  • identifying RMAN backups you'd like to avoid or use

    RESTORE DATABASE PREVIEW;
    RESTORE TABLESPACE users PREVIEW;
    RESTORE DATAFILE 3 PREVIEW;
    RESTORE ARCHIVELOG FROM LOGSEQ 200 PREVIEW;
    RESTORE ARCHIVELOG FROM TIME 'SYSDATE-7' PREVIEW;
    RESTORE ARCHIVELOG FROM SCN 234546 PREVIEW;
    RESTORE DATABASE UNTIL TIME "TO_DATE('18.11.2014 18:00:00','DD.MM.YYYY HH24:MI:SS')" PREVIEW;
    

    Use the RESTORE... PREVIEW SUMMARY option to suppress much of the detail about specific files used and
    affected by the restore process:

    RESTORE DATABASE PREVIEW SUMMARY;
    RESTORE DATABASE UNTIL TIME "TO_DATE('31-08-2010 18:00:00', 'DD-MM-YYYY HH24:MI:SS')" PREVIEW;
    RESTORE DATABASE UNTIL TIME 'sysdate-3' PREVIEW SUMMARY;
    RESTORE DATABASE UNTIL TIME 'sysdate-1/24' preview summary; -->; one hour ago
    RESTORE TABLESPACE users PREVIEW SUMMARY;
    RESTORE DATAFILE 3 PREVIEW SUMMARY;
    RESTORE ARCHIVELOG FROM SCN 234546 PREVIEW SUMMARY;
    -- For pluggable databases, add the keyword "pluggable" to the very same statement
    RESTORE PLUGGABLE DATABASE PDB2 until time "TO_DATE('31-08-2010 18:00:00', 'DD-MM-YYYY HH24:MI:SS')" PREVIEW;
    

    To avoid the following error stack:
    Starting restore at 02.12.2014 16:51:24
    allocated channel: ORA_DISK_1
    channel ORA_DISK_1: SID=15 device type=DISK
     
    RMAN-00571: ===========================================================
    RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============
    RMAN-00571: ===========================================================
    RMAN-03002: failure of restore command at 12/02/2014 16:51:25
    RMAN-06026: some targets not found - aborting restore
    RMAN-06100: no channel to restore a backup or copy of datafile n
    

    you need to allocate the appropriate channels for maintenance first, such as

    allocate channel for maintenance type 'sbt_tape';
    

    Output example from a preview started 06.05.2015 14:18:12, checking to see what would be needed if I took the database back approximately 1,5 hours:

    RMAN> restore database until time "TO_DATE('06.05.2015 12:52:00','DD.MM.YYYY HH24:MI:SS')" preview summary;
    
    Starting restore at 06.05.2015 14:18:12
    
    using channel ORA_SBT_TAPE_1
    using channel ORA_DISK_1
    using channel ORA_DISK_2
    
    
    List of Backups
    ===============
    
    Key     TY LV S Device Type Completion Time     #Pieces #Copies Compressed Tag
    ------- -- -- - ----------- ------------------- ------- ------- ---------- ---
    
    373688959 B  0  A SBT_TAPE    30.04.2015 17:42:55 1       1       NO         20150430173000.SOLP2
    373688963 B  0  A SBT_TAPE    30.04.2015 17:43:06 1       1       NO         20150430173000.SOLP2
    373688965 B  0  A SBT_TAPE    30.04.2015 17:43:21 1       1       NO         20150430173000.SOLP2
    373688962 B  0  A SBT_TAPE    30.04.2015 17:43:03 1       1       NO         20150430173000.SOLP2
    373688958 B  0  A SBT_TAPE    30.04.2015 17:42:26 1       1       NO         20150430173000.SOLP2
    373688961 B  0  A SBT_TAPE    30.04.2015 17:43:02 1       1       NO         20150430173000.SOLP2
    373688956 B  0  A SBT_TAPE    30.04.2015 17:42:22 1       1       NO         20150430173000.SOLP2
    373688957 B  0  A SBT_TAPE    30.04.2015 17:42:24 1       1       NO         20150430173000.SOLP2
    373688960 B  0  A SBT_TAPE    30.04.2015 17:42:58 1       1       NO         20150430173000.SOLP2
    373927006 B  0  A SBT_TAPE    06.05.2015 12:49:58 1       1       NO         20150506123352.SOLP2
    373688966 B  0  A SBT_TAPE    30.04.2015 17:45:12 1       1       NO         20150430173000.SOLP2
    373688964 B  0  A SBT_TAPE    30.04.2015 17:43:12 1       1       NO         20150430173000.SOLP2
    
    List of Backups
    
    ===============
    
    Key     TY LV S Device Type Completion Time     #Pieces #Copies Compressed Tag
    ------- -- -- - ----------- ------------------- ------- ------- ---------- ---
    
    373689024 B  A  A SBT_TAPE    30.04.2015 17:45:28 1       1       NO         TAG20150430T174527
    373701547 B  A  A SBT_TAPE    30.04.2015 21:40:29 1       1       NO         TAG20150430T214020
    373708776 B  A  A SBT_TAPE    30.04.2015 23:40:24 1       1       NO         TAG20150430T234018
    373715185 B  A  A SBT_TAPE    01.05.2015 03:40:28 1       1       NO         TAG20150501T034020
    373718630 B  A  A SBT_TAPE    01.05.2015 06:40:49 1       1       NO         TAG20150501T064020
    373747390 B  A  A SBT_TAPE    01.05.2015 23:40:33 1       1       NO         TAG20150501T234022
    373755172 B  A  A SBT_TAPE    02.05.2015 03:40:31 1       1       NO         TAG20150502T034022
    373758977 B  A  A SBT_TAPE    02.05.2015 06:40:41 1       1       NO         TAG20150502T064016
    373763033 B  A  A SBT_TAPE    02.05.2015 09:40:27 1       1       NO         TAG20150502T094020
    373772933 B  A  A SBT_TAPE    02.05.2015 12:40:20 1       1       NO         TAG20150502T124018
    373775169 B  A  A SBT_TAPE    02.05.2015 14:40:17 1       1       NO         TAG20150502T144016
    373818387 B  A  A SBT_TAPE    04.05.2015 01:01:30 1       1       NO         TAG20150502T164016
    373826167 B  A  A SBT_TAPE    04.05.2015 03:41:13 1       1       NO         TAG20150504T034021
    373826168 B  A  A SBT_TAPE    04.05.2015 03:41:33 1       1       NO         TAG20150504T034021
    373830219 B  A  A SBT_TAPE    04.05.2015 06:41:12 1       1       NO         TAG20150504T064022
    373835638 B  A  A SBT_TAPE    04.05.2015 09:40:22 1       1       NO         TAG20150504T094018
    373847467 B  A  A SBT_TAPE    04.05.2015 12:40:35 1       1       NO         TAG20150504T124024
    373889376 B  A  A SBT_TAPE    05.05.2015 14:40:43 1       1       NO         TAG20150505T144022
    373889377 B  A  A SBT_TAPE    05.05.2015 14:40:58 1       1       NO         TAG20150505T144022
    373889378 B  A  A SBT_TAPE    05.05.2015 14:41:26 1       1       NO         TAG20150505T144022
    373889379 B  A  A SBT_TAPE    05.05.2015 14:42:03 1       1       NO         TAG20150505T144022
    373889380 B  A  A SBT_TAPE    05.05.2015 14:42:20 1       1       NO         TAG20150505T144022
    373889381 B  A  A SBT_TAPE    05.05.2015 14:42:37 1       1       NO         TAG20150505T144022
    373924623 B  A  A SBT_TAPE    06.05.2015 12:32:13 1       1       NO         TAG20150506T123133
    373924624 B  A  A SBT_TAPE    06.05.2015 12:32:45 1       1       NO         TAG20150506T123133
    373924625 B  A  A SBT_TAPE    06.05.2015 12:33:02 1       1       NO         TAG20150506T123133
    373927099 B  A  A SBT_TAPE    06.05.2015 13:01:48 1       1       NO         TAG20150506T130147
    373927100 B  A  A SBT_TAPE    06.05.2015 13:01:49 1       1       NO         TAG20150506T130147
    
    validation succeeded for backup piece
    Media recovery start SCN is 169070460360
    Recovery must be done beyond SCN 169092024179 to clear datafile fuzziness
    validation succeeded for backup piece
    Finished restore at 06.05.2015 14:18:16
    
  • How to use the DBMS_FILE_TRANSFER.PUT_FILE procedure

    BEGIN
      SYS.DBMS_FILE_TRANSFER.PUT_FILE(
       source_directory_object      => 'DPUMP',
       source_file_name             => 'myfile.txt',
       destination_directory_object => 'REMOTE_DPDUMP',
       destination_file_name        => 'myfile.txt',
       destination_database         => 'REFRESH.MYDOMAIN.COM');
    END;
    /
    

    Used in a script:
    
    export DMP_NAME=`echo $1 | tr '[a-z]' '[A-Z]'`
    export DPDIR=`echo $4 | tr '[a-z]' '[A-Z]'`
    
    #####################################################
    # Transfer to remote server using DBMS_FILE_TRANSFER
    #####################################################
    
    cat << EoF > ${DBA_ADMIN}/sql/copy_file.sql
    set trimspool on
    spool copy_file.log
    Prompt Transferring Dumpfiles;
    define file_name=&1
    
    
    BEGIN
      SYS.DBMS_FILE_TRANSFER.PUT_FILE(
       source_directory_object      => 'DPUMP',
       source_file_name             => '&file_name',
       destination_directory_object => '${DPDIR}',
       destination_file_name        => '&file_name',
       destination_database         => 'REFRESH.MYDOMAIN.COM');
    END;
    /
    exit
    EoF
    
    for dmpfile in $(ls /oracle/datapump/${DMP_NAME}_*.dmp); do
     file_name=`echo $dmpfile | cut -d / -f 7`
    
    sqlplus -s / as sysdba @${DBA_ADMIN}/sql/copy_file.sql ${file_name} > ${BATCHDIR}/file_name.log 2> ${BATCHDIR}/file_name.err &
    done
    wait
    
    rm -f  ${DBA_ADMIN}/sql/copy_file.sql
    

    How to use RMANs LIST command to find individual archivelogs or a sequence of archivelogs





    To list an individual backup, any of the three alternatives bellow would be valid query using rman:
    RMAN> list backup of archivelog logseq=120316;
    RMAN> list backup of archivelog logseq 120316;
    RMAN> list backup of archivelog sequence 120316;
    
    To view backups of archivelog between two sequences:

    RMAN> list backup of archivelog sequence between 120316 and 120317;
    RMAN> list backup of archivelog from logseq 412593 until logseq 412656;
    

    Use the SUMMARY directive to view only the backupsets affected:
    RMAN> list backup of archivelog from logseq 412593 until logseq 412656 summary;
    RMAN> list backup of archivelog sequence between 120316 and 120317 summary;
    

    To view backups completed before a specific date:
    RMAN> list backup completed before "to_date( '18.12.2009 18:00:00', 'DD.MM.YYYY HH24:MI:SS')";
    RMAN> list backup of archivelog all summary completed before "to_date( '18.12.2009 18:00:00', 'DD.MM.YYYY HH24:MI:SS')";
    RMAN> list archivelog all completed before 'sysdate-2';:
    

    To list archivelogs recognized by the controlfile between two sequnce numbers:
    RMAN> list archivelog sequence between 110880 and 110881;
    
    To list archivelogs recognized by the controlfile up until yesterday:
    RMAN> list archivelog until time 'sysdate-1';
    
    To list archivelogs recognized by the controlfile from two days ago, up until yesterday:
    RMAN> list archivelog from time 'sysdate-2' until time 'sysdate-1';
    
    To limit the list of archivelogs to the ones taken on a specific date, in this case, the last of January 2022:
    RMAN> list archivelog from time '31.01.2022' until time '01.02.2022';
    
    If you remove the "until time" clause, RMAN will list all the archivelogs from 31.01.2022 up until the latest ones:
    RMAN> list archivelog from time '31.01.2022';
    
    Remember, the value of sysdate is the time right now, sysdate-1 is 24hrs ago, sysdate-2 is 48 hours ago, etc.
     select sysdate, sysdate-1, sysdate-2 from dual;
    
    SYSDATE             SYSDATE-1           SYSDATE-2
    ------------------- ------------------- -------------------
    03.02.2022 12:24:12 02.02.2022 12:24:12 01.02.2022 12:24:12
    

    ksh: script that will send alert when flash recovery are is filling up

    #!/usr/bin/ksh
    # Vegard Kasa
    # 11.07.2013
    #
    # Alert when FRA is filling up...
    #############################################################################################################
    export NOW=`date +\%d.\%m.\%y`
    export NLS_DATE_FORMAT='DD.MM.YYYY'
    ####################################################################
    # Set the script base to either $DBA_ADMIN in case of original build
    # or $DBA_ADMIN_HOME in case of newer build.
    ####################################################################
    if [ -n "${DBA_ADMIN}" ]; then
     ##############
     # Original build
     ##############
     SCRIPT_BASE=$DBA_ADMIN
    elif [ -n "${DBA_ADMIN_HOME}" ]; then
     #################
     # Another build
     # uses different
     # variable names
     #################
     SCRIPT_BASE=${DBA_ADMIN_HOME}
    fi
    
    
    cat << EoF > ${SCRIPT_BASE}/sql/get_sum_fra.sql
    set termout   off
    set trimspool on
    set verify    off
    set feedback  off
    set echo      off
    set linesize  200
    set heading   off
    set pagesize  0
    spool ${SCRIPT_BASE}/log/alert_fra_full_${NOW}.log
    SELECT    LTRIM(sum(PERCENT_SPACE_USED))
    FROM      V\$FLASH_RECOVERY_AREA_USAGE;
    exit
    EoF
    sqlplus -s / as sysdba @${SCRIPT_BASE}/sql/get_sum_fra.sql
    ##########################################################
    # Send the output via e-mail to the designated receipients
    ##########################################################
    PRC=`cat ${SCRIPT_BASE}/log/alert_fra_full_${NOW}.log`
    if [ ${PRC} -gt 80 ]; then
     echo "Warning: In database ${ORACLE_SID}, the FRA is ${PRC} percent used!"  |mailx -r monitoring@yourdomain.com -s "FRA usage report for database ${ORACLE_SID}" dba@yourdomain.com
    fi
    exit
    

    Monday, January 20, 2014

    Template for RMAN script, including Netbackup directives

    Executed as user oracle directly on the server:
    
    connect target /
    connect catalog rmancat/password@RMANCAT
    run {
    allocate channel t1 type sbt PARMS="BLKSIZE=1048576"  maxopenfiles 64;
    allocate channel t2 type sbt PARMS="BLKSIZE=1048576"  maxopenfiles 64;
    send 'NB_ORA_POLICY=my_policy_name,NB_ORA_CLIENT=my_client_name-bkp.mydomain.com,NB_ORA_SCHED=my_schedule_name';
    
    rman commands here
    
    
    release channel t1;
    release channel t2;
    }
    

    to execute:

    $ rman cmdfile='restore_archlog.cmd' log='restore_archlog.log'

    How the Archived Redo Log Deletion Policy works

    Archived redo logs can be deleted automatically by the database or as a result of user-initiated RMAN commands. Note that *only* logs in the flash recovery area can be deleted automatically by the database.

    You can use RMAN to create a persistent configuration that governs when archived redo logs are eligible for deletion from disk, by using the ARCHIVELOG DELETION POLICY. The archived redo log deletion policy is configured to NONE by default.

    When the Archived Redo Log Deletion Policy Is ENABLED

    You can use the CONFIGURE ARCHIVELOG DELETION POLICY command to specify when archived redo logs are eligible for deletion. This deletion policy applies to all archiving destinations, including the flash recovery area.

    For archived redo log files in the flash recovery area, the database retains them as long as possible and automatically deletes eligible logs [only] when additional disk space is required.

    You can also manually delete eligible logs from any location, whether inside or outside the flash recovery area, when you issue BACKUP ... DELETE INPUT or DELETE ARCHIVELOG.

    When the Archived Redo Log Deletion Policy Is DISABLED

    In this case, RMAN considers archived redo log files in the recovery area as eligible for deletion if they meet both of the following conditions:

    1. The archived redo logs, whether in the flash recovery area or outside of it, have been transferred to the required remote destinations specified by LOG_ARCHIVE_DEST_n.
    2. The archived redo logs have been backed up at least once to disk or SBT or the logs are obsolete according to the backup retention policy.

    The backup retention policy considers logs obsolete only if the logs are not needed by a guaranteed restore point and the logs are not needed by Oracle Flashback Database.


    Source: Oracle Documentation

    How does Oracle manage disk space in the Flash Recovery Area?

    Files in the recovery area are permanent or transient.

    Permanent files are active files used by the database instance (like control files).
    All files that are not permanent are transient.

    In general, Oracle Database eventually deletes transient files after they become obsolete under the backup retention policy or have been backed up to tape.

    Space in the flash recovery area is balanced among backups and archived logs that must be kept according to the retention policy, and other files which may be subject to deletion.
    Oracle Database does not delete eligible files from the flash recovery area until the space must be reclaimed for some other purpose.
    Thus, files recently moved to tape are often still available on disk for use in recovery. The recovery area can thus serve as a cache for tape.
    When the flash recovery area is full, Oracle Database automatically deletes eligible files to reclaim space in the recovery area as needed.

    The following rules govern when files become eligible for deletion from the recovery area:
    • Permanent files are never eligible for deletion.
    • Files that are obsolete under the retention policy are eligible for deletion.
    • Transient files that have been copied to tape are eligible for deletion.
    • Archived redo logs are not eligible for deletion until all the consumers of the logs have satisfied their requirements. Consumers of logs can include RMAN, standby databases, Oracle Streams databases, and the Flashback Database feature.

    The safe and reliable way to control deletion of files from the flash recovery area is to configure your retention policy and archived log deletion policy.
    To increase the likelihood that files moved to tape are retained on disk, increase the flash recovery area quota.

    Source: Oracle Documentation

    How to restore archive logs to a new destination

    This example restores all archived redo logs to the /oracle/temp_restore directory:
    RMAN> RUN
    { 
      SET ARCHIVELOG DESTINATION TO '/oracle/temp_restore/'; <-- note the last /
      RESTORE ARCHIVELOG ALL;
    }
    
    
    If the file is already on disk you will get an error message from RMAN.

    To override this, use the force option:
    RMAN> run {
    2> allocate channel t1 device type 'sbt';
    3> set archivelog destination to '/oracle/temp_restore/';
    4> restore archivelog logseq 15572 force;
    5> }
    

    Friday, January 17, 2014

    How is the database time zone set?

    Answer: it is set at creation time.
    If not explicitly defined by the DBA, it will use the time zone of the server's operating system.

    If you want to set it explicitly, do so in the CREATE DATABASE statement:
    CREATE DATABASE PRODDB
    .
    .
    SET TIME_ZONE='-05:00';
    
    
    
    Or set it to a named region, like this:
    
    CREATE DATABASE PRODDB
    .
    .
    SET TIME_ZONE='Europe/Zurich';
    
    
    The database time zone is relevant only for TIMESTAMP WITH LOCAL TIME ZONE columns.

    You can change the database time zone by using the SET TIME_ZONE clause of the ALTER DATABASE statement:

    ALTER DATABASE SET TIME_ZONE='05:00';
    ALTER DATABASE SET TIME_ZONE='Europe/Zurich';

    The ALTER DATABASE SET TIME_ZONE statement will return an error if the database contains a table using a TIMESTAMP WITH LOCAL TIME ZONE column and the column contains data. You will also have to restart the database.


    To see the current time zone of the database:
    SELECT DBTIMEZONE,SESSIONTIMEZONE FROM DUAL;

    DBTIMEZONE SESSIONTIMEZONE
    +01:00 Europe/Zurich

    For a database used globally, it may be beneficial to set the database time to UTC (0:00) regardless of where it is physically hosted.

    Source: Oracle Documentation

    Thursday, January 16, 2014

    How does Oracle Data Pump Import handles referential integrety constraint violations?

    How does Oracle Data Pump Import handles referential integrety constraint violations?

    To find out, let's use the two tables SHIPS and PORTS, which are connected by a referential constraint from SHIPS to PORTS, called FK_SHIPS_PORTS.
    CREATE TABLE SHIPS
    (
      SHIP_ID       NUMBER,
      SHIP_NAME     VARCHAR2(20 BYTE),
      CAPACITY      NUMBER,
      LENGTH        NUMBER,
      HOME_PORT_ID  NUMBER,
      LIFEBOATS     NUMBER(3),
      CONSTRAINT PK_SHIPS PRIMARY KEY (SHIP_ID),
      CONSTRAINT FK_SHIPS_PORTS FOREIGN KEY (HOME_PORT_ID) 
      REFERENCES PORTS (PORT_ID)
    );
    
    CREATE TABLE PORTS
    (
      PORT_ID    NUMBER,
      PORT_NAME  VARCHAR2(20 BYTE),
      COUNTRY    VARCHAR2(40 BYTE),
      CAPACITY   NUMBER,
      CONSTRAINT PK_PORTS PRIMARY KEY (PORT_ID)
    );
    
    In other words, you cannot add a ship without a valid PORT_ID that already exist in table PORTS.

    PORT_ID PORT_NAME COUNTRY CAPACITY
    1 Baltimore USA  
    2 Charleston USA  
    3 Tampa USA  
    4 Miami USA  

    SHIP_ID SHIP_NAME CAPACITY LENGTH HOME_PORT_ID LIFEBOATS
    1 Codd Crystal 2052 855 1 80
    15 Codd Champion 2000 650   30
    2 Codd Elegance 2974 952 2 95
    16 Codd Victorious 2055 876 2  
    17 Codd Grandeur 2030 840 4  
    18 Codd Prince 1500 550 2 32
    20 Codd Norway 1500 900 3 80

    I now remove one row from the PORTS table, so that new rows being imported will have a missing parent key. In order to do that I need to also remove any child record from SHIPS, in my case, only one:

    DELETE TESTUSER.SHIPS WHERE HOME_PORT_ID = 1;
    DELETE TESTUSER.PORTS WHERE PORT_ID = 1;
    COMMIT;

    1 row deleted.
    1 row deleted.
    Commit complete.

    SCENARIO 1: "What happens if we use TABLE_EXISTS_ACTION=REPLACE when the table being replaced has a referential constraint to another table?"

    Result:

    • The operation will report an error because of a constraint violation issue.
    • All rows are imported into SHIPS, including the offending ones
    • The referential constraint is dropped.

    Error message:
    Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
    . . imported "TESTUSER"."SHIPS" 7.289 KB 7 rows
    Processing object type TABLE_EXPORT/TABLE/CONSTRAINT/REF_CONSTRAINT
    ORA-39083: Object type REF_CONSTRAINT failed to create with error:
    ORA-02298: cannot validate (TESTUSER.FK_SHIPS_PORTS) - parent keys not found
    Failing sql is:
    ALTER TABLE "TESTUSER"."SHIPS" ADD CONSTRAINT "FK_SHIPS_PORTS" FOREIGN KEY ("HOME_PORT_ID") REFERENCES "TESTUSER"."PORTS" ("PORT_ID") DEFERRABLE ENABLE


    SCENARIO 2: "What happens if we use TABLE_EXISTS_ACTION=TRUNCATE when the table being truncated has a referential constraint to another table?"

    Result:

    • The operation will report an error because of a constraint violation issue.
    • The SHIPS table is left truncated, no rows are loaded.
    • The referential constraint stays.

    Error message:
    Processing object type TABLE_EXPORT/TABLE/TABLE
    ORA-39153: Table "TESTUSER"."SHIPS" exists and has been truncated. Data will be loaded but all dependent metadata will be skipped due to table_exists_action of truncate
    Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
    ORA-31693: Table data object "TESTUSER"."SHIPS" failed to load/unload and is being skipped due to error:
    ORA-02291: integrity constraint (TESTUSER.FK_SHIPS_PORTS) violated - parent key not found


    Both cases requires manual intervention afterwards to cleanup offending rows, and then to recreate the constraint.
    One way to do so would be to allow for orphan rows through temporarily disabling the index, loading the rows, then reenabling the index using the NOVALIDATE option.

    First disable the constraint:
    SQL> ALTER TABLE SHIPS DISABLE CONSTRAINT FK_SHIPS_PORTS;

    Table altered.

    Load the data once more:
    Processing object type TABLE_EXPORT/TABLE/TABLE
    ORA-39153: Table "TESTUSER"."SHIPS" exists and has been truncated. Data will be loaded but all dependent metadata will be skipped due to table_exists_action of truncate
    Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
    . . imported "TESTUSER"."SHIPS" 7.289 KB 7 rows
    Processing object type TABLE_EXPORT/TABLE/INDEX/INDEX
    Processing object type TABLE_EXPORT/TABLE/CONSTRAINT/CONSTRAINT
    Processing object type TABLE_EXPORT/TABLE/INDEX/STATISTICS/INDEX_STATISTICS
    Processing object type TABLE_EXPORT/TABLE/CONSTRAINT/REF_CONSTRAINT

    Finally, enable the constraint again. However, tell oracle to disregard existing rows, only apply the constraint to new rows:
    SQL> ALTER TABLE SHIPS ENABLE NOVALIDATE CONSTRAINT FK_SHIPS_PORTS;

    Table altered.

    SQL>

    Example is based on Steve O'Heam's "SQL Certified SQL Expert Exam Guide"

    How to drop a table partition without invalidating global indexes

    My interval range partitioned table looks as follows:
    
    CREATE TABLE SEGMENT_SIZES(
      SEGMENT_SIZES_ID NUMBER,
      STIMESTAMP      DATE,
      OWNER           VARCHAR2(30 BYTE),
      SEGMENT_NAME    VARCHAR2(30 BYTE),
      PARTITION_NAME  VARCHAR2(30 BYTE),
      SEGMENT_TYPE    VARCHAR2(20 BYTE),
      BYTES           NUMBER,
      CONSTRAINT SEGMENT_SIZES_PK PRIMARY KEY (SEGMENT_SIZES_ID)
    )
    PARTITION BY RANGE (STIMESTAMP )
    -- Use 11gR1 Interval Partitioning
    INTERVAL (NUMTOYMINTERVAL(1,'MONTH'))
    (
       PARTITION P062013 VALUES LESS THAN (TO_DATE('01.07.2013','DD.MM.YYYY'))
    )
    TABLESPACE TOOLS
    ENABLE ROW MOVEMENT
    COMPRESS FOR ALL OPERATIONS;
    
    It was populated with data, which created the needed partititions automatically.
    The primary key defined on the table will of course create a global index spanning all partitions.
    Consequently, during partition maintenance operations, you will end up with an UNUSUABLE primary key index if you drop a partition, as follows:

    ALTER TABLE SEGMENT_SIZES DROP PARTITION SYS_P42;

    However, if you you add the "UPDATE INDEXES" clause, oracle will update the global index; the index will remain USABLE:

    ALTER TABLE SEGMENT_SIZES DROP PARTITION SYS_P42 UPDATE INDEXES;

    Keep in mind that you cannot drop the highest range partition of an interval-partitioned table!

    Source: Oracle Documentation

    why am I getting ORA-14006: invalid partition name when attempting to drop a partition in TOAD?

    In TOAD you are trying to drop a partition, as follows:

    alter table segment_sizes drop partition SYS_P41;

    But you get ORA-14006: invalid partition name as a result.

    Solution: remove the ";" at the end of the statement, and try again.
    Alternatively, execute the statement through SQL*plus.

    Source: Derya Oktay's Oracle Weblog

    Wednesday, January 15, 2014

    How to use the sqlplus "autotrace" facility

    SET AUTOT ON
    Executes the SQL and returns the execution plan and statistics (shorthand for "set autotrace on")

    SET AUTOT TRACE
    Executes the SQL and returns the execution plan and statistics (shorthand for "set autotrace traceonly")

    Note: Using ON or TRACEONLY with no explicit options defaults to EXPLAIN STATISTICS.

    SET AUTOT TRACE EXP
    Explains the SQL, omits statistics and does not execute the SQL(shorthand for "set autotrace traceonly explain")
    The SQL statement is never execute for real, only explained.

    SET AUTOT TRACE EXP STAT
    Executes the SQL, displays the execution plan, displays statistics. Executes the SQL, but supresses the output (shorthand for "set autotrace traceonly explain statistics")

    SET AUTOT OFF
    Disables autotraceing (shorthand for "set autotrace off")

    If you have trouble getting the autotrace feature to work, make sure you have created the PLUSTRACE role.

    Source: Oracle 19c Documentation

    Tuesday, January 14, 2014

    sdtperfmeter - a graphical monitoring of cpu, paging and I/O on Solaris

    Create a file called monitor.sh:

    #!/usr/bin/bash

    /usr/dt/bin/sdtperfmeter -t page &
    /usr/dt/bin/sdtperfmeter -t cpu &
    /usr/dt/bin/sdtperfmeter -t disk &

    exit


    Start your X server, set display to your client, then execute in background:

    ./monitor.sh &

    Works on Solaris 10 (and several previous versions)

    How to generate a script to rebuild unusable index partitions



    set trimspool on
    set lines     200
    set pages     0
    set heading   off
    set verify    off
    set feedback  off
    set echo      off
    spool rebuild_stmts.sql
    --Rebuild the index partition to the same tablespace:
    SELECT 'alter index ' || idx.table_owner || '.' ||  idx.index_name || ' rebuild partition ' || idxpart.partition_name || ';'
    FROM   dba_indexes idx, dba_ind_partitions idxpart
    WHERE  idx.table_owner = 'SCOTT'
    AND    idx.index_name = idxpart.index_name
    AND    idxpart.status <> 'USABLE'
    ORDER BY idx.table_owner, idx.index_name
    /
    --For a specific INDEX, reallocating the index partitions to a new tablespace:
    SELECT 'alter index ' || idx.table_owner || '.' ||  idx.index_name || ' rebuild partition ' || idxpart.partition_name || ' TABLESPACE MYTABLESPACE;'
    FROM    dba_indexes idx, dba_ind_partitions idxpart
    WHERE   idx.table_owner = 'SCOTT'
    AND     idx.index_name = idxpart.index_name
    AND     idx.index_name = 'IDX_01'
    AND     idxpart.status <> 'USABLE'
    ORDER BY idx.table_owner, idx.index_name
    /
    --Use sqlplus variables, also reallocating the index partitions to a new tablespace:
    SELECT 'alter index ' || idx.table_owner || '.' ||  idx.index_name || ' rebuild partition ' || idxpart.partition_name || ' TABLESPACE MYTABLESPACE;'
    FROM    dba_indexes idx, dba_ind_partitions idxpart
    WHERE   idx.table_owner = 'SCOTT'
    AND     idx.index_name = idxpart.index_name
    AND     idx.index_name = '&&index_name'
    AND     idxpart.status <> 'USABLE'
    ORDER BY idx.table_owner, idx.index_name
    /
    -- Rebuild index subpartitions. Also add a parallel statement and the ONLINE keyword:
    SELECT 'alter index ' || IDX.TABLE_OWNER || '.' ||  IDX.INDEX_NAME || ' rebuild subpartition ' || IDXSUBPART.SUBPARTITION_NAME || ' parallel 4 tablespace ' || IDXSUBPART.TABLESPACE_NAME ||' online;'
    FROM    DBA_INDEXES IDX, DBA_IND_SUBPARTITIONS IDXSUBPART
    WHERE   IDX.TABLE_OWNER IN ('SCOTT','JAMES')
    AND     IDX.INDEX_NAME = IDXSUBPART.INDEX_NAME
    AND     IDX.INDEX_NAME IN (SELECT UNIQUE INDEX_NAME
                                            FROM DBA_IND_SUBPARTITIONS
                                            WHERE STATUS = 'UNUSABLE')
    AND INDEX_OWNER NOT IN ('SYS','SYSTEM')
    AND IDXSUBPART.STATUS <> 'USABLE'
    ORDER BY IDX.OWNER, IDX.INDEX_NAME
    /
    
    Upon completion, the file "rebuild_stmts.sql" should contain your "ALTER INDEX REBUILD PARTITION..." directives.

    Friday, January 10, 2014

    How to display session information, followed by a kill-statement

    Often, my customers ask me to kill a runaway session for them, typically this will be in the form "Can you please kill session with session id 170 for us?. It's urgent!"

    Before I do so, I'd like to be one houndred percent certain that I kill the right session.
    To help me in such situations, I execute the script below. It will take one parameter, the sessions SID, and echo back some basic information about what the session is doing. Finally it prints a "kill session" command, which I can choose to execute if it was indeed the right session.

    set verify           off
    set linesize 200
    col "os process"     format a30
    col "os process id"  format a10
    col "osuser"         format a15
    col "schemaname"     format a20
    col "client program" format a20
    col "client name"    format a20
    col "session type"   format a20
    col status           format a10
    col "session type"   format a15
    cle scr
    prompt ===================================================
    prompt This script will print basic information about a
    prompt session.
    prompt
    accept SID prompt 'Pls enter SID of session: '
    prompt ===================================================
    prompt  Information about database session &&SID
    prompt ===================================================
    column host_name new_value v_hostname;
    
    set termout off
    select host_name
    from   v$instance;
    set termout on
    
    select
            p.program "os process",
            p.spid "os process id",
            p.username "osuser",
            s.sid,s.serial# "serial num",
            lower(s.schemaname) "schemaname",
            lower(s.osuser) "client name",
            s.program "client program",
            lower(s.status) "status",
            lower(s.type) "session type"
    from v$process p, v$session s
    where p.program not like 'oracle@v_hostname (%'
    and p.addr = s.paddr
    and p.addr = (select paddr from v$session where sid=&&SID)
    order by s.username asc
    /
    set heading off
    prompt ===================================================
    prompt  Kill statement for session &&SID:
    prompt ===================================================
    select 'alter system kill session ''' || s.sid || ',' || s.serial# || ''';'
    from   v$process p, v$session s
    where  p.program not like 'oracle@v_hostname (%'
    and    p.addr = s.paddr
    and    p.addr = (select paddr from v$session where sid=&&SID)
    order by s.username asc
    /
    
    exit
    

    How to use SYS_CONTEXT to display user information


    Oracle provides a built-in namespace called USERENV, which describes the current session.

    The function SYS_CONTEXT can be used to return the value of parameter associated with the context namespace. You can use this function in both SQL and PL/SQL statements.

    You can use the SYS_CONTEXT to retreive userinformation from the namespace USERENV, some examples below:
    SELECT SYS_CONTEXT ('userenv','OS_USER') "OS user", 
           SYS_CONTEXT('userenv','CURRENT_SCHEMA') "Current schema",
           SYS_CONTEXT('userenv','IDENTIFICATION_TYPE') "Identification type",
           SYS_CONTEXT('userenv','IP_ADDRESS') "IP",
           SYS_CONTEXT('userenv','HOST') "Host name",
           SYS_CONTEXT('userenv','SID') "SID",
           SYS_CONTEXT('userenv','SERVICE_NAME') "Service"
    FROM DUAL;

    Executed from a remote session, logged into the database as user SCOTT, the output from the query above will be:
    OS user Current schema Identification type IP Host name SID Service
    SCOTT SCOTT LOCAL 192.168.1.2 MYDOMAIN\MYCLIENT 170 myservice.mydomain.com


    To find the serial# of your session, you will need to query the v$session dynamic performance view. you need to have SELECT privileges on the V$SESSION view to use this query, so first, a grant is needed.

    SQL> show user
    USER is "SYS"

    GRANT SELECT ON V_$SESSION TO SCOTT;

    Now, as user SCOTT, you can execute the query

    SELECT SID, SERIAL#
    FROM V$SESSION
    WHERE SID=SYS_CONTEXT('USERENV','SID');


    Source: Oracle Documentation The 12.2 SYS_CONTEXT documentation can be found here

    How to retreive information about CPUs on a Solaris server

    For analytic purposes when dealing with installations, system validations, database design and performance tuning, you will often need to know hard facts about the CPUs of a server hosting an oracle database. Here are some of my notes on the matter.

    Use the psrinfo utility. The flag -p displays the number of physical processors, and the -v flag is for verbose output:

    oracle@host1[PRODDB11] psrinfo -pv
    The physical processor has 8 virtual processors (0-7)
    SPARC64-VII (portid 1024 impl 0x7 ver 0x91 clock 2400 MHz)
    The physical processor has 8 virtual processors (8-15)
    SPARC64-VII (portid 1032 impl 0x7 ver 0x91 clock 2400 MHz)

    Without any argument, psrinfo prints a tabular output of the CPUs(or cores), as follows:
    oracle@host1[PRODDB11] psrinfo
    0 on-line since 07/18/2011 18:18:57
    1 on-line since 07/18/2011 18:19:58
    2 on-line since 07/18/2011 18:19:58
    3 on-line since 07/18/2011 18:19:58
    4 on-line since 07/18/2011 18:19:58
    5 on-line since 07/18/2011 18:19:58
    6 on-line since 07/18/2011 18:19:58
    7 on-line since 07/18/2011 18:19:58
    8 on-line since 07/18/2011 18:19:58
    9 on-line since 07/18/2011 18:19:58
    10 on-line since 07/18/2011 18:19:58
    11 on-line since 07/18/2011 18:19:58
    12 on-line since 07/18/2011 18:19:58
    13 on-line since 07/18/2011 18:19:58
    14 on-line since 07/18/2011 18:19:58
    15 on-line since 07/18/2011 18:19:58

    The utility uname can also be helpful, when executed with the -X flag, which prints expanded system information:

    oraoracle@host1[PRODDB11] uname -X
    System = SunOS
    Node = zus60h-0034
    Release = 5.10
    KernelID = Generic_137111-04
    Machine = sun4u
    BusType =
    Serial =
    Users =
    OEM# = 0
    Origin# = 1
    NumCPU = 16


    The prtdiag utility, likewise:

    oraoracle@host1[PRODDB11] prtdiag |more
    System Configuration: Sun Microsystems sun4u Sun SPARC Enterprise M4000 Server
    System clock frequency: 1012 MHz
    Memory size: 32768 Megabytes

    ==================================== CPUs ====================================

    CPU CPU Run L2$ CPU CPU
    LSB Chip ID MHz MB Impl. Mask
    --- ---- ---------------------------------------- ---- --- ----- ----
    00 0 0, 1, 2, 3, 4, 5, 6, 7 2530 5.5 7 160
    00 1 8, 9, 10, 11, 12, 13, 14, 15 2530 5.5 7 160



    Wednesday, January 8, 2014

    How to install java in an Oracle 11gR2 database

    Source: Oracle Support article "How to Reload the JVM in 11.2.0.x (Doc ID 1112983.1)"

    Here are the steps I followed:

    First, confirmed that java is indeed not installed (see my previous note "Is java installed in my database")

    Step 1: Executed full export or another type of full backup (Oracle recommends a cold backup):
    Create a parameter file as follows:
    USERID='/ as sysdba'
    DIRECTORY=DPUMP
    DUMPFILE=full_exp_before_java.dmp
    LOGFILE=full_exp_before_java.log
    JOB_NAME=PREJAVA_EXP
    FULL=Y

    Execute the export from the command line:

    $ [PRODDB11] expdp parfile=full_exp.par

    Check that export finished successfully:
    Dump file set for SYS.PREJAVA_EXP is:
    /db_impexp/oracle/PRODDB1/full_exp_before_java.dmp
    Job "SYS"."PREJAVA_EXP" successfully completed at 09:10:41

    Step 2: shutdown of the database:
    $ [PRODDB11] srvctl status database -d PRODDB10
    Instance PRODDB11 is running on node node1
    $ [PRODDB11] srvctl stop database -d PRODDB1
    $ [PRODDB11] srvctl status database -d PRODDB1
    Instance PRODDB1 is not running on node node1

    Step 3: Create script full_rmjvm.sql:
    -- Start of File full_rmjvm.sql
    spool full_rmjvm.log
    set echo on
    connect / as sysdba
    startup mount
    alter system set "_system_trig_enabled" = false scope=memory;
    alter system enable restricted session;
    alter database open;
    @?/rdbms/admin/catnoexf.sql
    @?/rdbms/admin/catnojav.sql
    @?/xdk/admin/rmxml.sql
    @?/javavm/install/rmjvm.sql
    truncate table java$jvm$status;
    select * from obj$ where obj#=0 and type#=0;
    delete from obj$ where obj#=0 and type#=0;
    commit;
    select owner, count(*) from all_objects
    where object_type like '%JAVA%' group by owner;
    select obj#, name from obj$
    where type#=28 or type#=29 or type#=30 or namespace=32;
    select o1.name from obj$ o1,obj$ o2
    where o1.type#=5 and o1.owner#=1 and o1.name=o2.name and o2.type#=29;
    shutdown immediate
    set echo off
    spool off
    exit
    -- End of File full_rmjvm.sql

    Step 4: Remove existing java installations, if any. From a new sqlplus session, run the script full_rmjvm.sql.
    (Note that the script will start up the database for you)
    $ [PRODDB11] sqlplus / as sysdba @rmjvm.sql

    Step 5: Review the log file FULL_RMJVM.LOG
    In my case, java was not installed, so the removal scritp had nothing to do and exited with the following message:

    ERROR at line 1:
    ORA-20000: CATJAVA has not been loaded into the database.
    ORA-06512: at line 3

    Step 6: Create script full_jvminst.sql
    -- Start of File full_jvminst.sql
    spool full_jvminst.log;
    set echo on
    connect / as sysdba
    startup mount
    alter system set "_system_trig_enabled" = false scope=memory;
    alter database open;
    select obj#, name from obj$
    where type#=28 or type#=29 or type#=30 or namespace=32;
    @?/javavm/install/initjvm.sql
    select count(*), object_type from all_objects
    where object_type like '%JAVA%' group by object_type;
    @?/xdk/admin/initxml.sql
    select count(*), object_type from all_objects
    where object_type like '%JAVA%' group by object_type;
    @?/xdk/admin/xmlja.sql
    select count(*), object_type from all_objects
    where object_type like '%JAVA%' group by object_type;
    @?/rdbms/admin/catjava.sql
    select count(*), object_type from all_objects
    where object_type like '%JAVA%' group by object_type;
    @?/rdbms/admin/catexf.sql
    select count(*), object_type from all_objects
    where object_type like '%JAVA%' group by object_type;
    shutdown immediate
    set echo off
    spool off
    exit
    -- End of File full_jvminst.sql

    Step 7: Install the JVM
    a) Be sure the REMOVAL script, full_rmjvm.sql, completed successfully
    b) Create the following INSTALL script, full_jvminst.sql
    c) Run it from a new SQL*Plus session
    $ [PRODDB11] sqlplus / as sysdba @full_jvminst.sql

    Step 8: Review the log file FULL_JVMINST.LOG
    In my case, there were no errors and the logfile ends with:
    SQL> select count(*), object_type from all_objects
      2  where object_type like '%JAVA%' group by object_type;
    
      COUNT(*) OBJECT_TYPE                                                          
    ---------- -------------------                                                  
           317 JAVA DATA                                                            
           762 JAVA RESOURCE                                                        
         20332 JAVA CLASS                                                           
             2 JAVA SOURCE                                                          
    
    SQL> shutdown immediate
    Database closed.
    Database dismounted.
    ORACLE instance shut down.
    

    Step 9: Start the database:
    $ [PRODDB11] srvctl start database -d PRODDB10
    Step 10: Resolve Invalid Objects:
    $ [PRODDB11] sqlplus / as sysdba @?/rdbms/admin/utlrp.sql
    Step 11: Create the file validate_java_installation.sql
    -- Start of File validate_java_installation.sql
    set lines 200
    col banner format a80
    col comp_name format a30
    col version format a20
    col status format a20
    -- Validation Query 1
    select count(*), object_type
    from all_objects
    where object_type like '%JAVA%'
    and owner = 'SYS'
    group by object_type;
    
    -- Validation Query 2
    select owner, count(*)
    from all_objects 
    where object_type like '%JAVA%'
    and owner = 'SYS'group by owner;
    
    -- Validation Query 3
    select owner, object_type, count(*)
    from all_objects 
    where object_type like '%JAVA%'
    and status <> 'VALID'
    and owner = 'SYS'
    group by owner, object_type;
    
    SELECT * FROM ALL_REGISTRY_BANNERS
    WHERE   BANNER LIKE INITCAP('%Java%') 
    OR      BANNER LIKE UPPER('%JAVA%');
    
    SELECT  COMP_NAME,VERSION,STATUS 
    FROM    DBA_REGISTRY 
    WHERE   COMP_NAME LIKE INITCAP('%Java%') 
    OR      COMP_NAME LIKE UPPER('%JAVA%');
    
    SELECT * FROM V$OPTION 
    WHERE PARAMETER = 'Java';
    exit
    -- End of File validate_java_installation.sql
    
    Step 12: Validate the Install. Expected output should be similar to the following:
    $ [PRODDB11] sqlplus / as sysdba @validate_java_installation.sql
    SQL*Plus: Release 11.2.0.2.0 Production on Wed Jan 8 11:19:04 2014
    
    Copyright (c) 1982, 2010, Oracle.  All rights reserved.
    
    Connected to:
    Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
    With the Partitioning, Real Application Clusters, Automatic Storage Management, Oracle Label Security,
    OLAP, Data Mining, Oracle Database Vault and Real Application Testing options
    
      COUNT(*) OBJECT_TYPE
    ---------- -------------------
           317 JAVA DATA
           761 JAVA RESOURCE
         20285 JAVA CLASS
             2 JAVA SOURCE
    
    OWNER                            COUNT(*)
    ------------------------------ ----------
    SYS                                 21365
    
    no rows selected
    
    BANNER
    --------------------------------------------------------------------------------
    JServer JAVA Virtual Machine Release 11.2.0.2.0 - Development
    Oracle Database Java Packages Release 11.2.0.2.0 - Development
    
    COMP_NAME                      VERSION              STATUS
    ------------------------------ -------------------- --------------------
    JServer JAVA Virtual Machine   11.2.0.2.0           VALID
    Oracle Database Java Packages  11.2.0.2.0           VALID
    
    PARAMETER                                                        VALUE
    ---------------------------------------------------------------- ----------------------------------------------------------------
    Java                                                             TRUE
    
    Disconnected from Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
    With the Partitioning, Real Application Clusters, Automatic Storage Management, Oracle Label Security,
    OLAP, Data Mining, Oracle Database Vault and Real Application Testing options´
    

    -- All done! --