You are on page 1of 54

What’s new in Oracle10g that is of interest to a DBA?

Simplified Oracle10g installation

Enhanced Enterprise Manager

Introducing DataPump - The load/unload utility

Automatic Database Diagnostic Monitor

Automatic Shared Memory Management

Automatic Optimizer Statistics Gathering

Automatic Undo Tuning

Automatic Workload Repository

Automatic Storage Management

Automatic Maintenance Tasks

SQL Tuning Advisor

SQL Access Advisor

Undo Advisor

Redo Logfile Size Advisor

Bigfile Tablespaces

New Flashback Features

The SYSAUX Tablespace

Direct Upgrade to 10g

UNIX Style Regular Expressions in SQL

HTML DB

New (bunch of) Wait Events

New Initialization Parameters


Rename Tablespace

Flush buffer cache

Temporary Tablespace Groups

Default Permanent Tablespace

Segment Shrink

Skip Unusable Indexes

Drop Database

Server Alerts

Transport tablespace across platforms


What’s new in Oracle9i that is of interest to a DBA?

******* Automatic undo management


What is automatic undo?

Oracle manages undo space using the undo tablespace instead of rollback segments
Oracle manages the size and number of undo segments
Relieves DBA from creating and monitoring rollback segments
New type of tablespace required – UNDO TABLESPACE
New initialization parameters
UNDO_MANAGEMENT - Decides the type of undo management.
AUTO specifies automatic undo management
MANUAL specifies pre-9i behavior where the DBA manages rollback segments.
This is the default
UNDO_TABLESPACE – Name of the undo tablespace, this is a dynamic parameter,
so you can change the name of the undo tablespace. You may have multiple undo
tablespaces on the database, only one can be active at any given time. If you do not
specify this parameter, oracle uses the first available undo tablespace.
UNDO_RETENTION - specifies (in seconds) the amount of committed undo
information to retain in the database. The default is 900 seconds. Keep this value
high to avoid “Snapshot too old” errors. This is also a dynamic parameter, which can
be changed using ALTER SYSTEM.
UNDO_SUPPRESS_ERRORS - Suppress errors while executing manual undo
management mode operations. If your application has SET TRANSACTION USE
ROLLBACK SEGMENT statement, setting this parameter value to TRUE will
suppress the error while in automatic undo.

How to create an undo tablespace?

Specify while creating the 9i database:


CREATE DATABASE … …
DATAFILE … …
UNDO TABLESPACE "UNDOTBS"
DATAFILE '/oradata/MYDB/undotbs01.dbf' SIZE 100M
CHARACTER SET … … …
Create using the CREATE TABLESPACE syntax:
CREATE UNDO TABLESPACE UNDOTBS
DATAFILE '/oradata/MYDB/undotbs01.dbf' SIZE 100M
You can specify only DATAFILE and EXTENT MANAGEMENT LOCAL clauses
when creating the UNDO TABLESPACE.

I just upgraded my database to 9i, how do I enable automatic undo management?


Create an undo tablespace
Include the UNDO_ parameters in your pfile or spfile. If using spfile, make sure you
specify SCOPE=SPFILE
Remove the rollback_segments parameter, if present in the init file. This will prevent
the rollback segments going online when the database is started.
Shutdown the database – make sure NOT to do SHUTDOWN ABORT.
Startup the database.
Drop the rollback segments and the rollback tablespace, if empty.

******* Automatic Segment Space Management


Automatic Segment Space Management (ASSM) introduced in Oracle9i is an easier way
of managing space in a segment using bitmaps. It eliminates the DBA from setting the
parameters pctused, freelists, and freelist groups.

ASSM can be specified only with the locally managed tablespaces (LMT). The CREATE
TABLESPACE statement has a new clause SEGMENT SPACE MANAGEMENT.
Oracle uses bitmaps to manage the free space. A bitmap, in this case, is a map that
describes the status of each data block within a segment with respect to the amount of
space in the block available for inserting rows. As more or less space becomes available
in a data block, its new state is reflected in the bitmap. Bitmaps allow Oracle to manage
free space more automatically.

Here is an example:

CREATE TABLESPACE myts


DATAFILE '/oradata/mysid/myts01.dbf' SIZE 100M
EXTENT MANAGEMENT LOCAL UNIFORM SIZE 2M
SEGMENT SPACE MANAGEMENT AUTO;

The storage parameters PCTUSED, FREELISTS and FREELIST GROUPS specified


while creating a table are ignored by Oracle on a LMT ASSM tablespace. Oracle does not
produce an error.

One huge benefit of having ASSM is to reduce the “Buffer Busy Waits” you see on
segments.

Peter Sherman’s presentation at RMOUG is a good one.

******* Rename Column


Oracle databases Oracle9i Release 2 and higher now allow you to rename a column in
the table.

ALTER TABLE table_name RENAME COLUMN old_name TO new_name

Use the RENAME COLUMN clause of ALTER TABLE to rename a column. The
new column name must not be the same as any other column name in
table.

Function-based indexes and check constraints that depend on the renamed column remain
valid.

Dependent views, triggers, domain indexes, functions, procedures, and packages are
marked INVALID. Oracle attempts to revalidate them when they are next accessed, but
you may need to alter these objects with the new column name if revalidation fails.

You cannot combine this clause with any of the other column_clauses in the same
statement.

You cannot rename a column that is used to define a join index.


Instead you must drop the index, rename the column, and re-create
the index

******* Rename Constraints


Oracle9i Release 2 lets you rename the constraint names. Here is a demonstration:

SQL> create table b_test (col1 number, col2 number,


2* constraint pk_b_test primary key (col1))
SQL> /
 
Table created.
 
SQL> select constraint_name from dba_constraints
2 where table_name = 'B_TEST';
 
CONSTRAINT_NAME
------------------------------
PK_B_TEST
 
1 row selected.
 
SQL> select index_name from dba_indexes
2 where table_name = 'B_TEST';
 
INDEX_NAME
------------------------------
PK_B_TEST
 
1 row selected.
 
SQL> alter index PK_B_TEST rename to B_TEST_PK;
 
Index altered.
 
SQL> select constraint_name from dba_constraints
2 where table_name = 'B_TEST';
 
CONSTRAINT_NAME
------------------------------
PK_B_TEST
 
1 row selected.
 
SQL> alter table b_test rename constraint PK_B_TEST to
B_TEST_PK;
 
Table altered.
 
SQL> select constraint_name from dba_constraints
2 where table_name = 'B_TEST';
 
CONSTRAINT_NAME
------------------------------
B_TEST_PK
 
1 row selected.
 
SQL>

What if you try to do the same in an Oracle8i database?

SQL> create table b_test (col1 number, col2 number,


2 constraint pk_b_test primary key (col1))
3 /
 
Table created.
 
SQL> select constraint_name from dba_constraints
2 where table_name = 'B_TEST';
 
CONSTRAINT_NAME
------------------------------
PK_B_TEST
 
1 row selected.
 
SQL> select index_name from dba_indexes
2 where table_name = 'B_TEST';
 
INDEX_NAME
------------------------------
PK_B_TEST
 
1 row selected.
 
SQL> alter index PK_B_TEST rename to B_TEST_PK;
 
Index altered.
 
SQL> select constraint_name from dba_constraints
2 where table_name = 'B_TEST';
 
CONSTRAINT_NAME
------------------------------
PK_B_TEST
 
1 row selected.
 
SQL> alter table b_test rename constraint PK_B_TEST to
B_TEST_PK;
alter table b_test rename constraint PK_B_TEST to B_TEST_PK
*
ERROR at line 1:
ORA-14155: missing PARTITION or SUBPARTITION keyword
 
 

************ Data Compression


Block level compression is a new feature in Oracle9i Release 2, which is very useful in
many data warehouses and read only large tables. Table compression can reduce storage
space requirement (drastically some times) and may make the queries run faster (need to
read only fewer blocks of data).

You may enable compression on a table at the time of table creation or by altering the
table. Remember the existing data in the table is not compressed on uncompressed when
you do the “alter”.
CREATE TABLE MYTABLE (
COL1 VARCHAR2 (20),
COL2 DATE)
TABLESPACE MYTABLESPACE
NOLOGGING
COMPRESS
PCTFREE 0;

ALTER TABLE MYTABLE COMPRESS;

The data compression is transparent to the user. You run queries against the table the
same way you use to do before. Oracle compresses data blocks only when the data is
loaded in direct path. The statements could be

INSERT with APPEND hint


INSERT with PARALLEL hint (parallel DML)
CREATE TABLE AS
SQL*Loader DIRECT LOAD

Rows loaded using conventional insert statements are not compressed.

Compression is suitable for large tables, where the updates/deletes are close to none. If
there are updates/deletes, you may end up using more space – to update, Oracle has to
uncompress the row, and insert it again; row deleted will free up some space which may
not be sufficient for the next inserted row, because conventional inserts are not
compressed, direct load inserts always load above the HWM.

You can either compress the table, or selectively on partitions. It may be a good idea to
compress the older data on a partitioned table. To do this, you have to perform a

ALTER TABLE MYPARTTABLE MOVE PARTITION JAN04 TABLESPACE


COMP_DATA COMPRESS PCTFREE 0;

After the partition move, you may also have to do:

ALTER TABLE MYPARTTABLE 


MODIFY PARTITION JAN04 REBUILD UNUSABLE LOCAL INDEXES;

Another place to use compression is when you create materialized views, because most of
the MVs are read only. If the MV already exist, you may do

ALTER MATERIALIZED VIEW MYMV COMPRESS;

The data will be compressed when the materialized view is refreshed.

Restrictions:
You cannot specify data segment compression for an index-
organized table, for any overflow segment or partition of an overflow
segment, or for any mapping table segment of an index-organized
table.
You cannot specify data segment compression for hash partitions or
for either hash or list sub-partitions.
You cannot specify data segment compression for an external table.

The dictionary views DBA_TABLES, DBA_TAB_PARTITIONS have a column named


COMPRESSION, which will be either DISABLED or ENABLED.

******** Index Key Compression


Index key compression introduced in Oracle9i lets you compress the leading columns of
an index (or index organized table) to save space. Oracle compresses only non-
partitioned indexes that are non-unique or unique indexes of at least two columns. Bitmap
indexes cannot be compressed.

Generally, keys in an index have two pieces, a grouping piece and a unique piece. If the
key is not defined to have a unique piece, Oracle provides one in the form of a rowid
appended to the grouping piece. Key compression is a method of breaking off the
grouping piece and storing it so it can be shared by multiple unique pieces.

Key compression is achieved by breaking the index entry into two pieces – a prefix entry
(or the grouping piece) and the suffix entry (the unique piece). Key compression is done
within an index block but not across multiple index blocks. Suffix entries form the
compressed version of index rows. Each suffix entry references a prefix entry, which is
stored in the same index block as the suffix entry.

Although key compression reduces the storage requirements of an index, it can increase
the CPU time required to reconstruct the key column values during an index scan. It also
incurs some additional storage overhead, because every prefix entry has an overhead of 4
bytes associated with it.

Example creating a compressed index-organized table:

CREATE TABLE BIJU_TEST_C


(OWNER VARCHAR2(30),
TABLE_NAME VARCHAR2(30),
TABLESPACE_NAME VARCHAR2 (30),
PRIMARY KEY (OWNER, TABLE_NAME))
ORGANIZATION INDEX
COMPRESS;
 Example creating a compressed index:

CREATE INDEX BIJU_IND1


ON BIJU_TAB1 (COUNTRY, STATE, SEX)
TABLESPACE INDX_TS
COMPRESS;

You can specify an integer along with the COMPRESS clause, which specifies the
number of prefix columns to compress. For unique indexes, the valid range of prefix
length values is from 1 to the number of key columns minus 1. The default is the number
of key columns minus 1. For non-unique indexes, the valid range is from 1 to the number
of key columns. The default is the number of key columns.

******** Flashback Query


Flashback query is a new feature in Oracle9i to recover from human errors. It allows
users to view the state of data at a point in time in the past without requiring any
structural changes to the database. Using Flashback Query, you can execute queries
against a snapshot of data consistent to a point in time in the past either by specifying a
system clock time or a System Change Number (SCN).

Since flashback query is done using the “AS OF” clause of the SELECT statement, the
developers/users do not need any administrative privileges or DBA intervention. While
you query the old data, the table with current data is available for other users.

The flashback clause of the SELECT statement has the following syntax:

AS OF {SCN | TIMESTAMP} expr

Let’s demonstrate the flashback-query using example. Notice that the COMMIT is what
completes a transaction.

11:16:47 SQL> select object_name, object_type


11:16:57 2 from test
11:17:01 3 where owner = 'OUTLN';
 
OBJECT_NAME OBJECT_TYPE
------------------------- ------------------
OL$ TABLE
OL$HINTS TABLE
OL$HNT_NUM INDEX
OL$NAME INDEX
OL$NODES TABLE
OL$SIGNATURE INDEX
ORA$GRANT_SYS_SELECT PROCEDURE
 
7 rows selected.
 
11:17:08 SQL>
11:17:14 SQL> update test
11:17:22 2 set object_type = 'INVALID'
11:17:53 3 where object_name = 'ORA$GRANT_SYS_SELECT';
 
1 row updated.
 
12:32:12 SQL> delete from test
12:32:18 2 where object_name = 'OL$NODES';
 
1 row deleted.
 
12:32:51 SQL> update test
12:32:58 2 set object_type = 'VALID'
12:33:07 3 where object_name = 'ORA$GRANT_SYS_SELECT';
 
1 row updated.
 
12:33:20 SQL>commit;
 
Commit complete.
 
12:33:23 SQL>
12:37:56 SQL>
12:37:57 SQL> select object_name, object_type
12:38:03 2 from test
12:38:03 3 where owner = 'OUTLN';
 
OBJECT_NAME OBJECT_TYPE
------------------------- ------------------
OL$ TABLE
OL$HINTS TABLE
OL$HNT_NUM INDEX
OL$NAME INDEX
OL$SIGNATURE INDEX
ORA$GRANT_SYS_SELECT VALID
 
6 rows selected.
 
12:38:04 SQL>
12:40:53 SQL> select object_name, object_type
12:41:02 2  from test AS OF TIMESTAMP                              
TO_TIMESTAMP('20040226123251','YYYYMMDDHHMISS')
12:42:39 3 where owner = 'OUTLN';
 
OBJECT_NAME OBJECT_TYPE
------------------------- ------------------
OL$ TABLE
OL$HINTS TABLE
OL$HNT_NUM INDEX
OL$NAME INDEX
OL$NODES TABLE
OL$SIGNATURE INDEX
ORA$GRANT_SYS_SELECT PROCEDURE
 
7 rows selected.
 
12:42:44 SQL>
12:43:15 SQL> select object_name, object_type
2 from test AS OF TIMESTAMP
TO_TIMESTAMP('20040226123319','YYYYMMDDHHMISS')
3 where owner = 'OUTLN'
12:43:51 SQL>/
 
OBJECT_NAME OBJECT_TYPE
------------------------- ------------------
OL$ TABLE
OL$HINTS TABLE
OL$HNT_NUM INDEX
OL$NAME INDEX
OL$NODES TABLE
OL$SIGNATURE INDEX
ORA$GRANT_SYS_SELECT PROCEDURE
 
7 rows selected.
 
12:43:51 SQL>

By writing proper sub queries and update statements you can recover the rows.

******** Object Privileges by DBA


Finally Oracle realized that DBA should have the privilege to grant object privileges.
From Oracle9i Release 2 onwards, you need not login as the owner of the object to grant
an object privilege. In the earlier releases since most of the time I do not remember the
schema password, had to login as the schema using the "back door"!

A new system privilege, "GRANT ANY OBJECT PRIVILEGE" is introduced to control


the delegation of an owner's right to grant and revoke object privileges.
In pre-Oracle9iR2 databases, to grant an object privilege on an object that belonged to
another user, you should have granted the privilege with the GRANT option.

GRANT ANY PRIVILEGE still gives the grantee privilege to grant any system privilege.

******** Default Temporary Tablespace


Oracle9i introduced a new clause in the CREATE DATABASE and ALTER
DATABASE statements to assign a default temporary tablespace for the database. When
creating users, if you do not provide the TEMPORARY TABLESPACE clause, Oracle
uses this tablespace as the users temporary tablespace. (The default for DEFAULT
TABLESPACE for the user is still SYSTEM J).

When you ALTER the DEFAULT TEMPORARY TABLESPACE for the database,
Oracle reassigns the temporary tablespace of the users with the default assignment to the
new tablespace. Here is an example:

SQL> select property_value from database_properties


2 where PROPERTY_NAME = 'DEFAULT_TEMP_TABLESPACE';
 
PROPERTY_VALUE
-----------------------------------
SYSTEM
 
1 row selected.
 
SQL> create user test_biju identified by test;
 
User created.
 
SQL> select default_tablespace, temporary_tablespace
2 from dba_users where username = 'TEST_BIJU';
 
DEFAULT_TABLESPACE TEMPORARY_TABLESPACE
------------------------------ ------------------------------
SYSTEM SYSTEM
 
1 row selected.
 
SQL> alter database default temporary tablespace temp;
 
Database altered.
 
SQL> select default_tablespace, temporary_tablespace
2 from dba_users where username = 'TEST_BIJU';
 
DEFAULT_TABLESPACE TEMPORARY_TABLESPACE
------------------------------ ------------------------------
SYSTEM TEMP
 
1 row selected.
 
SQL>

A default temporary tablespace cannot be taken offline until a new default temporary
tablespace is online

Here is something interesting from the Oracle documentation:

If you specify the EXTENT MANAGEMENT LOCAL clause for the SYSTEM
tablespace when creating a database, the database must have a default temporary
tablespace, because a locally managed SYSTEM tablespace cannot store temporary
segments.

If you specify EXTENT MANAGEMENT LOCAL but you do not specify the
DATAFILE clause, you can omit the default_temp_tablespace clause. Oracle will
create a default temporary tablespace called TEMP with one datafile of
size 10M with autoextend disabled.
If you specify both EXTENT MANAGEMENT LOCAL and the DATAFILE clause,
then you must also specify the default_temp_tablespace clause and explicitly
specify a datafile for that tablespace.

******** Resumable Space Allocation


Do you often have issues with batch jobs running out of space producing unable to
extent errors in the database? Now Oracle can suspend the session in error until you add
more space and resume the session from where it left….

Resumable space allocation solution can be used for the following errors:

         ORA-1650 unable to extend rollback segment ... in


tablespace ...
         ORA-1653 unable to extend table ... in tablespace ...
         ORA-1654 unable to extend index ... in tablespace ...
         ORA-1628 max # extents ... reached for rollback segment ...
         ORA-1631 max # extents ... reached in table ...
         ORA-1654 max # extents ... reached in index ...
         ORA-1536 space quote exceeded for tablespace string

The session need to enable the resumable mode using:

ALTER SESSION ENABLE RESUMABLE;


The following views can be queried to obtain information about the status of resumable
statements:

View Description
DBA_RESUMABLE These views contain rows for all currently executing or suspended
USER_RESUMABLE
resumable statements. They can be used by a DBA, AFTER SUSPEND
trigger, or another session to monitor the progress of, or obtain
specific information about, resumable statements.
V$SESSION_WAIT When a statement is suspended the session invoking the statement is
put into a wait state. A row is inserted into this view for the session
with the EVENT column containing "statement suspended, wait error to
be cleared".

To read more:

OTN – 9i Daily Feature – November 26

Oracle Documentation – Administrators Guide – Chapter 14

******** List Partitioning


Oracle9i introduces another type of partitioning in addition to the RANGE and HASH
partitions of 8i. List partitioning lets you create partitions based on a list of values. For
example, if you have a sales table, and you want to partition the table by the region, you
might create the table as:

create table list_example (


state char(2),
amount number)
partition by list (state)
(
partition south values ('TX','LA','OK'),
partition north values ('NY','DE','MA'),
partition others values (DEFAULT)
)
/

If you omit the partition name, then Oracle assigns partition names of the form SYS_Pn.

The DEFAULT keyword, introduced in Oracle9i release 2, creates a partition into which
Oracle will insert any row that does not map to another partition. Therefore, you can
specify DEFAULT for only one partition, and you cannot specify any other values for that
partition. Further, the default partition must be the last partition you define (similar to the
use of MAXVALUE for range partitions).

The index-organized table cannot be list-partitioned.

******** Range-list Partitioning


Prior to Oracle9i, the only sub-partitioning method available was to partition the table by
range, and sub-partition by hash. Oracle9i release 2 allows you to partition the table by
range and then sub-partition by list. These are the only sub-partitioning methods in
Oracle9i.

The following are the versions and partitioning methods available, just to refresh your
memory: <![endif]>

Oracle8 Oracle8i Oracle9iR1 Oracle9iR2


Range Range Range Range
Hash Hash Hash
Range-Hash List List
Range-Hash Range-Hash
Range-List

Here is an example of creating a range-list partitioned table:

create table range_list_example (


sales_dt date,
state char(2),
amount number)
partition by range (sales_dt)
subpartition by list (state)
(
partition s2004q1
values less than (to_date('04-2004','MM-YYYY'))
(subpartition s2004q1_south values ('TX','LA','OK'),
subpartition s2004q1_north values ('NY','DE','MA'),
subpartition s2004q1_others values (DEFAULT)),
partition s2004q2
values less than (to_date('07-2004','MM-YYYY'))
(subpartition s2004q2_south values ('TX','LA','OK'),
subpartition s2004q2_north values ('NY','DE','MA'),
subpartition s2004q2_others values (DEFAULT))
)
/
The same sub-partitions can be created using a sub-partition template as in the following
example:

create table range_list_example (


sales_dt date,
state char(2),
amount number)
partition by range (sales_dt)
subpartition by list (state)
subpartition template
(subpartition south values ('TX','LA','OK'),
subpartition north values ('NY','DE','MA'),
subpartition others values (DEFAULT))
(
partition s2004q1
values less than (to_date('04-2004','MM-YYYY')),
partition s2004q2
values less than (to_date('07-2004','MM-YYYY'))
)
/

******** External Tables


External Table introduced in Oracle9i is and excellent feature for ETL operations,
allows for flat files that reside outside the database, to be accessed just like relational
tables within the database. The flat-file data can be queried and joined to other tables
using standard SQL. From a user’s point of view, the main difference between an
external table and a regular table is that the external table is read-only. The metadata is
stored in the Oracle database, where as the actual data resides outside the database.

You create the external table using the ORAGANIZATION EXTERNAL clause of the
CREATE TABLE.

To create an external table, you must create a DIRECTORY in Oracle and have the READ
object privilege on the directory in which the external data resides. Also, no constraints
are permitted on external tables.

CREATE DIRECTORY "UNIX_FLATFILE" AS '/FileImport/Externall';


 
GRANT READ ON DIRECTORY "UNIX_FLATFILE" TO "MYUSER";
 
CREATE TABLE MYUSER.TEST_EXT_TAB
(
ASS_ID NUMBER,
TID_ID NUMBER,
ASS_DATE VARCHAR2(10 BYTE),
MCFD VARCHAR2(5 BYTE),
HRS VARCHAR2(5 BYTE),
PRES VARCHAR2(6 BYTE),
PIPELINE VARCHAR2(30 BYTE),
DAILY_DATE VARCHAR2(18 BYTE)
)
ORGANIZATION EXTERNAL
( TYPE ORACLE_LOADER
DEFAULT DIRECTORY UNIX_FLATFILE
ACCESS PARAMETERS
( RECORDS DELIMITED BY NEWLINE
CHARACTERSET WE8MSWIN1252
STRING SIZES ARE IN BYTES
BADFILE ‘mydata.bad’
NODISCARDFILE
NOLOGFILE
SKIP 1
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '"' AND '"'
NOTRIM
)
LOCATION (UNIX_FLATFILE:'mydata.csv')
)
REJECT LIMIT UNLIMITED;

External tables can be used to load data to a database, where you have to do some data
manipulation. This avoids couple of steps in the conventional method, where you would
load the data to a temporary table and then load the destination tables using queries.

Oracle9i's external tables are a complement to the existing SQL*Loader functionality,


and are especially useful for environments where the complete external source has to be
joined with existing database objects and transformed in a complex manner, or where the
external data volume is large and used only once. SQL*Loader, on the other hand, might
still be the better choice for loading of data where additional indexing of the staging table
is necessary. This is true for operations where the data is used in independent complex
transformations or the data is only partially used in further processing.

Dictionary Views that show external table information:

SQL >desc dba_external_tables


Name Null? Type
------------------------------- -------- ------------
OWNER NOT NULL VARCHAR2(30)
TABLE_NAME NOT NULL VARCHAR2(30)
TYPE_OWNER CHAR(3)
TYPE_NAME NOT NULL VARCHAR2(30)
DEFAULT_DIRECTORY_OWNER CHAR(3)
DEFAULT_DIRECTORY_NAME NOT NULL VARCHAR2(30)
REJECT_LIMIT VARCHAR2(40)
ACCESS_TYPE VARCHAR2(7)
ACCESS_PARAMETERS VARCHAR2(4000)
 
SQL >
SQL >desc dba_external_locations
Name Null? Type
------------------------------- -------- ----------------
OWNER NOT NULL VARCHAR2(30)
TABLE_NAME NOT NULL VARCHAR2(30)
LOCATION VARCHAR2(4000)
DIRECTORY_OWNER CHAR(3)
DIRECTORY_NAME VARCHAR2(30)
 
SQL >

******** Tuning Advisories


To help DBA tune the database, Oracle9i Release 2 introduces the following tuning
advisories:

Dynamic Buffer Cache Advisory


MTTR Advisory
Shared Pool Advisory
PGA Target Advisory

The advisories are turned on based on the value of initialization parameter


STATISTICS_LEVEL. It could have values BASIC, TYPICAL or ALL. The parameter
is dynamic – can be changed using ALTER SYSTEM or ALTER SESSION. The default
value is TYPICAL. BASIC does not collect any statistics or advisories. Dictionary view
V$STATISTICS_LEVEL gives the various statistics collection and advisories turned on
in the database and their explanation. Here is one from a database:

Statistics name Description


Buffer Cache Advice Predicts the impact of different cache sizes on number of physical reads
MTTR Advice Predicts the impact of different MTTR settings on number of physical I/Os
Predicts the impact of different values of pga_aggregate_target on the performance of memory
PGA Advice operators
Plan Execution
Statistics Enables collection of plan execution statistics
Segment Level
Statistics Enables gathering of segment access statistics
Shared Pool Advice Predicts the impact of different values of shared_pool_size on elapsed parse time saved
Timed OS Statistics Enables gathering of timed operating system statistics
Timed Statistics Enables gathering of timed statistics
The above table pretty much explains what you get with the advisories and which views
to look for results.

******** Dynamic Sampling of Optimizer Statistics

Dynamic sampling introduced in


Oracle9i Release 2 improves
server performance by
determining more accurate
selectivity and cardinality
estimates for queries.

You can use dynamic sampling


to:

Estimate single-table
predicate selectivities
when collected statistics
cannot be used or are
likely to lead to
significant errors in
estimation.
Estimate table
cardinality for tables
without statistics or for
tables whose statistics
are too out of date to
trust.

Dynamic sampling is controlled


by the initialization parameter
OPTIMIZER_DYNAMIC_SAMPLING.
It could have a value
between 0 and 10.

A value of 0 means
dynamic sampling will
not be done.
A value of 1 (the default)
means dynamic
sampling will be
performed if all of the
following conditions are
true:
There is more than one
table in the query.
Some table has not been
analyzed and has no
indexes.
The optimizer
determines that a
relatively expensive
table scan would be
required for this
unanalyzed table.
Increasing the value of the parameter
results in more aggressive application of
dynamic sampling, in terms of both the type
of tables sampled (analyzed or unanalyzed)
and the amount of I/O spent on sampling.
 

******** Dynamic Database Parameters


Oracle9i includes several database initialization parameters that can be changed
dynamically using ALTER SYSTEM or ALTER SESSION. The following are the
parameters that were not modifiable in 8i, which can be modified in 9i using ALTER
SYSTEM.

SHARED_POOL_SIZE
LARGE_POOL_SIZE
LOG_CHECKPOINTS_TO_ALERT
SERVICE_NAMES
LOCAL_LISTENER
OPEN_CURSORS

The following are the new parameters introduced in Oracle9i that are dynamic.

NAME DESCRIPTION
archive_lag_target Maximum number of seconds of redos the standby could lose
db_16k_cache_size Size of cache for 16K buffers
db_2k_cache_size Size of cache for 2K buffers
db_32k_cache_size Size of cache for 32K buffers
db_4k_cache_size Size of cache for 4K buffers
db_8k_cache_size Size of cache for 8K buffers
db_cache_advice Buffer cache sizing advisory
db_cache_size Size of DEFAULT buffer pool for standard block size buffers
db_create_file_dest default database location
db_create_online_log_dest_1 online log/controlfile destination #1
db_create_online_log_dest_2 online log/controlfile destination #2
db_create_online_log_dest_3 online log/controlfile destination #3
db_create_online_log_dest_4 online log/controlfile destination #4
db_create_online_log_dest_5 online log/controlfile destination #5
db_keep_cache_size Size of KEEP buffer pool for standard block size buffers
db_recycle_cache_size Size of RECYCLE buffer pool for standard block size buffers
dg_broker_config_file1 data guard broker configuration file #1
dg_broker_config_file2 data guard broker configuration file #2
dg_broker_start start Data Guard broker framework (DMON process)
dispatchers specifications of dispatchers
drs_start start DG Broker monitor (DMON process)
fal_client FAL client
fal_server FAL server list
fast_start_mttr_target MTTR target of forward crash recovery in seconds
file_mapping enable file mapping
filesystemio_options IO operations on filesystem files
log_archive_dest_10 archival destination #10 text string
log_archive_dest_6 archival destination #6 text string
log_archive_dest_7 archival destination #7 text string
log_archive_dest_8 archival destination #8 text string
log_archive_dest_9 archival destination #9 text string
log_archive_dest_state_10 archival destination #10 state text string
log_archive_dest_state_6 archival destination #6 state text string
log_archive_dest_state_7 archival destination #7 state text string
log_archive_dest_state_8 archival destination #8 state text string
log_archive_dest_state_9 archival destination #9 state text string
nls_length_semantics create columns using byte or char semantics by default
nls_nchar_conv_excp NLS raise an exception instead of allowing implicit conversion
olap_page_pool_size size of the olap page pool in bytes
optimizer_dynamic_sampling optimizer dynamic sampling
pga_aggregate_target Target size for the aggregate PGA memory consumed by the instanc
plsql_compiler_flags PL/SQL compiler flags
plsql_native_c_compiler plsql native C compiler
plsql_native_library_dir plsql native library dir
plsql_native_library_subdir_count plsql native library number of subdirectories
plsql_native_linker plsql native linker
plsql_native_make_file_name plsql native compilation make file
plsql_native_make_utility plsql native compilation make utility
remote_listener remote listener
shared_servers number of shared servers to start up
standby_file_management if auto then files are created/dropped automatically on standby
statistics_level statistics level
trace_enabled enable KST tracing
undo_retention undo retention in seconds
undo_suppress_errors Suppress RBU errors in SMU mode
undo_tablespace use/switch undo tablespace
workarea_size_policy policy used to size SQL working areas (MANUAL/AUTO)

******** Dynamic Memory Management / Automatic Memory


Tuning

Automatic PGA Memory Management

With Oracle 9i a new method of tuning the PGA memory areas was introduced.
Automatic PGA Memory Management takes the place of setting the sort_area_size,
sort_area_retained_size, sort_area_hash_size and other related memory management
parameters that all Oracle DBA's are familiar with.

The PGA memory management is now controlled by just two parameters

 pga_aggregate_target,
 workarea_size_policy

Note that work_area_size_policy can be altered per database session, allowing manual
memory management on a per session basis if needed. eg. a session is loading a large
import file and a rather large sort_area_size is needed. A logon trigger could be used to
set the work_area_size policy for the account doing the import.

A session is normally allowed to use up to approximately 5% of the PGA memory


available. This is controlled by the undocumented initialization parameter
_smm_max_size. This value is specified in kilobytes. eg. a value of 1000 really means
1000k. As with all undocumented parameters, don't expect help from Oracle support with
it, as you are not supposed to use it. If you experiment with it, do so on a test system.

Also note that Automate PGA management can only be used for dedicated server
sessions.

For more some good reading on Automatic PGA management, please see:

Oracle Documentation for Tuning PGA

The documentation contains some good guidelines for initial settings, and how to monitor
and tune them as needed.
If your 9i database is currently using manual PGA management, there are views available
to help you make a reasonable estimate for the setting.

If your database also has statspack statistics, then there is also historical information
available to help you determine the setting.

An initial setting can be determined by simply monitoring the amount of PGA memory
being used by the system as seen in v$pgastat, and by querying the
v$pga_target_for_estimate view.

v$pgastat:
select *
from v$pgastat
order by lower(name)
/

NAME VALUE UNIT


---------------------------------------- ------------------ ------------
aggregate PGA auto target 8,294,400.00 bytes
aggregate PGA target parameter 25,165,824.00 bytes
bytes processed 24,929,280.00 bytes
cache hit percentage 86.31 percent
extra bytes read/written 3,953,664.00 bytes
global memory bound 1,257,472.00 bytes
maximum PGA allocated 26,661,888.00 bytes
maximum PGA used for auto workareas 172,032.00 bytes
maximum PGA used for manual workareas 525,312.00 bytes
over allocation count .00
PGA memory freed back to OS 6,750,208.00 bytes
total freeable PGA memory 65,536.00 bytes
total PGA allocated 23,957,504.00 bytes
total PGA inuse 15,283,200.00 bytes
total PGA used for auto workareas .00 bytes
total PGA used for manual workareas .00 bytes

16 rows selected.
The statistic "maximum PGA allocated" will display the maximum amount of PGA
memory allocated during the life of the instance.

The statistic "maximum PGA used for auto workareas" and "maximum PGA used for
manual workareas" will display the maximum amount of PGA memory used for each
type of workarea during the life of the instance.

v$pga_target_advice:
select *
from v$pga_target_advice
order by pga_target_for_estimate
/
PGA TARGET PGA TARGET ESTIMATED EXTRA
ESTIMATED PGA ESTIMATED OVER
FOR EST FACTOR ADV BYTES PROCESSED BYTES RW
CACHE HIT % ALLOC COUNT
---------------- ---------- --- ---------------- ----------------
------------- --------------
12,582,912 .50 ON 17,250,304 0
100.00 3
18,874,368 .75 ON 17,250,304 0
100.00 3
25,165,824 1.00 ON 17,250,304 0
100.00 0
30,198,784 1.20 ON 17,250,304 0
100.00 0
35,231,744 1.40 ON 17,250,304 0
100.00 0
40,264,704 1.60 ON 17,250,304 0
100.00 0
45,297,664 1.80 ON 17,250,304 0
100.00 0
50,331,648 2.00 ON 17,250,304 0
100.00 0
75,497,472 3.00 ON 17,250,304 0
100.00 0
100,663,296 4.00 ON 17,250,304 0
100.00 0
150,994,944 6.00 ON 17,250,304 0
100.00 0
201,326,592 8.00 ON 17,250,304 0
100.00 0

12 rows selected.

Querying v$pga_target_advice can help you determine a good setting for


pga_aggregate_target. As seen in the previous query, an 18M PGA setting would have
caused Oracle to allocate more memory than specified on 3 occasions. With a 25M PGA,
this would not have happened.

Keep in mind that pga_aggregate_target is not set in stone. It is used to help Oracle better
manage PGA memory, but Oracle will exceed this setting if necessary.

There are other views that are also useful for PGA memory management.

v$process:
select
max(pga_used_mem) max_pga_used_mem
, max(pga_alloc_mem) max_pga_alloc_mem
, max(pga_max_mem) max_pga_max_mem
from v$process
/

This will show the maximum PGA usage per process:


select
max(pga_used_mem) max_pga_used_mem
, max(pga_alloc_mem) max_pga_alloc_mem
, max(pga_max_mem) max_pga_max_mem
from v$process
/

This displays the sum of all current PGA usage per process:
select
sum(pga_used_mem) sum_pga_used_mem
, sum(pga_alloc_mem) sum_pga_alloc_mem
, sum(pga_max_mem) sum_pga_max_mem
from v$process
/

Be sure to read the documentation referenced earlier, it contains an excellent explanation


of Automatic PGA Memory Management.

Following are some already canned scripts that may be of use.

******** Server Parameter File


Server parameter file (SPFILE) is new in Oracle9i that could be used to replace your
initialization file. While creating a database, you need to start with the traditional text
initialization parameter file (initSID.ora). SPFILE feature lets the DBA change the
parameter values without directly login to the server.

The SPFILE (spfile_SID.ora) is maintained on the server (on UNIX,


$ORACLE_HOME/dbs directory) in a binary format by Oracle. You’re not supposed to
edit this file. Changes to the SPFILE file are made using the ‘ALTER SYSTEM SET
<parameter_name> = <value> SCOPE=SPFILE’ statement. The SCOPE=BOTH also
changes the SPFILE.

Examples:

ALTER SYSTEM SET USER_DUMP_DEST=’/ora_dump/SID’ SCOPE=SPFILE;

ALTER SYSTEM SET SORT_AREA_SIZE=1048576 SCOPE=BOTH;

ALTER SYSTEM SET ROLLBACK_SEGMENTS=’’ SCOPE=SPFILE;

SPFILE can be generated from the traditional initSID.ora file using the CREATE
SPFILE FROM PFILE statement.

To change a parameter that need to open the database if the database is down, you need to
do the following:

1. STARTUP NOMOUNT
2. ALTER SYSTEM SET … SCOPE=SPFILE;
3. SHUTDOWN
4. STARTUP

Read, “Managing initialization parameters using a server parameter file” from Oracle
documentation.

******** Oracle Managed Files


Oracle Managed Files (OMF) is introduced in Oracle9i. OMF lets the DBA not worry
about file names and location once a parameter is defined in the database. This is good
for non-production databases where you can afford to keep all your data files in one
location or on LVM systems.

OMF is managed by the following parameters:

DB_CREATE_FILE_DEST – Specifies the location of the data files. This parameter can
be altered dynamically.

DB_CREATE_ONLINE_LOG_DEST_n – Specifies the location of the redo log files.


The ‘n’ can from 1 through 5, meaning you can specify up to 5 locations for redo log
files.

Advantages:

No need to specify the location, size or name of the data files when
creating tablespaces.
Automatically removes files from the OS when tablespace or redo
group is dropped.
Third party applications need not worry about OS specific file name
conventions.

I’m personally not a fan of OMF, but I use the INCLUDING CONTENTS AND
DATAFILES clause of DROP TABLESPACE to remove the OS files when a tablespace
is dropped. I like this feature.

DROP TABLESPACE MYTS INCLUDING CONTENTS AND DATAFILES;

Read more about OMF at OTN 9i daily feature – March 20

Also, see Oracle documentation.


******** Using multiple block sizes
This is one of the most exciting new features for the DBA, especially now a day there
are many databases where you can hardly distinguish between OLTP and DSS….

In the pre-9i releases, you define the BLOCK_SIZE when creating the database and it
cannot be changed. In 9i also this is true. In addition to the standard block size of the
database, you can create tablespaces with different block size. The block size of the
tablespace is specified using the BLOCK SIZE clause of CREATE TABLESPACE.

For you to use this feature, you need to set the right buffer cache parameter. The
DB_CACHE_SIZE specifies the buffer cache size for the objects in tablespaces created
with the standard block size. DB_nK_CACHE_SIZE parameter sets the appropriate
buffer cache for the non-standard block sized tablespace. ‘n’ could be 2, 4, 8, 16 or 32 but
it should not be equal to your standard block size. The default values for
DB_nK_CACHE_SIZE parameters are 0.

SQL> show parameter db%cache


 
NAME TYPE VALUE
------------------------------------ ----------- -------
db_16k_cache_size big integer 0
db_2k_cache_size big integer 0
db_32k_cache_size big integer 0
db_4k_cache_size big integer 0
db_8k_cache_size big integer 0
db_cache_advice string OFF
db_cache_size big integer 0
db_keep_cache_size big integer 0
db_recycle_cache_size big integer 0
SQL> show parameter db_block
 
NAME TYPE VALUE
------------------------------------ ----------- -------
db_block_buffers integer 1500
db_block_checking boolean FALSE
db_block_checksum boolean TRUE
db_block_size integer 8192
SQL>

Look at the above parameters; since the database was upgraded from 8i, it is still using
the old style buffer cache sizing using DB_BLOCK_BUFFERS. Here we cannot set any
of the DB_nK_CACHE_SIZE parameter because you have not used the
DB_CACHE_SIZE parameter to start the database.

SQL> alter system set db_4k_cache_size=20;


alter system set db_4k_cache_size=20
*
ERROR at line 1:
ORA-02097: parameter cannot be modified because specified value is
invalid
ORA-00381: cannot use both new and old parameters for buffer cache size
specification
 
SQL>

Let’s try another database:

SQL> show parameter db%cache


 
NAME TYPE VALUE
------------------------------------ ----------- ------------
db_16k_cache_size big integer 0
db_2k_cache_size big integer 0
db_32k_cache_size big integer 0
db_4k_cache_size big integer 0
db_8k_cache_size big integer 0
db_cache_advice string ON
db_cache_size big integer 83886080
db_keep_cache_size big integer 0
db_recycle_cache_size big integer 0
SQL> show parameter sga
 
NAME TYPE VALUE
------------------------------------ ----------- ------------
lock_sga boolean FALSE
pre_page_sga boolean FALSE
sga_max_size big integer 220163984
SQL>
SQL> alter system set db_cache_size=20m;
 
System altered.
 
SQL> alter system set db_4k_cache_size=2M;
 
System altered.
 
SQL> show parameter db%cache
 
NAME TYPE VALUE
------------------------------------ ----------- -------------------
db_16k_cache_size big integer 0
db_2k_cache_size big integer 0
db_32k_cache_size big integer 0
db_4k_cache_size big integer 16777216
db_8k_cache_size big integer 0
db_cache_advice string ON
db_cache_size big integer 33554432
db_keep_cache_size big integer 0
db_recycle_cache_size big integer 0
SQL>
SQL>
SQL> create tablespace test_biju datafile
2 '/ora_backup/test_biju.dbf' size 50m
3 extent management local
4* blocksize 4k
SQL> /
 
Tablespace created.
 
SQL>
SQL> select block_size from dba_tablespaces
2 where tablespace_name = 'TEST_BIJU';
 
BLOCK_SIZE
----------
4096
 
1 row selected.
 
SQL> drop tablespace test_biju including contents and datafiles;
 
Tablespace dropped.
 

******** Multi-table INSERT


Inserts to multiple tables in a single INSERT statement are a significant addition to the
Oracle9i database ETL features. This allows the INSERT INTO … SELECT statement
to load data to multiple target tables. A single scan can perform inserts to multiple target
tables [based on the conditions you specify - optional].

Prior to Oracle9i, you may have to write multiple INSERT statements for each table or
use a PL/SQL cursor to insert into different tables.

The syntax of multi-table insert is:

INSERT { ALL insert_into_clause [values_clause]


[insert_into_clause [values_clause]]...
| conditional_insert_clause
}
subquery

where the conditional_insert_clause is

[ ALL | FIRST ]
WHEN condition THEN insert_into_clause [values_clause]
[insert_into_clause [values_clause]]...
[WHEN condition THEN insert_into_clause [values_clause]
[insert_into_clause [values_clause]]...
]...
[ELSE insert_into_clause [values_clause]
[insert_into_clause [values_clause]]...
]
The INSERT ALL clause inserts rows into the target tables unconditionally. Each row
read is processed against each INSERT clause.

The following example takes each row from SALES_HISTORY table and inserts into the
SALES_MONTHLY table a total amount for each month (flat table to a normalized
table):

DESC SALES_HISTORY
Name Null? Type
----------------------------------------- -------- -------------
YEAR NUMBER(4)
REGION CHAR (2)
JAN NUMBER
FEB NUMBER
MAR NUMBER
APR NUMBER
MAY NUMBER
JUN NUMBER
JUL NUMBER
AUG NUMBER
SEP NUMBER
OCT NUMBER
NOV NUMBER
DEC NUMBER
 
DESC SALES_MONTHLY
Name Null? Type
----------------------------------------- -------- -------------
MONTH_YEAR DATE
AMOUNT NUMBER
 
INSERT ALL
INTO SALES_MONTHLY (MONTH_YEAR, AMOUNT)
VALUES (TO_DATE('01/'||YEAR,'MM/YYYY'), JAN)
INTO SALES_MONTHLY VALUES (TO_DATE('02/'||YEAR,'MM/YYYY'), FEB)
INTO SALES_MONTHLY VALUES (TO_DATE('03/'||YEAR,'MM/YYYY'), MAR)
INTO SALES_MONTHLY VALUES (TO_DATE('04/'||YEAR,'MM/YYYY'), APR)
INTO SALES_MONTHLY VALUES (TO_DATE('05/'||YEAR,'MM/YYYY'), MAY)
INTO SALES_MONTHLY VALUES (TO_DATE('06/'||YEAR,'MM/YYYY'), JUN)
INTO SALES_MONTHLY VALUES (TO_DATE('07/'||YEAR,'MM/YYYY'), JUL)
INTO SALES_MONTHLY VALUES (TO_DATE('08/'||YEAR,'MM/YYYY'), AUG)
INTO SALES_MONTHLY VALUES (TO_DATE('09/'||YEAR,'MM/YYYY'), SEP)
INTO SALES_MONTHLY VALUES (TO_DATE('10/'||YEAR,'MM/YYYY'), OCT)
INTO SALES_MONTHLY VALUES (TO_DATE('11/'||YEAR,'MM/YYYY'), NOV)
INTO SALES_MONTHLY VALUES (TO_DATE('12/'||YEAR,'MM/YYYY'), DEC)
SELECT YEAR,
SUM(JAN) JAN, SUM(FEB) FEB, SUM(MAR) MAR, SUM(APR) APR,
SUM(MAY) MAY, SUM(JUN) JUN, SUM(JUL) JUL, SUM(AUG) AUG,
SUM(SEP) SEP, SUM(OCT) OCT, SUM(NOV) NOV, SUM(DEC) DEC
FROM SALES_HISTORY
GROUP BY YEAR
/
The ALL in the conditional insert clause makes Oracle evaluate all the WHEN conditions
irrespective of the other WHEN conditions. The FIRST clause stops evaluating other
WHEN conditions the first time any condition is evaluated true. The conditions are
evaluated in the order they appear.

INSERT FIRST
WHEN REGION = 'TX' THEN
INTO SALES_TEXAS (YEAR, TOTAL_AMOUNT)
VALUES (YEAR, TOTAMT)
WHEN REGION = 'CA' THEN
INTO SALES_CALIF (YEAR, TOTAL_AMOUNT)
VALUES (YEAR, TOTAMT)
WHEN REGION = 'NM' THEN
INTO SALES_NEWMEX (YEAR, TOTAL_AMOUNT)
VALUES (YEAR, TOTAMT)
WHEN REGION = 'AZ' THEN
INTO SALES_ARIZ (YEAR, TOTAL_AMOUNT)
VALUES (YEAR, TOTAMT)
ELSE
INTO SALES_OTHER (YEAR, TOTAL_AMOUNT)
VALUES (YEAR, TOTAMT)
SELECT YEAR, REGION,
(JAN+FEB+MAR+APR+MAY+JUN+JUL+AUG+SEP+OCT+NOV+DEC) TOTAMT
FROM SALES_HISTORY
/

If the ELSE clause is omitted, Oracle takes no action on that row.

******** Index Skip Scan


In pre-Oracle9i releases a composite index could only be used if the leading edge
column of the index was referenced in the WHERE clause of a statement. In Oracle9i this
restriction is removed because the optimizer can perform skip scans to retrieve rowids for
values that do not use the prefix. 
Skip scanning lets a composite index be split logically into smaller sub-indexes. Skip
scanning is advantageous if there are few distinct values in the leading column of the
composite index and many distinct values in the non-leading key of the index.

The index and table must be analyzed for Oracle to take advantage of index skip scan. 

SQL>
SQL> create table test as
2 select * from dba_objects;
 
Table created.
 
SQL> create index test_i1 on test (owner, object_name);
 
Index created.
 
SQL> set autotrace on
SQL> select object_type, object_name
2 from test
3 where object_name = 'DWA_JOB_LOG';
 
OBJECT_TYPE OBJECT_NAME
------------------ -------------------------
TABLE DW_JOB_LOG
 
1 row selected.
 
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 TABLE ACCESS (FULL) OF 'TEST'
 
SQL>
SQL> analyze table test compute statistics;
 
Table analyzed.
 
SQL> select object_type, object_name
2 from test
3* where object_name = 'DWA_JOB_LOG'
SQL> /
 
OBJECT_TYPE OBJECT_NAME
------------------ -------------------------
TABLE DW_JOB_LOG
 
1 row selected.
 
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=46 Card=2 Bytes=62)
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'TEST' (Cost=46 Card=2 By tes=62)
2 1 INDEX (SKIP SCAN) OF 'TEST_I1' (NON-UNIQUE) (Cost=45 Card=2)
 
SQL>

******** DBMS_METADATA
DBMS_METADATA is a powerful package provided in Oracle9i to extract the object
definitions from the database. The following are the programs available in the package:
Subprogram Description
OPEN Procedure
Specifies the type of object to be
retrieved, the version of its metadata,
and the object model.
Subprogram Description
SET_FILTER Procedure
Specifies restrictions on the objects to
be retrieved, for example, the object
name or schema.
SET_COUNT Procedure
Specifies the maximum number of
objects to be retrieved in a single
FETCH_xxx call.
GET_QUERY Procedure
Returns the text of the queries that are
used by FETCH_xxx.
SET_PARSE_ITEM Procedure
Enables output parsing by specifying
an object attribute to be parsed and
returned.
ADD_TRANSFORM Procedure
Specifies a transform that FETCH_xxx
applies to the XML representation of
the retrieved objects.
SET_TRANSFORM_PARAM
Procedure Specifies parameters to the XSLT
stylesheet identified by
transform_handle.
FETCH_xxx Procedure
Returns metadata for objects meeting
the criteria established by OPEN,
SET_FILTER, SET_COUNT,
ADD_TRANSFORM, and so on.
CLOSE Procedure
Invalidates the handle returned by
OPEN and cleans up the associated
state.
GET_XML and GET_DDL Functions
Returns the metadata for the specified
object as XML or DDL.
GET_DEPENDENT_XML and
GET_DEPENDENT_DDL Functions Returns the metadata for one or more
dependent objects, specified as XML or
Subprogram Description

DDL.
GET_GRANTED_XML and
GET_GRANTED_DDL Functions Returns the metadata for one or more
granted objects, specified as XML or
DDL.

Here is an example:

SQL> EXECUTE DBMS_METADATA.SET_TRANSFORM_PARAM


(DBMS_METADATA.SESSION_TRANSFORM, 'STORAGE',false);
 
PL/SQL procedure successfully completed.
 
SQL>
SQL> SELECT DBMS_METADATA.GET_DDL('TABLE','SALES_HISTORY') FROM DUAL;
 
DBMS_METADATA.GET_DDL('TABLE','SALES_HISTORY')
-------------------------------------------------------
 
CREATE TABLE "MYUSER"."SALES_HISTORY"
( "YEAR" NUMBER(4,0),
"JAN" NUMBER,
 
1 row selected.
 
SQL> set long 32000
SQL> SELECT DBMS_METADATA.GET_DDL('TABLE','SALES_HISTORY') FROM DUAL;
 
DBMS_METADATA.GET_DDL('TABLE','SALES_HISTORY')
------------------------------------------------------------------
 
CREATE TABLE "MYUSER"."SALES_HISTORY"
( "YEAR" NUMBER(4,0),
"JAN" NUMBER,
"FEB" NUMBER,
"MAR" NUMBER,
"APR" NUMBER,
"MAY" NUMBER,
"JUN" NUMBER,
"JUL" NUMBER,
"AUG" NUMBER,
"SEP" NUMBER,
"OCT" NUMBER,
"NOV" NUMBER,
"DEC" NUMBER,
"REGION" CHAR(2)
) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
TABLESPACE "USERS"
 
1 row selected.
 
SQL>

SET_TRANSFORM_PARAM: Transform Parameters for the


DDL Transform
Object
Type Name Datatype Meaning

All objects PRETTY Boolean If TRUE, format the output


with indentation and line
feeds. Defaults to TRUE.

SQLTERMINATOR Boolean If TRUE, append a SQL


terminator (; or /) to each
DDL statement. Defaults to
FALSE.

TABLE SEGMENT_ATTRIBUTES Boolean If TRUE, emit segment


attributes (physical
attributes, storage
attributes, tablespace,
logging). Defaults to TRUE.

STORAGE Boolean If TRUE, emit storage clause.


(Ignored if
SEGMENT_ATTRIBUTES is FALSE.)
Defaults to TRUE.

TABLESPACE Boolean If TRUE, emit tablespace.


(Ignored if
SEGMENT_ATTRIBUTES is FALSE.)
Defaults to TRUE.

TABLE CONSTRAINTS Boolean If TRUE, emit all non-


referential table constraints.
Defaults to TRUE.

REF_CONSTRAINTS Boolean If TRUE, emit all referential


constraints (foreign key and
scoped refs). Defaults to
TRUE.
Object
Type Name Datatype Meaning

CONSTRAINTS_AS_ALTER Boolean If TRUE, emit table


constraints as separate
ALTER TABLE (and, if
necessary, CREATE INDEX)
statements. If FALSE, specify
table constraints as part of
the CREATE TABLE statement.
Defaults to FALSE. Requires
that CONSTRAINTS be TRUE.

OID Boolean If TRUE, emit the OID clause


for object tables. Defaults to
FALSE.

SIZE_BYTE_KEYWORD Boolean If TRUE, emit the BYTE


keyword as part of the size
specification of CHAR and
VARCHAR2 columns that use
byte semantics. If FALSE,
omit the keyword. Defaults
to FALSE.

INDEX SEGMENT_ATTRIBUTES Boolean If TRUE, emit segment


attributes (physical
attributes, storage
attributes, tablespace,
logging). Defaults to TRUE.

STORAGE Boolean If TRUE, emit storage clause.


(Ignored if
SEGMENT_ATTRIBUTES is FALSE.)
Defaults to TRUE.

TABLESPACE Boolean If TRUE, emit tablespace.


(Ignored if
SEGMENT_ATTRIBUTES is FALSE.)
Defaults to TRUE.
Object
Type Name Datatype Meaning

TYPE SPECIFICATION Boolean If TRUE, emit the type


specification. Defaults to
TRUE.

BODY Boolean If TRUE, emit the type body.


Defaults to TRUE.

PACKAGE  SPECIFICATION Boolean If TRUE, emit the package


specification. Defaults to
TRUE.

BODY Boolean If TRUE, emit the package


body. Defaults to TRUE.

VIEW FORCE Boolea If TRUE, use the FORCE


keyword in the CREATE VIEW
statement. Defaults to TRUE.

All objects DEFAULT Boolean Calling SET_TRANSFORM_PARAM


with this parameter set to
TRUE has the effect of
resetting all parameters for
the transform to their
default values. Setting this
FALSE has no effect. There is
no default.

INHERIT Boolean If TRUE, inherits session-level


parameters. Defaults to
FALSE. If an application calls
ADD_TRANSFORM to add the
DDL transform, then by
default the only transform
parameters that apply are
those explicitly set for that
transform handle. This has
no effect if the transform
Object
Type Name Datatype Meaning

handle is the session


transform handle.

The two tables on this page are excerpt from Oracle documentation – “PL/SQL Supplied
Packages”

******** DBMS_XPLAN
Remember the SQL you use to get the explain plan from the PLAN_TABLE and you
perform and EXPLAIN on a statement:

  SELECT LPAD(' ', 2*level) || operation ||' ' ||


options ||' ' || object_name || ' COST=' || cost
"Execution Plan"
FROM plan_table
  CONNECT BY PRIOR id = parent_id
START WITH ID = 1

Well, you may never use the above SQL, Oracle9i gives you a package to look at the
explain plans – DBMS_XPLAN.

Here is an example:

SQL> EXPLAIN PLAN FOR


2 select object_type, object_name
3 from test
4* where object_name = 'DWA_JOB_LOG'
SQL> /
 
Explained.
 
SQL> SELECT * FROM TABLE(dbms_xplan.display);
 
PLAN_TABLE_OUTPUT
--------------------------------------------------------
 
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 62 | 46 |
| 1 | TABLE ACCESS BY INDEX ROWID| TEST | 2 | 62 | 46 |
|* 2 | INDEX SKIP SCAN | TEST_I1 | 2 | | 45 |
---------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
2 - access("TEST"."OBJECT_NAME"='DWA_JOB_LOG')
filter("TEST"."OBJECT_NAME"='DWA_JOB_LOG')
 
Note: cpu costing is off
 
16 rows selected.
 
SQL>
SQL> alter table test parallel;
 
Table altered.
 
SQL> delete from plan_table;
 
3 rows deleted.
 
SQL> commit;
 
Commit complete.
 
SQL> EXPLAIN PLAN FOR
2 select object_type, object_name
3 from test
4 where object_name = 'DWA_JOB_LOG'
5 /
 
Explained.
 
SQL> SELECT * FROM TABLE(dbms_xplan.display);
 
PLAN_TABLE_OUTPUT
------------------------------------------------------------
----------------------------------------
 
------------------------------------------------------------------------
-------------------------
| Id | Operation | Name | Rows | Bytes | Cost | TQ
|IN-OUT| PQ Distrib |
------------------------------------------------------------------------
-------------------------
| 0 | SELECT STATEMENT | | 2 | 62 | 5 |
| | |
|* 1 | TABLE ACCESS FULL | TEST | 2 | 62 | 5 |
80,00 | P->S | QC (RAND) |
------------------------------------------------------------------------
-------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
1 - filter("TEST"."OBJECT_NAME"='DWA_JOB_LOG')
 
Note: cpu costing is off
 
14 rows selected.
 
SQL>
 
The following are the parameters of DBMS_XPLAN.DISPLAY procedure:
 
DBMS_XPLAN.DISPLAY(
table_name IN VARCHAR2 DEFAULT 'PLAN_TABLE',
statement_id IN VARCHAR2 DEFAULT NULL, 
format IN VARCHAR2 DEFAULT 'TYPICAL');

******** ANSI Style Outer Joins


If you’re one of those people who always get confused on where to put the (+) for an
outer join, here is relief for you. Oracle9i supports the ANSI style outer join syntax. You
can now use the English like meaningful keywords and even do an outer join from both
tables (full join).

The following are excerpts from Oracle Documentation – SQL Reference Guide

New Outer Join Syntax

An outer join extends the result of a simple join. An outer join returns all rows that
satisfy the join condition and also returns some or all of those rows from one table for
which no rows from the other satisfy the join condition.

To write a query that performs an outer join of tables A and B and


returns all rows from A (a left outer join), use the LEFT [OUTER] JOIN
syntax in the FROM clause, or apply the outer join operator (+) to all
columns of B in the join condition in the WHERE clause. For all rows in
A that have no matching rows in B, Oracle returns null for any select
list expressions containing columns of B.
To write a query that performs an outer join of tables A and B and
returns all rows from B (a right outer join), use the RIGHT [OUTER]
JOIN syntax in the FROM clause, or apply the outer join operator (+) to
all columns of A in the join condition in the WHERE clause. For all rows
in B that have no matching rows in A, Oracle returns null for any
select list expressions containing columns of A.
To write a query that performs an outer join and returns all rows
from A and B, extended with nulls if they do not satisfy the join
condition (a full outer join), use the FULL [OUTER] JOIN syntax in the
FROM clause.

Oracle Corporation recommends that you use the FROM clause OUTER JOIN syntax rather than
the Oracle join operator. Outer join queries that use the Oracle join operator (+) are subject to the
following rules and restrictions, which do not apply to the FROM clause join syntax:
You cannot specify the (+) operator in a query block that also
contains FROM clause join syntax.
The (+) operator can appear only in the WHERE clause or, in the
context of left-correlation (that is, when specifying the TABLE clause)
in the FROM clause, and can be applied only to a column of a table or
view.
If A and B are joined by multiple join conditions, then you must use
the (+) operator in all of these conditions. If you do not, then Oracle
will return only the rows resulting from a simple join, but without a
warning or error to advise you that you do not have the results of an
outer join.
The (+) operator does not produce an outer join if you specify one
table in the outer query and the other table in an inner query.
You cannot use the (+) operator to outer-join a table to itself,
although self joins are valid. For example, the following statement is
not valid:

-- The following statement is not valid:

SELECT employee_id, manager_id


FROM employees
WHERE employees.manager_id(+) =
employees.employee_id;
 

However, the following self join is valid:

SELECT e1.employee_id, e1.manager_id, e2.employee_id


FROM employees e1, employees e2
WHERE e1.manager_id(+) = e2.employee_id;
 
The (+) operator can be applied only to a column, not to an arbitrary
expression. However, an arbitrary expression can contain one or
more columns marked with the (+) operator.
A condition containing the (+) operator cannot be combined with
another condition using the OR logical operator.
A condition cannot use the IN comparison condition to compare a
column marked with the (+) operator with an expression.
A condition cannot compare any column marked with the (+)
operator with a subquery.
If the WHERE clause contains a condition that compares a column
from table B with a constant, then the (+) operator must be applied
to the column so that Oracle returns the rows from table A for which
it has generated nulls for this column. Otherwise Oracle will return
only the results of a simple join.
In a query that performs outer joins of more than two pairs of
tables, a single table can be the null-generated table for only one
other table. For this reason, you cannot apply the (+) operator to
columns of B in the join condition for A and B and the join condition
for B and C.

Using Outer Joins: Examples

The following example uses a left outer join to return the names of all departments in the
sample schema hr, even if no employees have been assigned to the departments:

SELECT d.department_id, e.last_name


FROM departments d LEFT OUTER JOIN employees e
ON d.department_id = e.department_id
ORDER BY d.department_id;
 
DEPARTMENT_ID LAST_NAME
------------- -------------------------
10 Whalen
20 Hartstein
20 Fay
30 Raphaely
...
250
260
270

Users familiar with the traditional Oracle outer joins syntax will recognize the same
query in this form:

SELECT d.department_id, e.last_name


FROM departments d, employees e
WHERE d.department_id = e.department_id(+)
ORDER BY d.department_id;

The left outer join returns all departments, including those without any employees. The
same statement with a right outer join returns all employees, including those not yet
assigned to a department:

SELECT d.department_id, e.last_name


FROM departments d RIGHT OUTER JOIN employees e
ON d.department_id = e.department_id
ORDER BY d.department_id;
 
DEPARTMENT_ID LAST_NAME
------------- -------------------------
...
110 Higgins
110 Gietz
Grant
Zeuss
It is not clear from this result whether employees Grant and Zeuss have department_id
NULL, or whether their department_id is not in the departments table. To determine this
requires a full outer join:

SELECT d.department_id as d_dept_id,


e.department_id as e_dept_id, e.last_name
FROM departments d FULL OUTER JOIN employees e
ON d.department_id = e.department_id
ORDER BY d.department_id;
 
D_DEPT_ID E_DEPT_ID LAST_NAME
---------- ---------- -------------------------
...
110 110 Gietz
110 110 Higgins
...
260
270
999 Zeuss
Grant

Because the column names in this example are the same in both tables in the join, you
can also use the common column feature (the USING clause) of the join syntax, which
coalesces the two matching columns department_id. The output is the same as for the
preceding example:

SELECT department_id AS d_e_dept_id, e.last_name


FROM departments d FULL OUTER JOIN employees e
USING (department_id)
ORDER BY department_id;
 
D_E_DEPT_ID LAST_NAME
----------- -------------------------
...
110 Higgins
110 Gietz
...
260
270
Grant
Zeuss

******** Random Sampling of Data


The SELECT statement in Oracle9i provides the SAMPLE clause to read a random
sample of data from table.

SELECT ...table_name SAMPLE [BLOCK] ( sample_percent )


You can sample the rows based on a random number of blocks instead of random rows.
The BLOCK keyword must be included for block sampling. The optional sample percent
must be less than 100.

When using the SAMPLE clause, the query must select only from one table, join queries
are not supported.

SQL >select count(*) from test sample (1);


 
COUNT(*)
----------
341
 
1 row selected.
 
SQL >select count(*) from test;
 
COUNT(*)
----------
33574
 
1 row selected.
 
SQL > select count(*) * 100 from test sample (1);
 
COUNT(*)*100
------------
35000
 
1 row selected.
 
SQL >

******** New Data Types

******** “Upsert” or the MERGE statement

MERGE is a new SQL statement introduced in Oracle9i to update or insert rows selected
from one table to another based on a condition. This avoids writing multiple DML
statements to satisfy a conditional update or insert. The syntax is:

MERGE [hint] INTO [schema .] table [t_alias] USING [schema .] 


{ table | view | subquery } [t_alias] ON ( condition ) 
WHEN MATCHED THEN UPDATE SET column = { expr | DEFAULT } [, column =
{ expr | DEFAULT }]...
WHEN NOT MATCHED THEN INSERT ( column [, column]... ) VALUES ( expr [,
expr]... )
MERGE
Purpose

Use the MERGE statement to select rows from one table for update or insertion into another
table. The decision whether to update or insert into the target table is based on a condition
in the ON clause.

This statement is a convenient way to combine at least two operations. It lets you avoid
multiple INSERT and UPDATE DML statements.

MERGE is a deterministic statement. That is, you cannot update the same row of the target
table multiple times in the same MERGE statement.

Prerequisites

You must have INSERT and UPDATE object privileges on the target table and SELECT
privilege on the source table.

Syntax

merge::=

Syntax

merge::=

Text description of merge

merge_update_clause::=
Text description of merge_update_clause

merge_insert_clause::=

Text description of merge_insert_clause

Semantics

INTO Clause

Use the INTO clause to specify the target table you are updating or inserting into.

USING Clause

Use the USING clause to specify the source of the data to be updated or inserted. The
source can be a table, view, or the result of a subquery.

ON Clause

Use the ON clause to specify the condition upon which the MERGE operation either updates
or inserts. For each row in the target table for which the search condition is true, Oracle
updates the row based with corresponding data from the source table. If the condition is
not true for any rows, then Oracle inserts into the target table based on the corresponding
source table row.

WHEN MATCHED | NOT MATCHED

Use these clauses to instruct Oracle how to respond to the results of the join condition in
the ON clause. You can specify these two clauses in either order.

merge_update_clause

The merge_update_clause specifies the new column values of the target table. Oracle
performs this update if the condition of the ON clause is true. If the update clause is
executed, then all update triggers defined on the target table are activated.

Restrictions on Updating a View


 You cannot specify DEFAULT when updating a view.
 You cannot update a column that is referenced in the ON condition clause.

merge_insert_clause

The merge_insert_clause specifies values to insert into the column of the target table
if the condition of the ON clause is false. If the insert clause is executed, then all insert
triggers defined on the target table are activated.

Restriction on Merging into a View

You cannot specify DEFAULT when updating a view.

Examples

Merging into a Table: Example

The following example creates a bonuses table in the sample schema oe with a default
bonus of 100. It then inserts into the bonuses table all employees who made sales (based
on the sales_rep_id column of the oe.orders table). Finally, the Human Resources
manager decides that all employees should receive a bonus. Those who have not made
sales get a bonus of 1% of their salary. Those who already made sales get an increase in
their bonus equal to 1% of their salary. The MERGE statement implements these changes in
one step:

CREATE TABLE bonuses (employee_id NUMBER, bonus NUMBER DEFAULT 100);

INSERT INTO bonuses(employee_id)


(SELECT e.employee_id FROM employees e, orders o
WHERE e.employee_id = o.sales_rep_id
GROUP BY e.employee_id);

SELECT * FROM bonuses;

EMPLOYEE_ID BONUS
----------- ----------
153 100
154 100
155 100
156 100
158 100
159 100
160 100
161 100
163 100

MERGE INTO bonuses D


USING (SELECT employee_id, salary, department_id FROM employees
WHERE department_id = 80) S
ON (D.employee_id = S.employee_id)
WHEN MATCHED THEN UPDATE SET D.bonus = D.bonus + S.salary*.01
WHEN NOT MATCHED THEN INSERT (D.employee_id, D.bonus)
VALUES (S.employee_id, S.salary*0.1);

EMPLOYEE_ID BONUS
----------- ----------
153 180
154 175
155 170
156 200
158 190
159 180
160 175
161 170
163 195
157 950
145 1400
170 960
179 620
152 900
169 1000
.

DO U KNOW

1998/10In PL/SQL you can suspend a session using


dbms_lock.sleep (seconds) which is equivalent to the 'sleep'
command in UNIX. The parameter (number data type) can even be
specified in hundredth of a second (10, 10.01, 10.5, 0.99 are all
legal values).

1998/11 When you TRUNCATE a table, the storage parameter NEXT


is automatically reset to the last extent deleted. Similarly when you
de-allocate extents from a table, the NEXT is automatically reset to
the size of the last extent deallocated.

1998/12 In PL/SQL you can assign a rollback segment to a


transaction (without using dynamic sql) by utilizing the Oracle
supplied package dbms_transaction.use_rollback_segment
('rbs_name').
The SQL select to_char(to_date(123456,'J'), 'JSP') from
1999/01
dual; can be used to convert numbers to words, here is the result:
ONE HUNDRED TWENTY-THREE THOUSAND FOUR HUNDRED FIFTY-
SIX.

To find the difference between date columns in Days, Hours,


1999/02
Minutes & Seconds use the SQL - Select trunc(date2 - date1) days,
to_char( to_date( trunc( mod(date2-date1,1) * 86400), 'SSSSS'),
'HH24:MI:SS') time from tablename;

The file sgadefSID.dbf is created at instance startup in


1999/03
$ORACLE_HOME/dbs directory and its function is to store the
address of the memory location of the SGA. When the instance is
shutdown, this file is deleted.

1999/04In oracle7, you have to query the table SYS.FILEXT$ to find


if AUTOEXTEND feature for a file is enabled and this table is only
created if the AUTOEXTEND feature is ever turned on in any datafile
in the database. The values for MAXEXTEND (max file size) and INC
(increment) are expressed in BLOCKS. In Oracle8, the
DBA_DATA_FILES view has this info.

1999/05 In oracle8i, to drop a column from a table, you no longer


have to create a temp table and do insert!! Cool!! The drop column
clause in ALTER TABLE lets you free space in the database by
dropping columns you no longer need, or by marking them to be
dropped at a future time when the demand on system resources is
less. You can view the tables with columns marked unusable in
DBA_UNUSED_COL_TABS.

1999/06 In oracle8i, you can fire a trigger on database STARTUP,


SHUTDOWN, SERVERERROR; user LOGON, LOGOFF; object
CREATE, ALTER, DROP. The trigger defined in database level will
fire for all users and schema level will fire only for the specific user
when the event occurs.

1999/07In oracle8i, there is a new option available to shutdown


database "SHUTDOWN TRANSACTIONAL". After submitting this
statement, no client can start a new transaction on this instance. If
clients attempt to start a new transaction, they are disconnected.
After all transactions have completed, any client still connected to
the instance is disconnected.

1999/08 In oracle8i, you can create temporary tables, which are


created in users temporary tablespace. Its definition is visible to all
sessions but the data is visible to, and can be queried by, only the
session that inserts the data into the table.

In oracle8i, you can reorganize a non-partitioned table


1999/09
without doing export and import. The table can be moved from one
tablespace to another also, operation requires double the amount of
space. (ALTER TABLE mytable MOVE TABLESPACE newtablespace;)

1999/10In oracle8i, TRIM function is available, which is a


combination of the existing LTRIM and RTRIM functions, allowing
the user to trim leading and trailing characters from a character
string.

In Oracle 8i, you can create an index reverse keyed


1999/11
[CREATE INDEX i ON t (a,b,c) REVERSE;]. Since lexically adjacent
keys are not stored next to each other in a reverse-key index, only
fetch-by-key or full-index (table) scans can be performed.

In Oracle8, the V$INSTANCE system view has many useful


1999/12
information like the hostname, startup time, version, etc.

Oracle error codes from 10000 to 10999 are pseudo-error


2000/01
messges which are used for setting event traces to debug.

2000/02 A temporary segment created on a TEMPORARY tablespace


is released only at shutdown, the temporary segments are reused;
whereas a temporary segment created on a PERMANENT tablespace
is cleaned up by the SMON process once the completion of the
statement and the space is released.

In Oracle8i, on most of the UNIX platforms, the


2000/03
sgadefSID.dbf is not created when the database is started. If you
use sgadefSID.dbf in the scripts to verify if the database is up, you
may need to look for the pmon_SID process from now on.

The V$RESERVED_WORDS system view has all the keywords


2000/04
that are reserved by Oracle.

In Oracle8i, you need not recreate the control file to adjust


2000/05
MAXDATAFILES defined at database creation, when increasing the
DB_FILES parameter, Oracle automatically adjusts the control file. 

2000/06 In Oracle8i, you can specify up to 5 archive log destinations


using the LOG_ARCHIVE_DEST_n parameter.

2000/07In release 8.1.6, block checking and checksums are turned


on for the SYSTEM tablespace, allowing the Oracle server to detect
and repair any SYSTEM tablespace corruptions before they are written
to disk.

OUTLN schema in Oracle8i database has a default password


2000/08
of OUTLN. This schema has some powerful privileges and hence the
password must be changed.

2000/09 Statspack collects high-resource SQL whereas UTLESTAT


does not.

You can upload the utlestat reports and statspack reports to


2000/10
www.oraperf.com for analyzing.

In Oracle8i, ALTER SYSTEM SUSPEND statement can


2000/11
suspend all I/O operations of the database, enabling hot backups
using OS mirror splits.

2000/12In Oracle8i, use $ORACLE_HOME/rdbms/admin/utlrp.sql


script to recompile all invalid PL/SQL stored programs, triggers and
views. You must connect as SYS or INTERNAL.

2001/01 In Oracle8i, you can execute DDL commands inside PL/SQL


block using the "EXECUTE IMMEDIATE" statement. Prior to 8i, you
need to parse and execute the command using the DBMS_SQL
package.

2001/02In Oracle8i, temporary tables can be created using CREATE


GLOBAL TEMPORARY TABLE statement, data in such tables are
visible only to the session that inserts rows. Rows are deleted at
the end of transaction or end of session (based on the ON COMMIT
clause table definition).

2001/03 You can move a table from one tablespace to another using
the MOVE clause of ALTER TABLE statement. All indexes of moved
table need to be rebuilt.

In Oracle8i, non-unique indexes can be created to enforce


2001/04
unique and primary key constraints. 

2001/05 In Oracle7, SELECT ANY TABLE privilege gave access to


dictionary views such as DBA_ and V$ views. In Oracle8i, you need
to set O7_DICTIONARY_ACCESSIBILITY=TRUE to achieve this
behavior. The new predefined roles SELECT_CATALOG_ROLE and
EXECUTE_CATALOG_ROLE can be used in 8i.

2001/06Composite partitioning in Oracle8i uses range partitioning


for partitions and hash partitioning for sub-partitions. Only sub-
partitions store data.
2001/07Oracle8i 8.1.6 release on UNIX platforms do not have the
"sqlload" executable, instead comes with "sqlldr" executable. If
your scripts are using "sqlload", you need to make a soft link using
"ln -s sqlldr sqlload"

2001/08 With Oracle8i 8.1.7, a new tool named iSQL*Plus is


available, which is a browser based SQL*Plus tool. No need to
install client software on every PC to use SQL*Plus!!

2001/09 Oracle9i supports ANSI SQL99 standard for specifying join


between tables. You can use NATURAL JOIN, CROSS JOIN, JOIN
ON, JOIN USING, LEFT OUTER JOIN, RIGHT OUTER JOIN and FULL
JOIN syntaxes.

2001/10 The TIMESTAMP data type in Oracle9i can store Date/Time


values with up to 9 digits precision for seconds. TIMESTAMP WITH
[LOCAL] TIME ZONE data type can also store time zone
information.

2001/11 In Oracle9i, you can define primary key, unique key and
foreign key constraints on views. These constraints are declarative
hence the only valid state is DISABLE NOVALIDATE.

In Oracle9i, ALTER INDEX <index name> MONITORING


2001/12
USAGE statement can monitor if an index is used.

2002/01 In Oracle9i, Server manager tool is not available. You need


to use "sqlplus /nolog" instead of "svrmgrl" and "connect / as
sysdba" instead of "connect internal".

In Oracle9i, CASE expression can be used instead of using


2002/02
complex DECODE functions.

2002/03 Prior to Oracle9i, database buffer cache size was determined


by DB_BLOCK_BUFFERS times DB_BLOCK_SIZE. In Oracle9i, the
DB_CACHE_SIZE parameter specifies the size.

You might also like