Quantcast
Channel: Andrew's Oracle Blog
Viewing all 330 articles
Browse latest View live

ORA-02495

$
0
0
This was tested on Oracle 11.2. If you try to resize a datafile in a read only tablespace, you get an ORA-02495. Changing the tablespace to read write makes the problem go away:
 
SQL> create tablespace andrew
  2  datafile '/tmp/andrew.dbf'
  3  size 100m
  4  /
 
Tablespace created.
 
SQL> alter tablespace andrew read only
  2  /
 
Tablespace altered.
 
SQL> alter database datafile '/tmp/andrew.dbf'
  2  resize 200m
  3  /
alter database datafile '/tmp/andrew.dbf'
*
ERROR at line 1:
ORA-02495: cannot resize file /tmp/andrew.dbf,
tablespace ANDREW is read only
 
SQL> alter tablespace andrew read write
  2  /
 
Tablespace altered.
 
SQL> alter database datafile '/tmp/andrew.dbf'
  2  resize 200m
  3  /
 
Database altered.
 
SQL>

Can You Use BETWEEN and a Subquery Together?

$
0
0
I saw a colleague about to throw away his copy of Oracle 7 The Complete Reference so I rescued it from the bin and started to read it (as you do). It said that you could not use BETWEEN and a subquery in the same SQL statement and I wondered if this restriction still applied. The oldest version of Oracle I have access to is Oracle 9 so I decided to try it out there. The examples I came up with are a bit artificial but they show that you can now use BETWEEN and a subquery in the same SQL statement. Furthermore, the subquery can be:
 
(1)  Before the AND.
(2)  After the AND.
(3)  Before and after the AND.   
 
SQL> select count(*) from dba_users
  2  where created between
  3  (select created from dba_users
  4   where username = 'DATALOAD')
  5  and '31-DEC-2013'
  6  /
 
  COUNT(*)
----------
        73
 
SQL> select count(*) from dba_objects
  2  where object_id between
  3  100 and
  4  (select max(object_id) from dba_objects
  5   where owner = 'SYSTEM')
  6  /
 
  COUNT(*)
----------
      8850
 
SQL> select count(*) from dba_tables
  2  where initial_extent between
  3  (select min(initial_extent)
  4   from dba_tables
  5   where owner = 'SYSTEM')
  6  and
  7  (select max(initial_extent)
  8   from dba_tables
  9   where owner = 'SYSTEM')
10  /
 
  COUNT(*)
----------
      1196
 
SQL>

ORA-13504

$
0
0
This was tested on Oracle 11.2.0.4. If you try to create a database like this i.e. without specifying a SYSAUX datafile clause:
 
create database extent management local
datafile '/database/NBAPERF/nba_system/system1.dbf'
size 100m autoextend on
logfile
group 1 ('/database/NBAPERF/nba_redo1/log1a.rdo',
         '/database/NBAPERF/nba_redo2/log1b.rdo') size 50m,
group 2 ('/database/NBAPERF/nba_redo1/log2a.rdo',
         '/database/NBAPERF/nba_redo2/log2b.rdo') size 50m
maxlogfiles 3
maxlogmembers 3
user sys identified by secret_password
user system identified by secret_password
default temporary tablespace temp
tempfile '/database/NBAPERF/nba_temp/temp1.dbf'
size 100m autoextend on
undo tablespace undotbs1
datafile '/database/NBAPERF/nba_system/undo1.dbf'
size 100m autoextend on
character set WE8ISO8859P1
/
 
Oracle will return an ORA-13504 and your database will not be created:
 
SQL>   2    3    4    5    6    7    8    9   10   11   12   13   14   15   16   17   18   19   20  create database extent management local
*
ERROR at line 1:
ORA-13504: No SYSAUX datafile clause specified
 
SQL>
 
You can stop this error occurring by specifying a SYSAUX datafile clause, as shown below:
 
create database extent management local
datafile '/database/NBAPERF/nba_system/system1.dbf'
size 100m autoextend on
sysaux datafile '/database/NBAPERF/nba_system/sysaux1.dbf'
size 100m autoextend on
logfile
group 1 ('/database/NBAPERF/nba_redo1/log1a.rdo',
         '/database/NBAPERF/nba_redo2/log1b.rdo') size 50m,
group 2 ('/database/NBAPERF/nba_redo1/log2a.rdo',
         '/database/NBAPERF/nba_redo2/log2b.rdo') size 50m
maxlogfiles 3
maxlogmembers 3
user sys identified by secret_password
user system identified by secret_password
default temporary tablespace temp
tempfile '/database/NBAPERF/nba_temp/temp1.dbf'
size 100m autoextend on
undo tablespace undotbs1
datafile '/database/NBAPERF/nba_system/undo1.dbf'
size 100m autoextend on
character set WE8ISO8859P1
/
 
… and the database will be created successfully:
 
SQL>   2    3    4    5    6    7    8    9   10   11   12   13   14   15   16   17   18   19   20   21   22
Database created.
 
SQL>

INVALID Materialized View NEEDS_COMPILE

$
0
0
This example was tested on Oracle 11.2. It shows how an on demand materialized view becomes invalid following DML on the underlying table. First I created a table:

SQL> create table tab1 (col1 number)
  2  /
 
Table created.
 
SQL>

Then I inserted the value 1 into it: 

SQL> insert into tab1 values (1)
  2  /
 
1 row created.
 
SQL>

I created an on demand materialized view on the table: 

SQL> create materialized view mv1
  2  refresh on demand
  3  as select * from tab1
  4  /
 
Materialized view created.
 
SQL>

I checked that it was VALID:

SQL> select object_type, status
  2  from user_objects
  3  where object_name = 'MV1'
  4  /
 
OBJECT_TYPE         STATUS
------------------- -------
TABLE               VALID
MATERIALIZED VIEW   VALID
 
SQL>

I updated the table, making the materialized view out of date: 

SQL> update tab1 set col1 = 2
  2  /
 
1 row updated.
 
SQL> commit
  2  /
 
Commit complete.
 
SQL> select * from tab1
  2  /
 
      COL1
----------
         2
 
SQL> select * from mv1
  2  /
 
      COL1
----------
         1
 
SQL>

Although you can still query the materialized view when this happens, it shows as INVALID:

SQL> select object_type, status
  2  from user_objects
  3  where object_name = 'MV1'
  4  /
 
OBJECT_TYPE         STATUS
------------------- -------
TABLE               VALID
MATERIALIZED VIEW   INVALID
 
SQL>

... and in need of compilation:

SQL> select mview_name, compile_state
  2  from user_mviews
  3  /
 
MVIEW_NAME                     COMPILE_STATE
------------------------------ -------------------
MV1                            NEEDS_COMPILE
 
SQL>

This isn't a problem but, if you are not happy with it, you can refresh the materialized view:

SQL> exec dbms_mview.refresh('MV1');
 
PL/SQL procedure successfully completed.
 
SQL>

This brings it in line with the underlying table:

SQL> select * from mv1
  2  /
 
      COL1
----------
         2
 
SQL>

It is then shown as VALID again:

SQL> select object_type, status
  2  from user_objects
  3  where object_name = 'MV1'
  4  /
 
OBJECT_TYPE         STATUS
------------------- -------
TABLE               VALID
MATERIALIZED VIEW   VALID
 
SQL>

... and not in need of compilation:

SQL> select mview_name, compile_state
  2  from user_mviews
  3  /
 
MVIEW_NAME                     COMPILE_STATE
------------------------------ -------------------
MV1                            VALID
 
SQL>

I updated the table, making the materialized view out of date again: 

SQL> update tab1 set col1 = 3
  2  /
 
1 row updated.
 
SQL> commit
  2  /
 
Commit complete.
 
SQL> select * from tab1
  2  /
 
      COL1
----------
         3
 
SQL> select * from mv1
  2  /
 
      COL1
----------
         2

SQL>

It was also INVALID and in need of compilation as before:
 
SQL> select object_type, status
  2  from user_objects
  3  where object_name = 'MV1'
  4  /
 
OBJECT_TYPE         STATUS
------------------- -------
TABLE               VALID
MATERIALIZED VIEW   INVALID
 
SQL> select mview_name, compile_state
  2  from user_mviews
  3  /
 
MVIEW_NAME                     COMPILE_STATE
------------------------------ -------------------
MV1                            NEEDS_COMPILE
 
SQL>

Another way to change this, if it bothers you, is to compile it:

SQL> alter materialized view mv1 compile
  2  /
 
Materialized view altered.
 
SQL>

This way, the materialized view is still out of date: 

SQL> select * from mv1
  2  /
 
      COL1
----------
         2
 
SQL>

... but it is no longer INVALID: 

SQL> select object_type, status
  2  from user_objects
  3  where object_name = 'MV1'
  4  /
 
OBJECT_TYPE         STATUS
------------------- -------
TABLE               VALID
MATERIALIZED VIEW   VALID
 
SQL>

... and it does not need compiling either:

SQL> select mview_name, compile_state
  2  from user_mviews
  3  /
 
MVIEW_NAME                     COMPILE_STATE
------------------------------ -------------------
MV1                            VALID
 
SQL>

ORA-01921

$
0
0
This was tested on Oracle 11.2. If you try to create a role which already exists, you get an ORA-01921:
 
SQL> create role dba
  2  /
create role dba
            *
ERROR at line 1:
ORA-01921: role name 'DBA' conflicts with another user
or role name
 
SQL>
 
You can check the names of existing roles by looking in DBA_ROLES something like this:
 
SQL> select count(*) from dba_roles
  2  where role = 'DBA'
  3  /
 
  COUNT(*)
----------
         1
 
SQL>
 
As the error message suggests, roles cannot match existing user names either. In the example below, there is no role called BRIAN. However, there is a user called BRIAN so you cannot create a role called BRIAN:
 
SQL> select count(*) from dba_roles
  2  where role = 'BRIAN'
  3  /
 
  COUNT(*)
----------
         0
 
SQL> select count(*) from dba_users
  2  where username = 'BRIAN'
  3  /
 
  COUNT(*)
----------
         1
 
SQL> create role brian
  2  /
create role brian
            *
ERROR at line 1:
ORA-01921: role name 'BRIAN' conflicts with another
user or role name
 
SQL>

Using RMAN to Clone a Database into a Different Database on the Same Server

$
0
0
This was tested on Oracle 11.2. I had an input or target database as follows:
 
SQL> select name from v$database
  2  /
 
NAME
---------
ORCL1
 
SQL> l
  1  select tablespace_name, file_name
  2* from dba_data_files order by 1
SQL> /
 
TABLESPACE_NAME FILE_NAME
--------------- --------------------------------------
SYSAUX          /database/RMAN_test/ORCL1/sysaux1.dbf
SYSTEM          /database/RMAN_test/ORCL1/system1.dbf
UNDOTBS1        /database/RMAN_test/ORCL1/undo1.dbf
 
SQL>
 
I wanted to create an output or auxiliary or clone database called ORCL2. First I created the directory structures for it:
 
Solaris: pwd
/database/RMAN_test
Solaris: mkdir ORCL2
Solaris:
 
Next I added the auxiliary database to the server’s oratab:
 
Solaris: cat /var/opt/oracle/oratab|grep ORCL2
ORCL2:/oracle/app/oracle/product/11.2.0:N
Solaris:
 
Then I copied the target database’s parameter file to create the auxiliary database’s parameter file:
 
Solaris: pwd
/oracle/app/oracle/product/11.2.0/dbs
Solaris: cp initORCL1.ora initORCL2.ora
Solaris:
 
I customised the auxiliary database’s parameter file as shown below. Note the db_file_name_convert parameter, which tells Oracle where to put the files for the auxiliary database:
 
Solaris: cat initORCL2.ora
compatible=11.2.0
control_files=/database/RMAN_test/ORCL2/control1.ctl
db_block_size=2048
db_file_name_convert=('/database/RMAN_test/ORCL1','/database/RMAN_test/ORCL2')
db_name=ORCL2
db_recovery_file_dest=/database/RMAN_test/FRA
db_recovery_file_dest_size=5g
os_authent_prefix=''
processes=100
remote_login_passwordfile='EXCLUSIVE'
sga_target=500m
undo_management=auto
undo_retention=900
undo_tablespace='UNDOTBS1'
Solaris:
 
I set up a password file for the auxiliary database:
 
Solaris: . oraenv
ORACLE_SID = [ORCL2] ?
The Oracle base remains unchanged with value /oracle/app/oracle/product
Solaris: cd $ORACLE_HOME/dbs
Solaris: orapwd file=orapwORCL2 password=secret_password
Solaris: ls -l orapwORCL2
-rw-r-----   1 oracle   dba         1536 Mar 14 18:17 orapwORCL2
Solaris:
 
I created a test table in the target database:
 
Solaris: sqlplus system/secret_password
 
SQL*Plus: Release 11.2.0.2.0 Production on Fri Mar 14 17:14:31 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, OLAP, Data Mining and Real Application Testing options
 
SQL> create table tab1 (col1 varchar2(30))
  2  /
 
Table created.
 
SQL> insert into tab1 values ('Andrew was here')
  2  /
 
1 row created.
 
SQL> exit
Disconnected from Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Solaris:
 
I backed up the target database:
 
Solaris: . oraenv
ORACLE_SID = [ORCL1] ?
The Oracle base remains unchanged with value /oracle/app/oracle/product
Solaris: rman target /
 
Recovery Manager: Release 11.2.0.2.0 - Production on Fri Mar 14 18:29:32 2014
 
Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.
 
connected to target database: ORCL1 (DBID=1226554576)
 
RMAN> backup database;
 
Starting backup at 14-MAR-14
using target database control file instead of recovery catalog
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=145 device type=DISK
channel ORA_DISK_1: starting full datafile backup set
channel ORA_DISK_1: specifying datafile(s) in backup set
input datafile file number=00001 name=/database/RMAN_test/ORCL1/system1.dbf
input datafile file number=00003 name=/database/RMAN_test/ORCL1/undo1.dbf
input datafile file number=00002 name=/database/RMAN_test/ORCL1/sysaux1.dbf
channel ORA_DISK_1: starting piece 1 at 14-MAR-14
channel ORA_DISK_1: finished piece 1 at 14-MAR-14
piece handle=/database/RMAN_test/FRA/ORCL1/backupset/2014_03_14/o1_mf_nnndf_TAG20140314T182942_9l6lnpnj_.bkp tag=TAG20140314T182942 comment=NONE
channel ORA_DISK_1: backup set complete, elapsed time: 00:00:15
channel ORA_DISK_1: starting full datafile backup set
channel ORA_DISK_1: specifying datafile(s) in backup set
including current control file in backup set
channel ORA_DISK_1: starting piece 1 at 14-MAR-14
channel ORA_DISK_1: finished piece 1 at 14-MAR-14
piece handle=/database/RMAN_test/FRA/ORCL1/backupset/2014_03_14/o1_mf_ncnnf_TAG20140314T182942_9l6lo8pk_.bkp tag=TAG20140314T182942 comment=NONE
channel ORA_DISK_1: backup set complete, elapsed time: 00:00:01
Finished backup at 14-MAR-14
 
RMAN>
 
I opened the auxiliary database in NOMOUNT mode:
 
Solaris: . oraenv
ORACLE_SID = [ORCL1] ? ORCL2
The Oracle base remains unchanged with value /oracle/app/oracle/product
Solaris: sqlplus / as sysdba
 
SQL*Plus: Release 11.2.0.2.0 Production on Fri Mar 14 17:30:46 2014
 
Copyright (c) 1982, 2010, Oracle.  All rights reserved.
 
Connected to an idle instance.
 
SQL> startup nomount
ORACLE instance started.
 
Total System Global Area  521936896 bytes
Fixed Size                  2225704 bytes
Variable Size             159386072 bytes
Database Buffers          352321536 bytes
Redo Buffers                8003584 bytes
SQL>
 
I got the target and auxiliary listening. I think the only one which HAS to be listening is the auxiliary. This involved adding them to /var/opt/oracle/tnsnames.ora:
 
Solaris: pwd
/var/opt/oracle
Solaris: cat tnsnames.ora
################
# tnsnames.ora #
################
#
ORCL1 =
   (DESCRIPTION =
     (ADDRESS_LIST =
          (ADDRESS =
             (PROTOCOL = TCP)
             (HOST = sge-mktred-lab2)
             (PORT = 1529)
          )
     )
     (CONNECT_DATA =
      (SID = ORCL1)
     )
   )
ORCL2 =
   (DESCRIPTION =
     (ADDRESS_LIST =
          (ADDRESS =
             (PROTOCOL = TCP)
             (HOST = sge-mktred-lab2)
             (PORT = 1529)
          )
     )
     (CONNECT_DATA =
      (SID = ORCL2)
     )
   )
Etc
Etc
 
… adding them to $ORACLE_HOME/network/admin/listener.ora:
 
Solaris: pwd
/oracle/app/oracle/product/11.2.0/network/admin
Solaris: cat listener.ora
SID_LIST_LISTENER_11 =
  (SID_LIST =
    (SID_DESC =
      (SID_NAME = ORCL1)
      (ORACLE_HOME = /oracle/app/oracle/product/11.2.0)
    )
    (SID_DESC =
      (SID_NAME = ORCL2)
      (ORACLE_HOME = /oracle/app/oracle/product/11.2.0)
    )
Etc
Etc
 
… restarting the listener and testing a remote connection:
 
Solaris: lsnrctl reload listener_11
 
LSNRCTL for Solaris: Version 11.2.0.2.0 - Production on 14-MAR-2014 17:54:55
 
Copyright (c) 1991, 2010, Oracle.  All rights reserved.
 
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=sge-mktred-lab2)(PORT=1529)))
The command completed successfully
Solaris: sqlplus system/secret_password@orcl1
 
SQL*Plus: Release 11.2.0.2.0 Production on Fri Mar 14 17:55:24 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, OLAP, Data Mining and Real Application Testing options
 
SQL>
 
I archived the redo in the target database:
 
Solaris: . oraenv
ORACLE_SID = [ORCL1] ?
The Oracle base remains unchanged with value /oracle/app/oracle/product
Solaris: sqlplus / as sysdba
 
SQL*Plus: Release 11.2.0.2.0 Production on Fri Mar 14 18:39:52 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, OLAP, Data Mining and Real Application Testing options
 
SQL> alter system archive log current
  2  /
 
System altered.
 
SQL>
 
Then I connected to the target and used the duplicate command to clone it into the auxiliary as follows:
 
Solaris: . oraenv
ORACLE_SID = [ORCL1] ?
The Oracle base remains unchanged with value /oracle/app/oracle/product
Solaris: rman target /
 
Recovery Manager: Release 11.2.0.2.0 - Production on Fri Mar 14 18:41:18 2014
 
Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.
 
connected to target database: ORCL1 (DBID=1226554576)
 
RMAN> connect auxiliary sys/secret_password@orcl2
 
connected to auxiliary database: ORCL2 (not mounted)
 
RMAN> duplicate target database to orcl2;
 
Starting Duplicate Db at 14-MAR-14
using target database control file instead of recovery catalog
allocated channel: ORA_AUX_DISK_1
channel ORA_AUX_DISK_1: SID=46 device type=DISK
 
contents of Memory Script:
{
   sql clone "create spfile from memory";
}
executing Memory Script
 
sql statement: create spfile from memory
 
contents of Memory Script:
{
   shutdown clone immediate;
   startup clone nomount;
}
executing Memory Script
 
Oracle instance shut down
 
connected to auxiliary database (not started)
Oracle instance started
 
Total System Global Area     521936896 bytes
 
Fixed Size                     2225704 bytes
Variable Size                163580376 bytes
Database Buffers             348127232 bytes
Redo Buffers                   8003584 bytes
 
contents of Memory Script:
{
   sql clone "alter system set  db_name =
''ORCL1'' comment=
''Modified by RMAN duplicate'' scope=spfile";
   sql clone "alter system set  db_unique_name =
''ORCL2'' comment=
''Modified by RMAN duplicate'' scope=spfile";
   shutdown clone immediate;
   startup clone force nomount
   restore clone primary controlfile;
   alter clone database mount;
}
executing Memory Script
 
sql statement: alter system set  db_name =  ''ORCL1'' comment= ''Modified by RMAN duplicate'' scope=spfile
 
sql statement: alter system set  db_unique_name =  ''ORCL2'' comment= ''Modified by RMAN duplicate'' scope=spfile
 
Oracle instance shut down
 
Oracle instance started
 
Total System Global Area     521936896 bytes
 
Fixed Size                     2225704 bytes
Variable Size                163580376 bytes
Database Buffers             348127232 bytes
Redo Buffers                   8003584 bytes
 
Starting restore at 14-MAR-14
allocated channel: ORA_AUX_DISK_1
channel ORA_AUX_DISK_1: SID=46 device type=DISK
 
channel ORA_AUX_DISK_1: starting datafile backup set restore
channel ORA_AUX_DISK_1: restoring control file
channel ORA_AUX_DISK_1: reading from backup piece /database/RMAN_test/FRA/ORCL1/backupset/2014_03_14/o1_mf_ncnnf_TAG20140314T182942_9l6lo8pk_.bkp
channel ORA_AUX_DISK_1: piece handle=/database/RMAN_test/FRA/ORCL1/backupset/2014_03_14/o1_mf_ncnnf_TAG20140314T182942_9l6lo8pk_.bkp tag=TAG20140314T182942
channel ORA_AUX_DISK_1: restored backup piece 1
channel ORA_AUX_DISK_1: restore complete, elapsed time: 00:00:01
output file name=/database/RMAN_test/ORCL2/control1.ctl
Finished restore at 14-MAR-14
 
database mounted
 
contents of Memory Script:
{
   set until scn  400755;
   set newname for datafile  1 to
"/database/RMAN_test/ORCL2/system1.dbf";
   set newname for datafile  2 to
"/database/RMAN_test/ORCL2/sysaux1.dbf";
   set newname for datafile  3 to
"/database/RMAN_test/ORCL2/undo1.dbf";
   restore
   clone database
   ;
}
executing Memory Script
 
executing command: SET until clause
 
executing command: SET NEWNAME
 
executing command: SET NEWNAME
 
executing command: SET NEWNAME
 
Starting restore at 14-MAR-14
using channel ORA_AUX_DISK_1
 
channel ORA_AUX_DISK_1: starting datafile backup set restore
channel ORA_AUX_DISK_1: specifying datafile(s) to restore from backup set
channel ORA_AUX_DISK_1: restoring datafile 00001 to /database/RMAN_test/ORCL2/system1.dbf
channel ORA_AUX_DISK_1: restoring datafile 00002 to /database/RMAN_test/ORCL2/sysaux1.dbf
channel ORA_AUX_DISK_1: restoring datafile 00003 to /database/RMAN_test/ORCL2/undo1.dbf
channel ORA_AUX_DISK_1: reading from backup piece /database/RMAN_test/FRA/ORCL1/backupset/2014_03_14/o1_mf_nnndf_TAG20140314T182942_9l6lnpnj_.bkp
channel ORA_AUX_DISK_1: piece handle=/database/RMAN_test/FRA/ORCL1/backupset/2014_03_14/o1_mf_nnndf_TAG20140314T182942_9l6lnpnj_.bkp tag=TAG20140314T182942
channel ORA_AUX_DISK_1: restored backup piece 1
channel ORA_AUX_DISK_1: restore complete, elapsed time: 00:00:25
Finished restore at 14-MAR-14
 
contents of Memory Script:
{
   switch clone datafile all;
}
executing Memory Script
 
datafile 1 switched to datafile copy
input datafile copy RECID=4 STAMP=842208178 file name=/database/RMAN_test/ORCL2/system1.dbf
datafile 2 switched to datafile copy
input datafile copy RECID=5 STAMP=842208178 file name=/database/RMAN_test/ORCL2/sysaux1.dbf
datafile 3 switched to datafile copy
input datafile copy RECID=6 STAMP=842208178 file name=/database/RMAN_test/ORCL2/undo1.dbf
 
contents of Memory Script:
{
   set until scn  400755;
   recover
   clone database
    delete archivelog
   ;
}
executing Memory Script
 
executing command: SET until clause
 
Starting recover at 14-MAR-14
using channel ORA_AUX_DISK_1
 
starting media recovery
 
archived log for thread 1 with sequence 18 is already on disk as file /database/RMAN_test/FRA/ORCL1/archivelog/2014_03_14/o1_mf_1_18_9l6m849g_.arc
archived log file name=/database/RMAN_test/FRA/ORCL1/archivelog/2014_03_14/o1_mf_1_18_9l6m849g_.arc thread=1 sequence=18
media recovery complete, elapsed time: 00:00:01
Finished recover at 14-MAR-14
Oracle instance started
 
Total System Global Area     521936896 bytes
 
Fixed Size                     2225704 bytes
Variable Size                167774680 bytes
Database Buffers             343932928 bytes
Redo Buffers                   8003584 bytes
 
contents of Memory Script:
{
   sql clone "alter system set  db_name =
''ORCL2'' comment=
''Reset to original value by RMAN'' scope=spfile";
   sql clone "alter system reset  db_unique_name scope=spfile";
   shutdown clone immediate;
   startup clone nomount;
}
executing Memory Script
 
sql statement: alter system set  db_name =  ''ORCL2'' comment= ''Reset to original value by RMAN'' scope=spfile
 
sql statement: alter system reset  db_unique_name scope=spfile
 
Oracle instance shut down
 
connected to auxiliary database (not started)
Oracle instance started
 
Total System Global Area     521936896 bytes
 
Fixed Size                     2225704 bytes
Variable Size                167774680 bytes
Database Buffers             343932928 bytes
Redo Buffers                   8003584 bytes
sql statement: CREATE CONTROLFILE REUSE SET DATABASE "ORCL2" RESETLOGS ARCHIVELOG
  MAXLOGFILES      3
  MAXLOGMEMBERS      3
  MAXDATAFILES       30
  MAXINSTANCES     1
  MAXLOGHISTORY      292
LOGFILE
  GROUP  1  SIZE 50 M ,
  GROUP  2  SIZE 50 M
DATAFILE
  '/database/RMAN_test/ORCL2/system1.dbf'
CHARACTER SET WE8ISO8859P1
 
contents of Memory Script:
{
   set newname for tempfile  1 to
"/database/RMAN_test/ORCL2/temp1.dbf";
   switch clone tempfile all;
   catalog clone datafilecopy  "/database/RMAN_test/ORCL2/sysaux1.dbf",
"/database/RMAN_test/ORCL2/undo1.dbf";
   switch clone datafile all;
}
executing Memory Script
 
executing command: SET NEWNAME
 
renamed tempfile 1 to /database/RMAN_test/ORCL2/temp1.dbf in control file
 
cataloged datafile copy
datafile copy file name=/database/RMAN_test/ORCL2/sysaux1.dbf RECID=1 STAMP=842208205
cataloged datafile copy
datafile copy file name=/database/RMAN_test/ORCL2/undo1.dbf RECID=2 STAMP=842208206
 
datafile 2 switched to datafile copy
input datafile copy RECID=1 STAMP=842208205 file name=/database/RMAN_test/ORCL2/sysaux1.dbf
datafile 3 switched to datafile copy
input datafile copy RECID=2 STAMP=842208206 file name=/database/RMAN_test/ORCL2/undo1.dbf
 
contents of Memory Script:
{
   Alter clone database open resetlogs;
}
executing Memory Script
 
database opened
Finished Duplicate Db at 14-MAR-14
 
RMAN>
 
Finally, I logged into the auxiliary database, made sure that the datafiles were in the correct place and checked the contents of the test table, which I created in the target earlier:
 
Solaris: . oraenv
ORACLE_SID = [ORCL1] ? ORCL2
The Oracle base remains unchanged with value /oracle/app/oracle/product
Solaris: sqlplus system/secret_password
 
SQL*Plus: Release 11.2.0.2.0 Production on Fri Mar 14 18:50:30 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, OLAP, Data Mining and Real Application Testing options
 
SQL> select tablespace_name, file_name
  2  from dba_data_files
  3  order by 1
  4  /
 
TABLESPACE_NAME  FILE_NAME
---------------- --------------------------------------
SYSAUX           /database/RMAN_test/ORCL2/sysaux1.dbf
SYSTEM           /database/RMAN_test/ORCL2/system1.dbf
UNDOTBS1         /database/RMAN_test/ORCL2/undo1.dbf
 
SQL> select * from tab1
  2  /
 
COL1
------------------------------
Andrew was here
 
SQL>

ORA-10636

$
0
0
I tested this in an Oracle 11.2.0.1.0 database. I created a table with lots of data:
 
SQL> create table andrews_table
  2  as select * from dba_tables
  3  /
 
Table created.
 
SQL> begin
  2  for a in 1..5 loop
  3  insert into andrews_table select * from andrews_table;
  4  end loop;
  5  end;
  6  /
 
PL/SQL procedure successfully completed.
 
SQL>
 
I deleted 30% of the rows. This left the table with some empty space:
 
SQL> select count(*) from andrews_table
  2  /
 
  COUNT(*)
----------
     99328
 
SQL> delete andrews_table where owner = 'SYS'
  2  /
 
30624 rows deleted.
 
SQL>
 
I checked the amount of space occupied by the table:
 
SQL> select bytes from dba_segments
  2  where segment_name = 'ANDREWS_TABLE'
  3  /
 
     BYTES
----------
  29360128
 
SQL>
 
I tried to recoup the empty space but this failed as row movement was not enabled:
 
SQL> alter table andrews_table shrink space
  2  /
alter table andrews_table shrink space
*
ERROR at line 1:
ORA-10636: ROW MOVEMENT is not enabled
 
SQL>
 
I enabled row movement…
 
SQL> alter table andrews_table enable row movement
  2  /
 
Table altered.
 
SQL>
 
…then I was able to reclaim the empty space…
 
SQL> alter table andrews_table shrink space
  2  /
 
Table altered.
 
SQL>
 
…and the table had gone down from 29M to 20M:
 
SQL> select bytes from dba_segments
  2  where segment_name = 'ANDREWS_TABLE'
  3  /
 
     BYTES
----------
  20185088
 
SQL>

How to Automatically Trace a User's Sessions

$
0
0
This example shows how you can use a logon trigger to automatically trace all sessions for a given user. This can be useful where an application is launched from the desktop and then fails before the DBA has had time to identify the SID and SERIAL# and start tracing it. First create the user:

SQL> conn system/manager@adhoc
Connected.
SQL> create user andrew identified by reid
  2  /

User created.

SQL> grant create session,
  2        create trigger,
  3        alter session to andrew
  4  /

Grant succeeded.

SQL>


Create the logon trigger in the new schema:

SQL> conn andrew/reid@adhoc  
Connected.
SQL> create or replace trigger immediate_trace
  2  after logon on andrew.schema
  3  begin
  4  execute immediate 'alter session set sql_trace=true';
  5  end;
  6  /

Trigger created.

SQL>


Logon as the new user again and run some SQL:

SQL> conn andrew/reid@adhoc
Connected.
SQL> select sysdate from dual
  2  /

SYSDATE
---------
01-FEB-10

SQL>


This will produce a trace file ready for further analysis e.g. by tkprof. It will contain, among other statements, the following:

=====================
PARSING IN CURSOR #3 len=64 dep=1 uid=86 oct=47 lid=86 tim=3571197485 hv=815087497 ad='2f4d8670' sqlid='ahb55sss9agw9'
begin
execute immediate 'alter session set sql_trace=true';
end;
END OF STMT
EXEC #3:c=0,e=8020,p=0,cr=0,cu=0,mis=0,r=1,dep=1,og=1,tim=3571197471
=====================


and

=====================
PARSING IN CURSOR #3 len=24 dep=0 uid=86 oct=3 lid=86 tim=3573486632 hv=2343063137 ad='2f47564c' sqlid='7h35uxf5uhmm1'
select sysdate from dual
END OF STMT
PARSE #3:c=0,e=341,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=3573486623
EXEC #3:c=0,e=91,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=3573487278
FETCH #3:c=0,e=60,p=0,cr=0,cu=0,mis=0,r=1,dep=0,og=1,tim=3573487570
STAT #3 id=1 cnt=1 pid=0 pos=1 obj=0 op='FAST DUAL  (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
FETCH #3:c=0,e=6,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=0,tim=3573490855

*** 2010-12-21 23:12:46.828
XCTEND rlbk=0, rd_only=1
=====================

ORA-12983

$
0
0
If you try to drop all columns in a table, you get an ORA-12983 as you cannot have a table with no columns. You can see what I mean in the examples below, which I ran in an Oracle 11.2 database:

SQL> create table tab1
  2  (col1 number)
  3  /
 
Table created.
 
SQL> alter table tab1 drop column col1
  2  /
alter table tab1 drop column col1
*
ERROR at line 1:
ORA-12983: cannot drop all columns in a table
 
SQL> create table tab2
  2  (col1 number,
  3   col2 number)
  4  /
 
Table created.
 
SQL> alter table tab2 drop (col1, col2)
  2  /
alter table tab2 drop (col1, col2)
*
ERROR at line 1:
ORA-12983: cannot drop all columns in a table
 
SQL>

INVALID Materialized View with COMPILATION_ERROR

$
0
0
In this example, Andrew grants access on a table to a role then grants this role to John. John creates a materialized view on Andrew’s table. Andrew updates his table, making John’s materialized view INVALID. John then tries to compile his materialized view, which gives it a COMPILE_STATE of COMPILATION_ERROR. Andrew then grants access to his table directly to John and the problem goes away. It was tested on Oracle 11.2:
 
First, user Andrew creates a table with one row of data: 

SQL> conn andrew/reid
Connected.
SQL> create table tab1 (col1 number)
  2  /
 
Table created.
 
SQL> insert into tab1 values (1)
  2  /
 
1 row created.
 
SQL>

Then he creates a role and grants access on the table to it:
 
SQL> create role role1
  2  /
 
Role created.
 
SQL> grant select on tab1 to role1
  2  /
 
Grant succeeded.
 
SQL> 

A new user called John is set up. He has access to Andrew’s table via ROLE1 and he creates an ON DEMAND materialized view on it:
 
SQL> conn / as sysdba
Connected.
SQL> create user john identified by smith
  2  default tablespace users
  3  quota unlimited on users
  4  /
 
User created.
 
SQL> grant create session,
  2        create table,
  3        create materialized view,
  4        role1
  5        to john
  6  /
 
Grant succeeded.
 
SQL> conn john/smith
Connected.
SQL> create materialized view mv1
  2  refresh on demand
  3  as select * from andrew.tab1
  4  /
 
Materialized view created.
 
SQL> select * from mv1
  2  /
 
      COL1
----------
         1
 
SQL> select object_type, status
  2  from user_objects
  3  where object_name = 'MV1'
  4  /
 
OBJECT_TYPE         STATUS
------------------- -------
TABLE               VALID
MATERIALIZED VIEW   VALID
 
SQL> select mview_name, compile_state
  2  from user_mviews
  3  /
 
MVIEW_NAME                     COMPILE_STATE
------------------------------ -------------------
MV1                            VALID
 
SQL>
 
Andrew updates his table:

SQL> conn andrew/reid
Connected.
SQL> update tab1 set col1 = 2
  2  /
 
1 row updated.
 
SQL>

This makes John’s materialized view INVALID and gives it a COMPILE_STATE of NEEDS_COMPILE. I showed you this in an earlier example:
 
SQL> conn john/smith
Connected.
SQL> select object_type, status
  2  from user_objects
  3  where object_name = 'MV1'
  4  /
 
OBJECT_TYPE         STATUS
------------------- -------
TABLE               VALID
MATERIALIZED VIEW   INVALID
 
SQL> select mview_name, compile_state
  2  from user_mviews
  3  /
 
MVIEW_NAME                     COMPILE_STATE
------------------------------ -------------------
MV1                            NEEDS_COMPILE
 
SQL> select * from mv1
  2  /
 
      COL1
----------
         1
 
SQL>

Johns spots this and tries to compile his materialized view but this time, it remains INVALID:

SQL> alter materialized view mv1 compile
  2  /
 
Materialized view altered.
 
SQL> select object_type, status
  2  from user_objects
  3  where object_name = 'MV1'
  4  /
 
OBJECT_TYPE         STATUS
------------------- -------
TABLE               VALID
MATERIALIZED VIEW   INVALID
 
SQL>

… and it now has a COMPILE_STATE of COMPILATION_ERROR:
 
SQL> select mview_name, compile_state
  2  from user_mviews
  3  /
 
MVIEW_NAME                     COMPILE_STATE
------------------------------ -------------------
MV1                            COMPILATION_ERROR
 
SQL> select * from mv1
  2  /
 
      COL1
----------
         1
 
SQL>

Even refreshing the materialized view does not make the problem go away:
 
SQL> exec dbms_mview.refresh('MV1');
 
PL/SQL procedure successfully completed.
 
SQL> select object_type, status
  2  from user_objects
  3  where object_name = 'MV1'
  4  /
 
OBJECT_TYPE         STATUS
------------------- -------
TABLE               VALID
MATERIALIZED VIEW   INVALID
 
SQL> select mview_name, compile_state
  2  from user_mviews
  3  /
 
MVIEW_NAME                     COMPILE_STATE
------------------------------ -------------------
MV1                            COMPILATION_ERROR
 
SQL>

Although it does bring the data up to date:

SQL> select * from mv1
  2  /
 
      COL1
----------
         2
 
SQL>

Andrew grants SELECT access directly to John:
 
SQL> conn andrew/reid
Connected.
SQL> grant select on tab1 to john
  2  /
 
Grant succeeded.
 
SQL>

… and when John tries to compile the materialized view again, the problem disappears:
 
SQL> conn john/smith
Connected.
SQL> alter materialized view mv1 compile
  2  /
 
Materialized view altered.
 
SQL> select object_type, status
  2  from user_objects
  3  where object_name = 'MV1'
  4  /
 
OBJECT_TYPE         STATUS
------------------- -------
TABLE               VALID
MATERIALIZED VIEW   VALID
 
SQL> select mview_name, compile_state
  2  from user_mviews
  3  /
 
MVIEW_NAME                     COMPILE_STATE
------------------------------ -------------------
MV1                            VALID
 
SQL> select * from mv1
  2  /
 
      COL1
----------
         2
 
SQL>

ORA-01442

$
0
0
This was tested on Oracle 11.2. If you define a column as NOT NULL then try to modify it to NOT NULL again, you get an ORA-01442:

SQL> create table tab1 (col1 number not null)
  2  /
 
Table created.
 
SQL> alter table tab1 modify (col1 number not null)
  2  /
alter table tab1 modify (col1 number not null)
                         *
ERROR at line 1:
ORA-01442: column to be modified to NOT NULL is
already NOT NULL
 
SQL>

Moving a Table Deletes its Statistics

$
0
0
Statistics are important as they help the optimizer to work out the execution plan for a SQL statement. If you move a table, this deletes its statistics so you need to analyze it again afterwards. You can see this in the example below. First I created a table:

SQL> create table object_list
  2  as select * from dba_objects
  3  /

Table created.

SQL>

When you create a table it has no statistics so the num_rows column is null:

SQL> select nvl(to_char(num_rows), 'NULL')
  2  as row_count
  3  from dba_tables
  4  where table_name = 'OBJECT_LIST'
  5  /

ROW_COUNT
----------------------------------------
NULL
                                                  
SQL>

When you calculate statistics, the num_rows column is updated:

SQL> analyze table object_list
  2  compute statistics
  3  /

Table analyzed.

SQL> select nvl(to_char(num_rows), 'NULL')
  2  as row_count
  3  from dba_tables
  4  where table_name = 'OBJECT_LIST'
  5  /

ROW_COUNT
----------------------------------------
7932

SQL>

Moving the table deletes the statistics so num_rows is null afterwards:

SQL> alter table object_list move
  2  /

Table altered.

SQL> select nvl(to_char(num_rows), 'NULL')
  2  as row_count
  3  from dba_tables
  4  where table_name = 'OBJECT_LIST'
  5  /

ROW_COUNT
---------------------------------------- NULL                                       

SQL>

To reinstate the statistics, simply analyze the table again:

SQL> analyze table object_list
  2  compute statistics
  3  /

Table analyzed.

SQL> select nvl(to_char(num_rows), 'NULL')
  2  as row_count
  3  from dba_tables
  4  where table_name = 'OBJECT_LIST'
  5  /

ROW_COUNT
----------------------------------------
7932

SQL>

ORA-00957

$
0
0
I tested this on Oracle 11.2. If you try to use a column name more than once in an Oracle table, you get an ORA-00957

SQL> create table tab1
  2  (col1 number,
  3   col1 number)
  4  /
col1 number)
*
ERROR at line 3:
ORA-00957: duplicate column name
 
SQL>

How to Diagnose a Locking Issue

$
0
0
A user ran an update statement and noticed that it did not seem to be doing anything:
 
SQL> conn gordon/bennett
Connected.
SQL> update andrew.emp
  2  set ename = 'COLIN'
  3  where ename = 'BRIAN'
  4  /
 
I looked up his SID in V$SESSION:
 
SQL> select sid from v$session
  2  where username = 'GORDON'
  3  /
 
       SID
----------
      393
 
SQL>

I ran the following SQL, waited 10 seconds and ran it again:
 
SQL> l
  1  select event, time_waited/100
  2  from v$session_event
  3  where sid = 393
  4  and wait_class != 'Idle'
  5* order by 2 desc
SQL> /
 
EVENT                          TIME_WAITED/100
------------------------------ ---------------
enq: TX - row lock contention           249.58
Disk file operations I/O                   .01
SQL*Net message to client                    0
 
SQL> /
 
EVENT                          TIME_WAITED/100
------------------------------ ---------------
enq: TX - row lock contention            258.6
Disk file operations I/O                   .01
SQL*Net message to client                    0
 
SQL> 

This showed me that there was an ongoing locking issue with this user. I looked up the SID of the blocking session like this:
 
SQL> l
  1  select blocking_session from v$session
  2* where sid = 393
SQL> /
 
BLOCKING_SESSION
----------------
             101
 
SQL>
 
I saw that it belonged to Fred:
 
SQL> l
  1  select username from v$session
  2* where sid = 101
SQL> /
 
USERNAME
------------------------------
FRED
 
SQL>

I found some SQL on the Internet and hoped that it would tell me what Fred was doing but it did not work:
 
SQL> l
  1  select b.sql_text
  2  from v$session a, v$sqlarea b
  3  where a.sql_address = b.address
  4* and a.sid = 101
SQL> /
 
no rows selected
 
SQL>
 
I wondered if Fred had run his SQL but not commited it and changed my SQL as follows:
 
SQL> l
  1  select b.sql_text
  2  from v$session a, v$sqlarea b
  3  where a.prev_sql_addr = b.address
  4* and a.sid = 101
SQL> /
 
SQL_TEXT
--------------------------------------------------
update andrew.emp set enum = 2 where enum = 1
 
SQL> 

Then I looked in the EMP table and saw that both Fred and Gordon were trying to update the same row:
 
SQL> select * from andrew.emp
  2  /
 
ENUM  ENAME
----- ----------
1     BRIAN
 
SQL>
 
I asked Fred to COMMIT his UPDATE statement:
 
SQL> update andrew.emp
  2  set enum = 2
  3  where enum = 1
  4  /
 
1 row updated.
 
SQL> commit
  2  /
 
Commit complete.
 
SQL>

This allowed Gordon’s UPDATE to finish:
 
SQL> conn gordon/bennett
Connected.
SQL> update andrew.emp
  2  set ename = 'COLIN'
  3  where ename = 'BRIAN'
  4  /
 
1 row updated.
 
SQL>

ORA-29339

$
0
0
I discovered a new error today. I was using Data Pump to copy a database from Sun SPARC to X86 and from Oracle 11.1.0.6.0 to 11.2.0.4.0 for testing purposes. I extracted the tablespace creation SQL from the old database like this. (This is only some of it.):
 
SQL> set lines 32000
SQL> set pages 50
SQL> exec dbms_metadata.set_transform_param(-
> DBMS_METADATA.SESSION_TRANSFORM,'SQLTERMINATOR',TRUE);
 
PL/SQL procedure successfully completed.
 
SQL> select dbms_metadata.get_ddl(-
> 'TABLESPACE','PINDAR_LARGE_32KBLOCKS')
  2  from dual
  3  /
 
DBMS_METADATA.GET_DDL('TABLESPACE','PINDAR_LARGE_32KBLOCKS')
--------------------------------------------------------------------------------
 
  CREATE TABLESPACE "PINDAR_LARGE_32KBLOCKS" DATAFILE
  '/cisdpt/nbadpt1/nba_data/pindar_large_32kblocks_a.dbf' SIZE 8388608000,
  '/cisdpt/nbadpt1/nba_data/pindar_large_32kblocks_b.dbf' SIZE 10485760000,
  '/cisdpt/nbadpt1/nba_data/pindar_large_32k_blocks_c.dbf' SIZE 15728640000
  LOGGING ONLINE PERMANENT BLOCKSIZE 32768
  EXTENT MANAGEMENT LOCAL UNIFORM SIZE 209715200 SEGMENT SPACE MANAGEMENT AUTO;
 
SQL>
 
I did a global replace to change part of the file name to bring it in line with the file system naming on the X86 server. Then I ran the SQL to create the tablespace in the new database but it failed:
 
SQL>   CREATE TABLESPACE "PINDAR_LARGE_32KBLOCKS" DATAFILE
  2    '/database/GBNBAPF1/nba_data/pindar_large_32kblocks_a.dbf' SIZE 8388608000,
  3    '/database/GBNBAPF1/nba_data/pindar_large_32kblocks_b.dbf' SIZE 10485760000,
  4    '/database/GBNBAPF1/nba_data/pindar_large_32k_blocks_c.dbf' SIZE 15728640000
  5    LOGGING ONLINE PERMANENT BLOCKSIZE 32768
  6    EXTENT MANAGEMENT LOCAL UNIFORM SIZE 209715200 SEGMENT SPACE MANAGEMENT AUTO;
  CREATE TABLESPACE "PINDAR_LARGE_32KBLOCKS" DATAFILE
*
ERROR at line 1:
ORA-29339: tablespace block size 32768 does not match configured block sizes
 
SQL>
 
The db_block_size was 8192 in both the old and new databases but the old one had the following extra line in its parameter file:
 
db_32k_cache_size=12m
 
This is to set up a cache for tablespaces with a 32K block size. I added this line to the parameter file for the new database and bounced it. Then I was able to create the tablespace there successfully:
 
SQL> CREATE TABLESPACE "PINDAR_LARGE_32KBLOCKS" DATAFILE
  2  '/database/GBNBAPF1/nba_data/pindar_large_32kblocks_a.dbf' SIZE 8388608000,
  3  '/database/GBNBAPF1/nba_data/pindar_large_32kblocks_b.dbf' SIZE 10485760000,
  4  '/database/GBNBAPF1/nba_data/pindar_large_32k_blocks_c.dbf' SIZE 15728640000
  5  LOGGING ONLINE PERMANENT BLOCKSIZE 32768
  6  EXTENT MANAGEMENT LOCAL UNIFORM SIZE 209715200 SEGMENT SPACE MANAGEMENT AUTO;
 
Tablespace created.
 
SQL>

PLSQL_OPTIMIZE_LEVEL

$
0
0
This parameter controls how much optimization Oracle does to PL/SQL code when it is compiled.
 
In Oracle 10, valid values were 0, 1 and 2:
 
Oracle 10: sqlplus / as sysdba
 
SQL*Plus: Release 10.2.0.3.0 - Production on Thu Apr 3 17:41:02 2014
 
Copyright (c) 1982, 2006, Oracle.  All Rights Reserved.
 
Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bit Production
With the Partitioning, OLAP and Data Mining options
 
SQL> alter session set plsql_optimize_level = 3
  2  /
ERROR:
ORA-00068: invalid value 3 for parameter plsql_optimize_level, must be between
0 and 2
 
SQL>
 
In Oracle 11, they were 0, 1, 2 and 3:
 
Oracle 11: sqlplus / as sysdba
 
SQL*Plus: Release 11.2.0.1.0 Production on Thu Apr 3 17:47:49 2014
 
Copyright (c) 1982, 2009, Oracle.  All rights reserved.
 
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
 
SQL> alter session set plsql_optimize_level = 4
  2  /
ERROR:
ORA-00068: invalid value 4 for parameter plsql_optimize_level, must be between
0 and 3
 
SQL>
 
You can see the effect of PLSQL_OPTIMIZE_LEVEL in the examples below, which I ran in an Oracle 11 database.

A procedure is compiled with three different values for this parameter. The code contains a loop, which is executed 10 million times. Inside the loop there is a statement, which assigns a value, which is never used. You could achieve the same effect by doing the assignment only once outside the loop. You could even omit the assignment altogether as the only information provided to the outside world by running the procedure is the amount of CPU time it has used.

As far as I understand, Oracle do not say how they will optimize your code, they simply say that they might alter and/or reorder the statements to achieve the same result in a different way.

With the parameter set to 0 i.e. no optimization, the procedure uses 8.1 seconds of CPU. Setting it to 1 reduces the time to 1.04 seconds. Finally, when it is set to 2, no CPU usage is recorded at all:
 
SQL> alter session set plsql_optimize_level = 0
  2  /
 
Session altered.
 
SQL> create or replace procedure counter is
  2  x number;
  3  t1 integer;
  4  t2 integer;
  5  t3 number;
  6  begin
  7    t1 := dbms_utility.get_cpu_time();
  8    for a in 1..10000000 loop
  9      x := 1 + 2 - 3 * 4 / 5;
 10    end loop;
 11    t2 := dbms_utility.get_cpu_time();
 12    t3 := (t2-t1)/100;
 13    dbms_output.put_line('CPU used = '||t3||' seconds');
 14  end;
 15  /
 
Procedure created.
 
SQL> exec counter;
CPU used = 8.1 seconds
 
PL/SQL procedure successfully completed.
 
SQL> alter session set plsql_optimize_level = 1
  2  /
 
Session altered.
 
SQL> create or replace procedure counter is
  2  x number;
  3  t1 integer;
  4  t2 integer;
  5  t3 number;
  6  begin
  7    t1 := dbms_utility.get_cpu_time();
  8    for a in 1..10000000 loop
  9      x := 1 + 2 - 3 * 4 / 5;
 10    end loop;
 11    t2 := dbms_utility.get_cpu_time();
 12    t3 := (t2-t1)/100;
 13    dbms_output.put_line('CPU used = '||t3||' seconds');
 14  end;
 15  /
 
Procedure created.
 
SQL> exec counter;
CPU used = 1.04 seconds
 
PL/SQL procedure successfully completed.
 
SQL> alter session set plsql_optimize_level = 2
  2  /
 
Session altered.
 
SQL> create or replace procedure counter is
  2  x number;
  3  t1 integer;
  4  t2 integer;
  5  t3 number;
  6  begin
  7    t1 := dbms_utility.get_cpu_time();
  8    for a in 1..10000000 loop
  9      x := 1 + 2 - 3 * 4 / 5;
 10    end loop;
 11    t2 := dbms_utility.get_cpu_time();
 12    t3 := (t2-t1)/100;
 13    dbms_output.put_line('CPU used = '||t3||' seconds');
 14  end;
 15  /
 
Procedure created.
 
SQL> exec counter;
CPU used = 0 seconds
 
PL/SQL procedure successfully completed.
 
SQL>

ORA-12985

$
0
0
If you try to drop a column from a table in a read only tablespace, you get an ORA-12985. If you really need to drop the column, you must put the tablespace back into read write mode first. You can see what I mean in the example below, which I tested in an Oracle 9 database:
 
SQL> create tablespace andrews_ts
  2  datafile '/tmp/andrew.dbf'
  3  size 1m
  4  /
 
Tablespace created.
 
SQL> grant dba to andrew identified by reid
  2  /
 
Grant succeeded.
 
SQL> alter user andrew default tablespace andrews_ts
  2  /
 
User altered.
 
SQL> conn andrew/reid
Connected.
SQL> create table tab1
  2  (col1 number, col2 number)
 3  /
 
Table created.
 
SQL> alter tablespace andrews_ts read only
  2  /
 
Tablespace altered.
 
SQL> alter table tab1 drop column col2
  2  /
alter table tab1 drop column col2
*
ERROR at line 1:
ORA-12985: tablespace 'ANDREWS_TS' is read only,
cannot drop column
 
SQL> alter tablespace andrews_ts read write
  2  /
 
Tablespace altered.
 
SQL> alter table tab1 drop column col2
  2  /
 
Table altered.
 
SQL> drop tablespace andrews_ts
  2  including contents and datafiles
  3  /
 
Tablespace dropped.
 
SQL>

enq: SQ – contention

$
0
0
This example shows how to deal with the enq: SQ – contention wait event. It was tested on Oracle 11.2. First I created a sequence and queried the amount of time already spent on this wait event:
 
SQL> create sequence seq1
  2  /
 
Sequence created.
 
SQL> select time_waited/100
  2  from v$system_event
  3  where event = 'enq: SQ - contention'
  4  /
 
no rows selected
 
SQL>
 
Then I created the following UNIX shell script to run test.sql 20 times simultaneously:
 
Oracle 11.2: cat test.ksh
#!/bin/ksh
export ORAENV_ASK=NO
export ORACLE_SID=ORCL
. oraenv
sqlplus / @test  0 &
sqlplus / @test  1 &
sqlplus / @test  2 &
sqlplus / @test  3 &
sqlplus / @test  4 &
sqlplus / @test  5 &
sqlplus / @test  6 &
sqlplus / @test  7 &
sqlplus / @test  8 &
sqlplus / @test  9 &
sqlplus / @test 10 &
sqlplus / @test 11 &
sqlplus / @test 12 &
sqlplus / @test 13 &
sqlplus / @test 14 &
sqlplus / @test 15 &
sqlplus / @test 16 &
sqlplus / @test 17 &
sqlplus / @test 18 &
sqlplus / @test 19 &
Oracle 11.2:
 
This is test.sql. It accepts a parameter and uses it to generate a SPOOL file name. Then it selects 10,000 values from the sequence created earlier:
 
Oracle 11.2: cat test.sql
spool test&&1
set echo on
declare
num1 number;
begin
 for a in 1..10000 loop
  select seq1.nextval into num1 from dual;
 end loop;
end;
/
exit
spool off
Oracle 11.2:
 
I ran test.ksh and waited until all the SPOOL files had been created: 

Oracle 11.2: ls -ltr
total 36
-rwxr--r--   1 oracle   dba          487 Apr 11 13:48 test.ksh
-rw-r--r--   1 oracle   dba          147 Apr 11 13:55 end_test1.sql
-rw-r--r--   1 oracle   dba          147 Apr 11 13:56 end_test2.sql
-rw-r--r--   1 oracle   dba          150 Apr 11 13:56 start_test1.sql
-rw-r--r--   1 oracle   dba          161 Apr 11 13:56 start_test2.sql
-rwxr--r--   1 oracle   dba          154 Apr 11 13:57 test.sql
-rw-r--r--   1 oracle   dba          184 Apr 11 14:43 start_test1.lst
-rw-r--r--   1 oracle   dba          206 Apr 11 16:12 test16.lst
-rw-r--r--   1 oracle   dba          206 Apr 11 16:12 test1.lst
-rw-r--r--   1 oracle   dba          206 Apr 11 16:12 test4.lst
-rw-r--r--   1 oracle   dba          206 Apr 11 16:12 test6.lst
-rw-r--r--   1 oracle   dba          206 Apr 11 16:12 test12.lst
-rw-r--r--   1 oracle   dba          206 Apr 11 16:12 test9.lst
-rw-r--r--   1 oracle   dba          206 Apr 11 16:12 test13.lst
-rw-r--r--   1 oracle   dba          206 Apr 11 16:12 test19.lst
-rw-r--r--   1 oracle   dba          206 Apr 11 16:12 test3.lst
-rw-r--r--   1 oracle   dba          206 Apr 11 16:12 test2.lst
-rw-r--r--   1 oracle   dba          206 Apr 11 16:12 test15.lst
-rw-r--r--   1 oracle   dba          206 Apr 11 16:12 test17.lst
-rw-r--r--   1 oracle   dba          206 Apr 11 16:12 test11.lst
-rw-r--r--   1 oracle   dba          206 Apr 11 16:12 test0.lst
-rw-r--r--   1 oracle   dba          206 Apr 11 16:12 test10.lst
-rw-r--r--   1 oracle   dba          206 Apr 11 16:12 test14.lst
-rw-r--r--   1 oracle   dba          206 Apr 11 16:12 test5.lst
-rw-r--r--   1 oracle   dba          206 Apr 11 16:12 test8.lst
-rw-r--r--   1 oracle   dba          206 Apr 11 16:12 test7.lst
-rw-r--r--   1 oracle   dba          206 Apr 11 16:12 test18.lst
Oracle 11.2: 

Then I looked in one of them to see that it had worked OK:

Oracle 11.2: cat test18.lst
SQL> declare
  2   num1 number;
  3  begin
  4   for a in 1..10000 loop
  5    select seq1.nextval into num1 from dual;
  6   end loop;
  7  end;
  8  /
 
PL/SQL procedure successfully completed.
 
SQL> exit
Oracle 11.2:
 
I rechecked the amount of time spent on the wait event. This is the time Oracle spends waiting for the next value to come back from the sequence. It had gone from zero to 436.8 seconds as 20 sessions had been requesting values at the same time:
 
SQL> select time_waited/100
  2  from v$system_event
  3  where event = 'enq: SQ - contention'
  4  /
 
TIME_WAITED/100
---------------
          436.8
 
SQL> drop sequence seq1
  2  /
 
Sequence dropped.
 
SQL>
 
I recreated the sequence but this time I told Oracle to cache 10,000 values in memory:
 
SQL> create sequence seq1 cache 10000
  2  /
 
Sequence created.
 
SQL> select time_waited/100
  2  from v$system_event
  3  where event = 'enq: SQ - contention'
  4  /
 
TIME_WAITED/100
---------------
          436.8
 
SQL>
 
I reran test.ksh then rechecked the time spent on the wait event. This time it had increased by less than 20 seconds:
 
SQL> select time_waited/100
  2  from v$system_event
  3  where event = 'enq: SQ - contention'
  4  /
 
TIME_WAITED/100
---------------
         455.15
 
SQL> drop sequence seq1
  2  /
 
Sequence dropped.
 
SQL>
 
I recreated the sequence but this time I told Oracle to cache 200,000 values in memory:
 
SQL> create sequence seq1 cache 200000
  2  /
 
Sequence created.
 
SQL> select time_waited/100
  2  from v$system_event
  3  where event = 'enq: SQ - contention'
  4  /
 
TIME_WAITED/100
---------------
         455.15
 
SQL>
 
I reran test.ksh then rechecked the time spent on the wait event. This time it had not increased at all:
 
SQL> select time_waited/100
  2  from v$system_event
  3  where event = 'enq: SQ - contention'
  4  /
 
TIME_WAITED/100
---------------
         455.15
 
SQL> drop sequence seq1
  2  /
 
Sequence dropped.
 
SQL>

So, when you create a sequence, if you set the cache value appropriately, you can reduce the time spent on this wait event or maybe even eliminate it altogether.

ORA-12899

$
0
0
This was tested on Oracle 11.2. If you try to update a column with a value which is too long, you will get an ORA-12899:
 
SQL> conn andrew/reid
Connected.
SQL> create table tab1 (first_name varchar2(10))
  2  /
 
Table created.
 
SQL> insert into tab1 values ('Christopher')
  2  /
insert into tab1 values ('Christopher')
                         *
ERROR at line 1:
ORA-12899: value too large for column
"ANDREW"."TAB1"."FIRST_NAME" (actual: 11, maximum: 10)
 
SQL>
 
If this happens, you can either use a shorter value:
 
SQL> insert into tab1 values ('Colin')
  2  /
 
1 row created.
 
SQL>
 
…or make the column longer:
 
SQL> alter table tab1 modify first_name varchar2(15)
 2  /
 
Table altered.
 
SQL> insert into tab1 values ('Christopher')
  2  /
 
1 row created.
 
SQL>

How to Rename a Table

$
0
0
I tested this example in Oracle 12.1. First I created a table:

SQL> create table fred
  2  as select * from user_synonyms
  3  where 1 = 2
  4  /
 
Table created.

SQL>

Then I checked its object_id for later:

SQL> select object_id
  2  from user_objects
  3  where object_name = 'FRED'
  4  /
 
OBJECT_ID
----------
     92212

SQL>

... and described it:

SQL> desc fred
Name                       Null?    Type
-------------------------- -------- ------------------
SYNONYM_NAME               NOT NULL VARCHAR2(128)
TABLE_OWNER                         VARCHAR2(128)
TABLE_NAME                 NOT NULL VARCHAR2(128)
DB_LINK                             VARCHAR2(128)
ORIGIN_CON_ID                       NUMBER

SQL>

Then I changed its name:

SQL> rename fred to joe
  2  /
 
Table renamed.

SQL>

... and finally, to prove I was still looking at the same object, I used the new name to look up the object_id and description and confirmed that they had not changed:

SQL> select object_id
  2  from user_objects
  3  where object_name = 'JOE'
  4  /
 
OBJECT_ID
----------
     92212
 
SQL> desc joe
Name                       Null?    Type
-------------------------- -------- ------------------
SYNONYM_NAME               NOT NULL VARCHAR2(128)
TABLE_OWNER                         VARCHAR2(128)
TABLE_NAME                 NOT NULL VARCHAR2(128)
DB_LINK                             VARCHAR2(128)
ORIGIN_CON_ID                       NUMBER
 
Viewing all 330 articles
Browse latest View live