Oracle Relational Tables
Version 12.1.0.1

General Information
Library Note Morgan's Library Page Footer
The Library is currently in the process of being upgraded from Oracle Database Version 11.2.0.3 to 12.1.0.1. Demos are being upgraded to reflect the new Container paradigm as well as EBR (Edition Based Redefinition) and may contain references to CDBs, PDBs, and other objects you may not be familiar with such as CDB_OBJECTS_AE: Welcome to 12c.
Purpose Oracle defines two basic table types: Relational and Object. This page focuses on Relational Heap Tables which is the default table type in Oracle. Library pages on other forms of relational tables: can be access via the links in the Table Types section below

Simply stated relational tables are the primary way permanently store data in a relational database. The complete syntax for create table is so complex that there is no rational way to explore it on a single Library page so use the "Relational Table Types" to select the type of relational table you are researching. There is also a table of links titled "Relational Table Clauses" that will take you to the section of this page, or another Library page, with demos for that clause.
Row Chaining and Migration Row chaining occurs when a row can no longer fit into its original block. If the entire row can fit in a new block, the row is moved completely, leaving only a forwarding pointer - this is known as row migration. If the row has grown so large that it may not fit in a single block then the row is split into two or more blocks - row chaining. When Oracle is forced to split a row into pieces, it often splits individual columns into one or more pieces.
Follow the ANALYZE link at page bottom and find the section titled "List Chained Rows"
Dependencies
ALL_ALL_TABLES CDB_TAB_COL_STATISTICS DBA_TAB_PRIVS
ALL_COL_COMMENTS CDB_TAB_COMMENTS DBA_TAB_STATISTICS
ALL_PARTIAL_DROP_TABS CDB_TAB_HISTOGRAMS DBA_TAB_STATS_HISTORY
ALL_TABLES CDB_TAB_MODIFICATIONS DBA_UNUSED_COL_TABS
ALL_TAB_COLS CDB_TAB_PRIVS TAB$
ALL_TAB_COLUMNS CDB_TAB_STATISTICS USER_ALL_TABLES
ALL_TAB_COL_STATISTICS CDB_TAB_STATS_HISTORY USER_COL_COMMENTS
ALL_TAB_COMMENTS CDB_UNUSED_COL_TABS USER_PARTIAL_DROP_TABS
ALL_TAB_HISTOGRAMS COL$ USER_TABLES
ALL_TAB_MODIFICATIONS DBA_ALL_TABLES USER_TAB_COLS
ALL_TAB_PRIVS DBA_COL_COMMENTS USER_TAB_COLUMNS
ALL_TAB_STATISTICS DBA_PARTIAL_DROP_TABS USER_TAB_COL_STATISTICS
ALL_TAB_STATS_HISTORY DBA_TABLES USER_TAB_COMMENTS
ALL_UNUSED_COL_TABS DBA_TAB_COLS USER_TAB_HISTOGRAMS
CDB_ALL_TABLES DBA_TAB_COLUMNS USER_TAB_MODIFICATIONS
CDB_COL_COMMENTS DBA_TAB_COL_STATISTICS USER_TAB_PRIVS
CDB_PARTIAL_DROP_TABS DBA_TAB_COMMENTS USER_TAB_STATISTICS
CDB_TABLES DBA_TAB_HISTOGRAMS USER_TAB_STATS_HISTORY
CDB_TAB_COLS DBA_TAB_MODIFICATIONS USER_UNUSED_COL_TABS
CDB_TAB_COLUMNS    
Relational Table Types
Cluster One or more tables in a single database block
Compressed Compressed heap table
External External files readable as tables
Global Temporary Two different types depending
Heap Default Oracle table type
Index Organized Merger between a table and an index
Partitioned Partition/Subpartitioned by hash, range, or list
Relational Table and Column Clauses
Cache Clause Specify how the database should store blocks in the buffer cache
Deferred Segment Creation The initial table segment is created upon INSERT of the first row
Encryption Specification Tables utilizing the encryption clauses are referred to as Transparent Data Encryption so also use the link at page bottom
Evaluate Edition Clause Use this clause to specify the edition that is searched during name resolution of the editioned PL/SQL function—the evaluation edition
Flashback Archive Clause Specify to enable tracking for the table. You can specify flashback_archive to designate a particular flashback data archive for this table.
The flashback data archive you specify much already exist.
ILM Policy Clause Use this clause to describe an Automatic Data Optimization policy.
Invisible/Visible Clause Specifies whether a column will be visible during a describe operation
Logging Clause Specify if you want logging of all tables, indexes, and partitions within the tablespace. The tablespace-level logging attribute can be overridden by logging specifications at the table, index, and partition levels. It is always prefereable to do FORCE LOGGING at the database level.
Null / Not Null Clause Allows columns to be specfied as nullable or not nullable
Parallel Clause Specify PARALLEL if you want Oracle to select a degree of parallelism equal to the number of CPUs available on all participating instances times the value of the PARALLEL_THREADS_PER_CPU initialization parameter
Period Definition Use the period_definition clause to create a valid time dimension for table. This clause implements Temporal Validity support for table.
Physical Attributes Clause Specify physical attributes of a table
Row Dependencies Enable or disable row-level dependency tracking: Primary for parallel propagation in replication environments
Row Movement Clause Specifies whether the database can move a table row
Storage Clauses Specify physical storage of a table
Supplemental Logging The clause lets you instruct the database to put additional data into the log stream to support log-based replication tools.
Tiering Clause Specify this clause to migrate data to tablespace when the condition specified in the AFTER clause is met or when the PL/SQL function specified in the ON clause returns TRUE. If you specify READ ONLY, then tablespace is made read only after the data is migrated.
Unusable Editions Clause This clause lets you specify that the virtual column expression is unusable for evaluating queries in one or more editions. The remaining editions form a range of editions in which it is safe for the optimizer to use the virtual column expression to evaluate queries.
Virtual Column A non-stored column resulting from an explicit calculation possibly using a deterministic function.
Row Storage The format of a row is: row header, column length - value; column_length - value; column_length - value; ....

The length of a column is stored as an attribute in the row.

If the column name is "LAST_NAME" and the column is defined as CHAR(20) it is be stored as :20:Morgan--------------:

If the column name is "LAST_NAME" and the column is defined as VARCHAR2(20) it is stored as :6:Morgan:

Oracle starts adding rows from the end of the block towards the block header. In this way, the block header can grow if required.

To see the actual block and row as stored by Oracle use the DBMS_ROWID built-in package.

If you want to optimize access and improve performance create the table with those columns in order of how often they will need to be accessed rather than in the order in which you might fill out a paper form.
System Privileges
ALTER ANY TABLE DELETE ANY TABLE LOCK ANY TABLE
BACKUP ANY TABLE DROP ANY TABLE SELECT ANY TABLE
COMMENT ANY TABLE FLASHBACK ANY TABLE UNDER ANY TABLE
CREATE ANY TABLE INSERT ANY TABLE UPDATE ANY TABLE
CREATE TABLE    
 
Create Heap Table
Create Table With a Single Columns CREATE TABLE <table_name> (
<column_name>  <column_data_type>);
CREATE TABLE one_col (
last_name VARCHAR2(25));

desc one_col

desc user_tables

SELECT table_name, tablespace_name
FROM user_tables;

desc user_tab_columns  -- stop using this view ... here's why

desc user_tab_cols

SELECT column_id, column_name
FROM user_tab_cols
WHERE table_name = 'ONE_COL'
ORDER BY column_id;
Create Table With Multiple Columns CREATE TABLE <table_name> (
<column_name>  <column_data_type>,
<column_name>  <column_data_type>,
...);
CREATE TABLE multi_col (
pid   NUMBER(5),
fname VARCHAR2(20),
lname VARCHAR2(25)
);

desc multi_col

SELECT column_id, column_name
FROM user_tab_cols
WHERE table_name = 'MULTI_COL'
ORDER BY column_id;
Create table using a Select statement with data CREATE TABLE <table_name>
TABLESPACE <tablespace_name> AS
<select statement>;
CREATE TABLE ctas AS
SELECT
table_name, tablespace_name
FROM all_tables;

SELECT *
FROM ctas;
Create an empty table using a Select statement CREATE TABLE <table_name>
TABLESPACE <tablespace_name> AS
<select statement>
WHERE <Boolean Condition Is False>;
CREATE TABLE ctas_nodata AS
SELECT table_name, tablespace_name
FROM all_tables
WHERE 1=2;

SELECT *
FROM ctas_nodata;
 
Table Options
CACHE Use the CACHE clauses to indicate how Oracle Database should store blocks in the buffer cache. If you specify neither CACHE nor NOCACHE, then:
  • In a CREATE TABLE statement, NOCACHE is the default
  • In an ALTER TABLE statement, the existing value is not changed.
CACHE
For data that is accessed frequently, this clause indicates that the blocks retrieved for this table are placed at the most recently used end of the least recently used (LRU) list in the buffer cache when a full table scan is performed. This attribute is useful for small lookup tables.

You cannot specify CACHE for an index-organized table. However, index-organized tables implicitly provide CACHE behavior.

NOCACHE
For data that is not accessed frequently, this clause indicates that the blocks retrieved for this table are placed at the least recently used end of the LRU list in the buffer cache when a full table scan is performed. NOCACHE is the default for LOB storage.

As a parameter in the LOB_storage_clause, NOCACHE specifies that the LOB value either is not brought into the buffer cache or is brought into the buffer cache and placed at the least recently used end of the LRU list. The latter is the default behavior.


<CACHE | NOCACHE>
CREATE TABLE heap_cache (
testcol  VARCHAR2(20))
CACHE;

SELECT table_name, cache
FROM user_tables
WHERE table_name = 'HEAP_CACHE';

ALTER TABLE heap_cache NOCACHE;

SELECT table_name, cache
FROM user_tables
WHERE table_name = 'HEAP_CACHE';
CACHE READS Follow the link, at page bottom, to LOBs
Deferred Segment Creation

aka: Segment Creation On Demand
Deferred creation defers creating the segment until an insert statement is executed.

SEGMENT CREATION <IMMEDIATE | DEFERRED>
CREATE TABLE uwclass.now (
col1 NUMBER,
col2 VARCHAR2(20))
SEGMENT CREATION IMMEDIATE;

CREATE TABLE uwclass.later (
col1 NUMBER,
col2 VARCHAR2(20))
SEGMENT CREATION DEFERRED;

SELECT table_name, tablespace_name, segment_created
FROM user_tables
WHERE table_name IN ('LATER', 'NOW');

SELECT segment_name, tablespace_name
FROM user_segments
WHERE segment_name IN ('LATER', 'NOW');

INSERT INTO now (col1, col2) VALUES (1, 'A');
INSERT INTO later (col1, col2) VALUES (1, 'B');

SELECT segment_name, tablespace_name
FROM user_segments
WHERE segment_name IN ('LATER', 'NOW');
Encryption Specification -- valid algorithms are 3DES168, AES128, AES192, and AES256

USING '<encryption_algorithm>' IDENTIFIED BY <password> [NO] [SALT]
Follow the Transparent Data Encryption link at page bottom
Evaluate Edition Clause -- to use this clause the schema owner must be editions enabled and the function used to specify the virtual column editioned

CREATE TABLE [schema_name.]table_name(
<column_specification>
EVALUATE USING <CURRENT EDITION | EDITION <edition_name> | NULL EDITION>;
conn uwclass/uwclass@pdbdev

show edition

CREATE OR REPLACE FUNCTION evalValue(rid IN NUMBER) RETURN PLS_INTEGER AUTHID DEFINER DETERMINISTIC IS
BEGIN
  RETURN TO_NUMBER(SUBSTR(TO_CHAR(SYSDATE),rid,1));
END evalValue;
/

SELECT evalValue FROM dual;

CREATE TABLE eec (
rid NUMBER,
virtcol NUMBER AS (evalValue(rid))
EVALUATE USING CURRENT EDITION);

col evaluation_edition format a20

SELECT table_name, column_name, evaluation_edition
FROM user_tab_cols
WHERE table_name = 'EEC';
Flashback Archive FLASHBACK [ARCHIVE <flashback_archive>]
or
NO FLASHBACK ARCHIVE
See Flashback Archive link at page bottom
ILM Policy Clause 1 CREATE TABLE [schema_name.]table_name(
<column_specification>
TABLE COMPRESSION <GROUP | ROW | SEGMENT>
AFTER <integer> <DAY | DAYS | MONTH | MONTHS | YEAR | YEARS>
OF <CREATION | LOW ACCESS | NO ACCESS | NO MODIFICATION>;
TBD
ILM Policy Clause 2 CREATE TABLE [schema_name.]table_name(
<column_specification>
TABLE COMPRESSION <GROUP | ROW | SEGMENT>
ON <function_name>;
TBD
ILM Policy Clause 3 CREATE TABLE [schema_name.]table_name(
<column_specification>
<tiering clause> <GROUP | ROW | SEGMENT>
[AFTER <integer> <DAY | DAYS | MONTH | MONTHS | YEAR | YEARS>
OF <CREATION | LOW ACCESS | NO ACCESS | NO MODIFICATION]
TBD
ILM Policy Clause 4 CREATE TABLE [schema_name.]table_name(
<column_specification>
<tiering clause> <GROUP | ROW | SEGMENT>
ON <function_name>;
TBD
LOGGING Specify whether the creation of the table and of any indexes required because of constraints, partition, or LOB storage characteristics will be logged in the redo log file (LOGGING) or not (NOLOGGING). The logging attribute of the table is independent of that of its indexes.

This attribute also specifies whether subsequent direct loader (SQL*Loader) and direct-path INSERT operations against the table, partition, or LOB storage are logged (LOGGING) or not logged (NOLOGGING).


<LOGGING | NOLOGGING>
CREATE TABLE logging_test (
testcol  VARCHAR2(20))
LOGGING;

SELECT table_name, logging
FROM user_all_tables;

ALTER TABLE logging_test NOLOGGING;

SELECT table_name, logging
FROM user_all_tables;
PARALLEL Specify PARALLEL if you want Oracle to select a degree of parallelism equal to the number of CPUs available on all participating instances times the value of the PARALLEL_THREADS_PER_CPU initialization parameter. Specify NOPARALLEL, the default, for serial execution.

<PARALLEL | NOPARALLEL>

For this to be optimally effective the table should be distributed among multiple datafiles.
CREATE TABLE parallel_test (
testcol VARCHAR2(20))
PARALLEL 2;

SELECT table_name, degree
FROM user_tables;

set autotrace traceonly explain

SELECT * FROM parallel_test;

set autotrace off

ALTER TABLE parallel_test PARALLEL 4;

SELECT table_name, degree
FROM user_tables;

set autotrace traceonly explain

SELECT * FROM parallel_test;

CREATE TABLE parallel_test (
testcol VARCHAR2(20))
PARALLEL;

SELECT table_name, degree
FROM user_tables;
Period Definition -- this clause is new in 12c and supports Temporal Validity. Further demos can be seen on the Temporal Validity page linked at page bottom.

CREATE TABLE [schema_name.]table_name(
<column_specification);

ALTER TABLE <table_name> PERIOD FOR <valid_time_column> [(<start_time_column>, <end_time_column>];
CREATE TABLE perDef(
rid  NUMBER,
dob1 DATE,
dob2 DATE);

SELECT column_name, hidden_column
FROM user_tab_cols
WHERE table_name = 'PERDEF'
ORDER BY column_id;

ALTER TABLE perDef ADD PERIOD FOR track_time(dob1, dob2);

SELECT column_name, hidden_column
FROM user_tab_cols
WHERE table_name = 'PERDEF'
ORDER BY column_id;
ROWDEPENDENCIES This clause lets you specify whether table will use row-level dependency tracking. With this feature, each row in the table has a system change number (SCN) that represents a time greater than or equal to the commit time of the last transaction that modified the row. This setting cannot be changed after table creation.

<ROWDEPENDENCIES | NOROWDEPENDENCIES>
CREATE TABLE rowdep_test (
testcol  VARCHAR2(20))
ROWDEPENDENCIES;

SELECT table_name, dependencies
FROM user_tables;

-- Not alterable after table creation. Follow the ORA_ROWSCN link at page bottom for more information
Row Movement The row_movement_clause specifies whether the database can move a table row. It is possible for a row to move, for example, during table compression or an update operation on partitioned data. The default is to disable row movement.

<ENABLE | DISABLE> ROW MOVEMENT
CREATE TABLE rowmove_test (
testcol  VARCHAR2(20))
ENABLE ROW MOVEMENT;

SELECT table_name, row_movement
FROM user_tables;

ALTER TABLE rowmove_test DISABLE ROW MOVEMENT;

SELECT table_name, row_movement
FROM user_tables;
Supplemental ID Key Logging Clause DATA (<ALL | PRIMARY KEY | UNIQUE | FOREIGN KEY>) COLUMNS
CREATE TABLE sup_log1 (
pid   NUMBER(5),
fname VARCHAR2(20),
lname VARCHAR2(25),
SUPPLEMENTAL LOG DATA (ALL) COLUMNS);

conn / as sysdba

SELECT object_id
FROM dba_objects_ae
WHERE owner = 'UWCLASS'
AND object_name = 'SUP_LOG1';

SELECT type#
FROM cdef$
WHERE obj# = 74097;

cdef$ information from dcore.sql

type# number not null, /* constraint type: */
/* 1 = table check, 2 = primary key, 3 = unique, */
/* 4 = referential, 5 = view with CHECK OPTION, */
/* 6 = view READ ONLY check */
/* 7 - table check constraint associated with column NOT NULL */
/* 8 - hash expressions for hash clusters */
/* 9 - Scoped REF column constraint */
/* 10 - REF column WITH ROWID constraint */
/* 11 - REF/ADT column with NOT NULL const */
/* 12 - Log Groups for supplemental logging */
/* 14 - Primary key supplemental logging */
/* 15 - Unique key supplemental logging */
/* 16 - Foreign key supplemental logging */
/* 17 - All column supplemental logging */
Tiering CREATE TABLE [schema_name.]table_name(
<column_specification>
TIER TO <tablespace_name>  [READ ONLY];
TBD
Unusable Editions Clause Synax 1 CREATE TABLE [schema_name.]table_name(
<column_specification>
UNUSABLE BEFORE <CURRENT EDITION | EDITION <edition_name>;
conn uwclass/uwclass@pdbdev

show edition

CREATE OR REPLACE FUNCTION evalValue(rid IN NUMBER) RETURN PLS_INTEGER AUTHID DEFINER DETERMINISTIC IS
BEGIN
  RETURN TO_NUMBER(SUBSTR(TO_CHAR(SYSDATE),rid,1));
END evalValue;
/

SELECT evalValue FROM dual;

CREATE TABLE uec1 (
rid NUMBER,
virtcol NUMBER AS (evalValue(rid))
UNUSABLE BEFORE EDITION ora$base);

col unusable_before format a20
col unusable_beginning format a20

SELECT table_name, column_name, unusable_before, unusable_beginning
FROM user_tab_cols
WHERE table_name LIKE 'UEC%';
Unusable Editions Clause Synax 2 CREATE TABLE [schema_name.]table_name(
<column_specification>
UNUSABLE BEGINNING WITH <CURRENT EDITION | EDITION <edition_name> | NULL EDITION>;
conn uwclass/uwclass@pdbdev

show edition

CREATE OR REPLACE FUNCTION evalValue(rid IN NUMBER) RETURN PLS_INTEGER AUTHID DEFINER DETERMINISTIC IS
BEGIN
  RETURN TO_NUMBER(SUBSTR(TO_CHAR(SYSDATE),rid,1));
END evalValue;
/

SELECT evalValue FROM dual;

CREATE TABLE uec2 (
rid NUMBER,
virtcol NUMBER AS (evalValue(rid))
UNUSABLE BEGINNING WITH CURRENT EDITION);

col unusable_before format a20
col unusable_beginning format a20

SELECT table_name, column_name, unusable_before, unusable_beginning
FROM user_tab_cols
WHERE table_name LIKE 'UEC%';
 
Physical Attributes Clauses
INITRANS Specifies the number of DML transaction entries for which space is initially reserved in the data block header. Space is reserved in the headers of all data blocks in the associated segment.

Oracle uses control information stored in the data block to indicates which rows in the block contain committed and uncommitted changes. In a sense, the block contains a recent history of transactions that affected each row in the block. The amount of history that is retained is controlled by the INITRANS parameter of CREATE TABLE and ALTER TABLE.

Under some circumstances, Oracle can have insufficient history information to determine whether a row has been updated by a "too recent" transaction. This can occur when many transactions concurrently modify the same data block, or do so in a very short period. You can avoid this situation by setting higher values of INITRANS for tables that will experience many transactions updating the same blocks. Doing so enables Oracle to allocate sufficient storage in each block to record the history of recent transactions that accessed the block.


INITRANS <integer>
SELECT table_name, ini_trans
FROM user_tables;
PCTFREE Determines when a used block is removed from the list of available blocks. When a block is removed from the list ... no more data is written to it so that when records are updated there is room for the data in the block ... thus no chained rows.

Tables on which there are no updates should have PCTFREE set to 0. The default value of 10 leaves 90% of each block empty.


PCTFREE <integer>
SELECT table_name, pct_free
FROM user_all_tables;
PCTUSED Determines when a used block is re-added to the list of available blocks. When deletes take place and the room available in a block falls below this value ... the block is made available for new inserts to take place.

Tables on which there are no updates should have PCTUSED set to 99. The default value is 40% which means that blocks are available for insertion when they are less than 40% full.


PCTUSED <integer>
SELECT table_name, pct_used
FROM user_all_tables;
TABLESPACE LOGGING TABLESPACE <tablespace_name> <LOGGING | NOLOGGING>;
CREATE TABLE force_logging (
rid   NUMBER,
lname VARCHAR2(30))
TABLESPACE uwdata LOGGING;
 
Storage Clauses
BUFFER POOL Defines a default buffer pool (cache) for a schema object.

<KEEP | RECYCLE | DEFAULT>
CREATE TABLE buffer_test (
testcol  VARCHAR2(20))
STORAGE (buffer_pool DEFAULT);

SELECT table_name, buffer_pool
FROM user_tables;

ALTER TABLE buffer_test STORAGE (buffer_pool RECYCLE);

SELECT table_name, buffer_pool
FROM user_tables;

ALTER TABLE buffer_test STORAGE (buffer_pool KEEP);

SELECT table_name, buffer_pool
FROM user_tables;

-- for additional information click on the Buffer Pools link at page bottom
FLASH_CACHE Allows an override of the automatic buffer cache policy and specifcation of how specific schema objects are cached in flash memory

FLASH_CACHE <DEFAULT | KEEP | NONE>
CREATE TABLE fcache(
testcol VARCHAR2(20))
STORAGE (FLASH_CACHE DEFAULT);
FREELISTS The number of lists maintained on a table that can be used to identify a block available for insert. Set this to 1 on all tables except those receiving very large numbers of simultaneous inserts. When a process requests a free list, it uses a 'hashing' function to select which free list based on the process id. Using a prime number with such mechanisms usually reduces the number of collisions that occur if the input is randomly distributed. Therefore, if you need more than one free list make the number of lists a prime number (for example 1, 2, 3, 5, 7, 11, 13, 17, 19, 23, .... for optimal performance).

Oracle ignores a setting of FREELISTS if the tablespace in which the object resides is in automatic segment-space management mode.


FREELISTS <1 | integer>
SELECT table_name, freelists
FROM user_tables;
FREELIST GROUPS The number of groups of free lists for the database object you are creating. The database uses the instance number of Oracle Real Application Cluster instances to map each instance to one free list group.

This parameter is ignored for objects created in locally managed tablespaces with segment space management specified as AUTO.


FREELIST GROUPS <1 | integer>
SELECT table_name, freelist_groups
FROM user_tables;
INITIAL In a tablespace that is specified as EXTENT MANAGEMENT LOCAL. The database uses the value of INITIAL in conjunction with the extent size for the tablespace to determine the initial amount of space to reserve for the object. For example, in a uniform locally managed tablespace with 5M extents, if you specify an INITIAL value of 1M, then the database must allocate one 5M extent, because that is the uniform size of extents for the tablespace. If the extent size of the tablespace is smaller than the value of INITIAL, then the initial amount of space allocated will in fact be more than one extent.

INITIAL <integer> <K | M | G | T | P | E>
SELECT tablespace_name, initial_extent
FROM user_tablespaces

SELECT table_name, tablespace_name, initial_extent
FROM user_tables;
MAXEXTENTS The maximum number of extents that can be allocated to the segment.

MAXEXTENTS <integer>
SELECT table_name, max_extents
FROM user_all_tables;
MAXSIZE Defines the maximum size of a table in bytes.

MAXSIZE < integer <K | M | G | T | P | E> | UNLIMITED>
CREATE TABLE msize(
testcol VARCHAR2(20))
STORAGE(MAXSIZE 10G) CACHE;
MINEXTENTS The total number of extents to be allocated when the segment is created. This allows for a large allocation of space at creation time, even if contiguous space is not available.

In a tablespace that is specified as EXTENT MANAGEMENT LOCAL, MINEXTENTS is used only to compute the initial amount of space that is allocated. The initial amount of space that is allocated and is equal to INITIAL * MINEXTENTS. Thereafter it is set to 1 for these tablespaces (as seen in the DBA_SEGMENTS view).


MINEXTENTS <integer>
SELECT table_name, min_extents
FROM user_all_tables;
NEXT Not meaningful for objects created in a tablespace that is specified as EXTENT MANAGEMENT LOCAL because the database automatically manages extents.

NEXT <integer> <K | M | G | T | P | E>
SELECT tablespace_name, next_extent
FROM user_tablespaces

SELECT table_name, tablespace_name, next_extent
FROM user_all_tables;
PCTINCREASE The default is zero and it should be left that way. Using alternate values back in Oracle 8.0 and before was always a bad idea but unfortunately back then that didn't stop a lot of people from setting other values.

PCTFREE <0 | integer>
SELECT table_name, pct_increase
FROM user_tables;
TABLESPACE The name of the tablespace where the table will be built. The table may exist in one or more the the datafiles mapped to the tablespace.

TABLESPACE <tablespace_name>
or
TABLESPACE <tablespace_group_name>
SELECT tablespace_name, max_bytes, max_blocks
FROM user_ts_quotas;

CREATE TABLE tbsp_test (
testcol VARCHAR2(20))
TABLESPACE users;

SELECT table_name, tablespace_name
FROM user_tables
ORDER BY 1;

ALTER TABLE tbsp_test MOVE TABLESPACE uwdata;

SELECT table_name, tablespace_name
FROM user_tables
ORDER BY 1;

CREATE TABLE ctas2
TABLESPACE uwdata AS
SELECT * FROM all_tables;
 
Column Options
Column Defaults -- the value inserted into the column if the insert or update would leave the column value NULL. In 12c this can include a sequence generated surrogate key

<DEFAULT <value> | NULL>
CREATE TABLE default_test (
active     VARCHAR2(1) DEFAULT 'Y',
created_by VARCHAR2(30) DEFAULT USER,
created_on TIMESTAMP DEFAULT SYSTIMESTAMP);

set long 100000
set linesize 121
col data_default format a50

SELECT column_name, data_default
FROM user_tab_cols
WHERE table_name = 'DEFAULT_TEST';

ALTER TABLE default_test MODIFY (active DEFAULT 'N');

SELECT column_name, data_default
FROM user_tab_cols
WHERE table_name = 'DEFAULT_TEST';

ALTER TABLE default_test MODIFY (active DEFAULT NULL);

SELECT column_name, data_default
FROM user_tab_cols
WHERE table_name = 'DEFAULT_TEST';

INSERT INTO default_test
(active)
VALUES
('X');

SELECT * FROM default_test;

INSERT INTO default_test
(active, created_by)
VALUES
('Y', 'Morgan');

SELECT * FROM default_test;

UPDATE default_test
SET created_by = DEFAULT;

SELECT * FROM default_test;
IDENTITY See IDENTITY COLUMN Link At Page Bottom
Invisible / Visible CREATE TABLE [schema_name.]table_name(
<column_specification [<INVISIBLE | VISIBLE>);
CREATE TABLE vis (
rid     NUMBER,
testcol VARCHAR2(20));

CREATE TABLE invis (
rid     NUMBER,
testcol VARCHAR2(20) INVISIBLE);

desc vis

desc invis

SELECT table_name, column_name, data_upgraded, hidden_column
FROM user_tab_cols
WHERE table_name like '%VIS';
Create Table With NOT NULL Constraints CREATE TABLE <table_name>
<column_name>  <column_data_type> NOT NULL,
<column_name>  <column_data_type>);
CREATE TABLE nn_test (
pid   NUMBER(5) NOT NULL,
fname VARCHAR2(20),
lname VARCHAR2(25));

desc nn_test

SELECT column_id, nullable
FROM user_tab_cols
WHERE table_name = 'NN_TEST'
ORDER BY column_id;

ALTER TABLE nn_test MODIFY (pid NULL);

desc nn_test

SELECT column_id, nullable
FROM user_tab_cols
WHERE table_name = 'NN_TEST'
ORDER BY column_id;

ALTER TABLE nn_test MODIFY (pid NOT NULL);

SELECT column_id, nullable
FROM user_tab_cols
WHERE table_name = 'NN_TEST'
ORDER BY column_id;
Virtual Column <column_name> [<data_type>] [GENERATED ALWAYS] AS (column_expression)
VIRTUAL (inline_constraint)

Note: "GENERATED ALWAYS" and "VIRTUAL" are optional keywords. For an example of a virtual column based on a deterministic function see the Evaluate Edition Clause above.
CREATE TABLE vcol (
salary     NUMBER(8),
bonus      NUMBER(3),
total_comp NUMBER(10) GENERATED ALWAYS AS (salary+bonus) VIRTUAL);

desc vcol

col data_type format a30
col data_default format a30
set long 100000

desc user_tab_columns -- stop using this view ... here's why

desc user_tab_cols

SELECT column_name, data_type, virtual_column, data_default
FROM user_tab_cols
WHERE table_name = 'VCOL';

INSERT into vcol
(salary, bonus, total_comp)
VALUES
(100, 10, 110);

INSERT into vcol
(salary, bonus)
VALUES
(100, 10);

SELECT * FROM vcol;

DROP TABLE vcol PURGE;

CREATE TABLE vcol (
salary     NUMBER(8),
bonus      NUMBER(3),
total_comp NUMBER(10) GENERATED ALWAYS AS (salary+bonus));

DROP TABLE vcol PURGE;

CREATE TABLE vcol (
salary     NUMBER(8),
bonus      NUMBER(3),
total_comp NUMBER(10) AS (salary+bonus));

ALTER TABLE vcol
ADD CONSTRAINT cc_vcol_total_comp
CHECK (total_comp < 50001);

INSERT into vcol
(salary, bonus)
VALUES
(100, 10);

INSERT into vcol
(salary, bonus)
VALUES
(200, 12);

COMMIT;

INSERT into vcol
(salary, bonus)
VALUES
(50000, 1);

SELECT * FROM vcol;

EXPLAIN PLAN FOR
SELECT * FROM vcol;

SELECT * FROM TABLE(dbms_xplan.display);

EXPLAIN PLAN FOR
SELECT /*+ RESULT_CACHE */ * FROM vcol;

SELECT * FROM TABLE(dbms_xplan.display);

ALTER TABLE vcol
ADD CONSTRAINT pk_vcol
PRIMARY KEY (salary)
USING INDEX;

CREATE INDEX ix_virtual_column
ON vcol(total_comp);

SELECT index_name, index_type
FROM user_indexes
WHERE table_name = 'VCOL';

col column_name format a30

SELECT column_name, column_position, column_length
FROM user_ind_columns
WHERE table_name = 'VCOL';

BEGIN
  FOR i IN 1 .. 20000 LOOP
    BEGIN
      INSERT INTO vcol
      (salary, bonus)
      VALUES
      (i, TRUNC(MOD(i, 5)));
    EXCEPTION
      WHEN OTHERS THEN
        NULL;
    END;
  END LOOP;
  COMMIT;
END;
/

exec dbms_stats.gather_index_stats(USER, 'PK_VCOL');
exec dbms_stats.gather_index_stats(USER, 'IX_VIRTUAL_COLUMN');

desc user_ind_statistics

SELECT index_name, object_type, blevel, leaf_blocks, distinct_keys, clustering_factor
FROM user_ind_statistics
WHERE table_name = 'VCOL';
 
ALTER TABLE Statements
MOVE ALTER TABLE <table_name> MOVE TABLESPACE <new_tablespace_location>;
SELECT segment_type, tablespace_name, blocks
FROM dba_extents
WHERE segment_name = 'MGMT_JOB_STATE_CHANGES';

ALTER TABLE sysman.mgmt_job_state_changes MOVE TABLESPACE sysaux;

SELECT segment_type, tablespace_name, blocks
FROM dba_extents
WHERE segment_name = 'MGMT_JOB_STATE_CHANGES';
READ ONLY READ ONLY
CREATE TABLE readonly (
testcol VARCHAR2(20))
READ ONLY;
-- why did this fail?

CREATE TABLE readonly
READ ONLY AS
SELECT * FROM servers;
-- why did this fail too?

CREATE TABLE readonly (
testcol VARCHAR2(20));

INSERT INTO readonly (testcol) VALUES ('Morgan');

ALTER TABLE readonly READ ONLY;

SELECT table_name, read_only
FROM user_tables
ORDER BY 2;

INSERT INTO readonly (testcol) VALUES ('Morgan');

tab$ information from dcore.sql

trigflag number, /* first two bytes for trigger flags, the rest for */
/* general use, check tflags_kqldtvc in kqld.h for detail */
/* 0x00000001 deferred RPC Queue */
/* 0x00000002 snapshot log */
/* 0x00000004 updatable snapshot log */
/* 0x00000008 = context trigger */
/* 0x00000010 = synchronous change table */
/* 0x00000020 = Streams trigger */
/* 0x00000040 = Content Size Trigger */
/* 0x00000080 = audit vault trigger */
/* 0x00010000 = server-held key encrypted columns exist */
/* 0x00020000 = user-held key encrypted columns exist */
/* 0x00200000 = table is read only */
/* 0x00400000 = lobs use shared segment */
/* 0x00800000 = queue table */
/* 0x10000000 = streams unsupported table */
/* enabled at some point in past */
/* 0x80000000 = Versioning enabled on this table */
TABLE LOCK

Prevent and re-enable DDL on a table
ALTER TABLE <table_name> DISABLE TABLE LOCK;
CREATE TABLE tl_test (
col1 VARCHAR2(20));

desc tl_test

SELECT table_name, table_lock
FROM user_all_tables
ORDER BY 2;

ALTER TABLE tl_test DISABLE TABLE LOCK;

SELECT table_name, table_lock
FROM user_all_tables
ORDER BY 2;

ALTER TABLE tl_test ADD (col2 VARCHAR2(20));

TRUNCATE TABLE tl_test;

DROP TABLE tl_test PURGE;

ALTER TABLE tl_test ENABLE TABLE LOCK;

SELECT table_name, table_lock
FROM user_all_tables
ORDER BY 2;

TRUNCATE TABLE tl_test;

DROP TABLE tl_test PURGE;
 
Commenting Tables and Columns
Comment a table COMMENT ON TABLE <table_name> IS '<comment_string>';
COMMENT ON TABLE zip_code IS 'US Postal Service Zip Codes';

SELECT table_name, comments
FROM user_tab_comments;
Comment a column COMMENT ON COLUMN <table_name.column_name> IS '<comment>';
COMMENT ON COLUMN zip_code.zip_code IS '5 Digit Zip Code';

SELECT table_name, column_name, comments
FROM user_col_comments;
 
Compressed Table
COMPRESSED The table_compression clause is valid only for heap-organized tables. Use this clause to instruct the database whether to compress data segments to reduce disk use. This clause is especially useful in environments such as data warehouses, where the amount of insert and update operations is small. The COMPRESS keyword enables table compression. The NOCOMPRESS keyword disables table compression. NOCOMPRESS is the default.

When you enable table compression, Oracle Database attempts to compress data during direct-path INSERT operations when it is productive to do so. The original import utility (imp) does not support direct-path INSERT, and therefore cannot import data in a compressed format. You can specify table compression for the following portions of a heap-organized table.
  • For an entire table, in the physical_properties clause of relational_table or object_table
  • For a range partition, in the table_partition_description of the range_partitioning clause
  • For a list partition, in the table_partition_description of the list_partitioning clause
  • For the storage table of a nested table, in the nested_table_col_properties clause
Table compression saves disk space and reduces memory use in the buffer cache, and is completely transparent to applications. Compression ratios as high as 3.5 : 1 can be achieved. Table compression can also speed up query execution during reads. There is, however, a cost in CPU overhead for DML.
Create a table in a compressed tablespace CREATE TABLESPACE ...
<NOCOMPRESS | COMPRESS>;
conn sys@pdbdev as sysdba

CREATE TABLESPACE compressed
DATAFILE 'compressed.dbf' SIZE 5M
DEFAULT COMPRESS;

SELECT tablespace_name, def_tab_compression
FROM dba_tablespaces;

ALTER USER uwclass
QUOTA unlimited ON compressed;

conn uwclass/uwclass@pdbdev

CREATE TABLE regtab
TABLESPACE uwdata AS
SELECT * FROM all_objects;

CREATE TABLE comptab
TABLESPACE compressed AS
SELECT * from all_objects;

SELECT table_name, tablespace_name, compression
FROM user_tables
WHERE table_name IN ('REGTAB', 'COMPTAB');

exec dbms_stats.gather_table_stats(USER, 'REGTAB');
exec dbms_stats.gather_table_stats(USER, 'COMPTAB');

SELECT table_name, blocks
FROM user_tables
WHERE table_name IN ('REGTAB', 'COMPTAB');

conn sys@pdbdev as sysdba

DROP TABLESPACE compressed INCLUDING CONTENTS AND DATAFILES;
Compressed Table CREATE TABLE ...
COMPRESS;
conn uwclass/uwclass@pdbdev

CREATE TABLE regtab
TABLESPACE uwdata AS
SELECT * FROM all_objects;

CREATE TABLE comptab
TABLESPACE uwdata COMPRESS AS
SELECT * FROM all_objects;

SELECT table_name, tablespace_name, compression
FROM user_tables
WHERE table_name IN ('REGTAB', 'COMPTAB');

exec dbms_stats.gather_table_stats(USER, 'REGTAB');
exec dbms_stats.gather_table_stats(USER, 'COMPTAB');

SELECT table_name, blocks
FROM user_tables
WHERE table_name IN ('REGTAB', 'COMPTAB');
Compressed Direct Load CREATE TABLE ...
COMPRESS FOR DIRECT_LOAD OPERATIONS;
CREATE TABLE regtab
TABLESPACE uwdata AS
SELECT /*+ APPEND */ *
FROM all_objects;

CREATE TABLE comptab
TABLESPACE uwdata COMPRESS FOR DIRECT_LOAD OPERATIONS AS
SELECT /*+ APPEND */ *
FROM all_objects;

SELECT table_name, tablespace_name, compression
FROM user_tables
WHERE table_name IN ('REGTAB', 'COMPTAB');

exec dbms_stats.gather_table_stats(USER, 'REGTAB');
exec dbms_stats.gather_table_stats(USER, 'COMPTAB');

SELECT table_name, blocks
FROM user_tables
WHERE table_name IN ('REGTAB', 'COMPTAB');
Compressed Table Demo CREATE TABLE t1 (
testcol VARCHAR2(50))
TABLESPACE uwdata;

CREATE TABLE t2 (
testcol VARCHAR2(50))
TABLESPACE uwdata COMPRESS;

DECLARE
 x t1.testcol%TYPE;
BEGIN
  FOR i IN 1 .. 100000 LOOP
    SELECT dbms_crypto.randombytes(25)
    INTO x
    FROM dual;

    INSERT INTO t1 VALUES (x);
    INSERT INTO t2 VALUES (x);
  END LOOP;
  COMMIT;
END;
/

-- some sample rows
3605CAA721159CAC4E462B841419CCB7390F1AE3484FF14963
05B7AE0B6BB076EEAF3E8E7DBA1BE9D5C8F97737AA1FDF21A5
40756BCEBF00CCB80ACA5F4F6BF3AFE6BC19D19EA74F10212B
234812A15930421A208BCF19C943762B5FA11D0C0C7E811F5E
4177AFC94C248D6B6765B8CE45FE3E49E2E5456BA6BA48C147

exec dbms_stats.gather_table_stats(USER, 'T1');
exec dbms_stats.gather_table_stats(USER, 'T2');

SELECT table_name, blocks
FROM user_tables
WHERE table_name IN ('T1', 'T2');
 
Alter Table Column Clauses
Add a new column ALTER TABLE <table_name>
MODIFY (<field_name data_type>);
CREATE TABLE test (
first_col VARCHAR2(20));

desc test

ALTER TABLE test ADD (second_col NUMBER(20));

desc test
Add more than one new column ALTER TABLE <table_name> MODIFY (<field_name data_type>, <field_name data type>);
ALTER TABLE test ADD (third_col DATE, fourth_col VARCHAR2(3));

desc test
Rename a column ALTER TABLE <table_name> RENAME COLUMN <current_name> TO <new_name>;
ALTER TABLE test RENAME COLUMN third_col TO date_col;

desc test
Rename a table RENAME <current_table_name> TO <new_name>;
CREATE TABLE old_name (
test  VARCHAR2(20));

SELECT table_name
FROM user_tables
ORDER BY 1;

RENAME old_name TO new_name;

SELECT table_name
FROM user_tables
ORDER BY 1;
Drop a column of a small to medium sized table ALTER TABLE <table_name> DROP COLUMN <column_name>;
ALTER TABLE test DROP COLUMN fourth_col;

desc test
Drop a column of a large table ALTER TABLE <table_name>
DROP COLUMN <column_name>
CHECKPOINT <integer>;
ALTER TABLE test DROP COLUMN fourth_col CHECKPOINT 1000;
Set a column as unused ALTER TABLE <table_name> SET UNUSED COLUMN <column_name>;
ALTER TABLE test SET UNUSED COLUMN second_col;

desc test

SELECT *
FROM user_unused_col_tabs;
Drop an unused column ALTER TABLE <table_name> DROP UNUSED COLUMNS;
ALTER TABLE test DROP UNUSED COLUMNS;

desc test
Drop unused columns in a very large table ALTER TABLE <table_name>
DROP UNUSED COLUMNS
CHECKPOINT <integer>;
ALTER TABLE test DROP UNUSED COLUMNS CHECKPOINT 250;

desc test
Alter table change data type ALTER TABLE <table_name> MODIFY (<column_name new_data_type);
CREATE TABLE dt_test (
test_col VARCHAR2(20));

desc dt_test

ALTER TABLE dt_test MODIFY (test_col NUMBER(6));

desc dt_test

-- in most cases a column must be empty to change the data type
Alter table change data type of multiple columns ALTER TABLE <table_name>
MODIFY (<column_name> <data_type>,
        <column_name> <data_type>);
CREATE TABLE mcdt_test (
col_one NUMBER(10),
col_two VARCHAR2(10),
dat_col DATE);

DESC mcdt_test

ALTER TABLE mcdt_test
MODIFY
(col_one NUMBER(12), col_two VARCHAR2(20));

desc mcdt_test
 
Alter Table Space Storage Clauses
Force Extent Allocation ALTER TABLE <table_name> ALLOCATE EXTENT;
ALLOCATE EXTENT [(
{ SIZE size_clause | DATAFILE 'filename' | INSTANCE integer }
[ SIZE size_clause | DATAFILE 'filename' | INSTANCE integer ]...)];
CREATE TABLE allo_test (
testcol VARCHAR2(20));

col segment_name format a30

SELECT segment_name, extents, blocks
FROM user_segments
HERE segment_name = 'ALLO_TEST';

ALTER TABLE allo_test ALLOCATE EXTENT;

SELECT segment_name, extents, blocks
FROM user_segments
HERE segment_name = 'ALLO_TEST';

ALTER TABLE allo_test ALLOCATE EXTENT
(SIZE 1M INSTANCE 1)
;

SELECT segment_name, extents, blocks
FROM user_segments
HERE segment_name = 'ALLO_TEST';
Deallocate Unused Space ALTER TABLE <table_name> DEALLOCATE UNUSED [KEEP <integer>];
ALTER TABLE allo_test DEALLOCATE UNUSED;

SELECT segment_name, extents, blocks
FROM user_segments
HERE segment_name = 'ALLO_TEST';
Shrink Space Valid only for segments in tablespaces with automatic segment management. Row movement must be enabled. COMPACT defragments the segment space and compacts the table rows for subsequent release. COMPACT does not readjust the high water mark and does not release the space immediately. CASCADE performs the same operations on all dependent objects.

ALTER TABLE <table_name> SHRINK SPACE [COMPACT] [CASCADE];
CREATE TABLE shrink_test (
rid      NUMBER(5),
testcol  VARCHAR2(20))
ENABLE ROW MOVEMENT;

SELECT bid, count(*)
FROM (
  SELECT dbms_rowid.rowid_block_number(rowid) BID
  FROM shrink_test)
GROUP BY bid;

BEGIN
  FOR i IN 1..40000
  LOOP
    INSERT INTO shrink_test (rid, testcol)
    VALUES (i, 'ABCDEFGHIJKLMNOPQRST');
  END LOOP;
  COMMIT;
END;
/

SELECT COUNT(*)
FROM shrink_test;

SELECT bid, count(*)
FROM (
  SELECT dbms_rowid.rowid_block_number(rowid) BID
  FROM shrink_test)
GROUP BY bid;

DELETE FROM shrink_test WHERE mod(rid, 2) = 0;
COMMIT;

SELECT COUNT(*)
FROM shrink_test;

SELECT bid, count(*)
FROM (
  SELECT dbms_rowid.rowid_block_number(rowid) BID
  FROM shrink_test)
GROUP BY bid;

ALTER TABLE shrink_test SHRINK SPACE COMPACT CASCADE;

SELECT bid, COUNT(*)
FROM (
  SELECT dbms_rowid.rowid_block_number(rowid) BID
  FROM shrink_test)
GROUP BY bid;
Control the Number of Records per Block for bitmap indexes This clause ensures that any bitmap indexes subsequently created on the table will be as compressed as possible. It cannot be specify MINIMIZE or NOMINIMIZE if a bitmap index has already been defined on table or if the table is empty.

ALTER TABLE <table_name> MINIMIZE RECORDS_PER_BLOCK;
ALTER TABLE test MINIMIZE RECORDS_PER_BLOCK;
Release Control on the Number of Records Per Block ALTER TABLE <table_name> NOMINIMIZE RECORDS_PER_BLOCK;
ALTER TABLE test NOMINIMIZE RECORDS_PER_BLOCK;
 
Drop Table
Drop Table into the Recycle Bin DROP TABLE <table_name>;
DROP TABLE zip_code;
Drop Table and bypass the Recycle Bin DROP TABLE <table_name> PURGE;
DROP TABLE zip_code PURGE;
Drop Table Including Referential Constraints DROP TABLE <table_name> CASCADE CONSTRAINTS;
DROP TABLE work_note_header CASCADE CONSTRAINTS PURGE;
 
Miscellaneous
Maximum number of columns Oracle documentation states that a table can contain as many as 1000 columns. No sane person should ever build one 1/10th that size and certainly never with more than 255 columns. The truth is that no table really can contain 1000 columns. Oracle does a bit of sleight of hand behind the scenes to make it appear that a single table contains the large number of columns and you and your application will pay a horrendous price in performance.

Here is another reason to severely limit the number of columns in any table.

* Oracle stores columns in variable length format
* Each row is parsed in order to retrieve one or more columns
* Each subsequently parsed column introduces a cost of 20 CPU cycles whether or not it is used
Slow table reads The init parameter db_file_multiblock_read_count is paramount
12c Maximum Sring Size Enhancement

Note: This is a one-way street. Once you perform this ALTER SYSTEM you can not undo it
show parameter max_string_size

CREATE TABLE new_feature(
vcol  VARCHAR2(32767),
nvcol NVARCHAR2(16383),
rcol  RAW(32767));

ALTER SYSTEM SET max_string_size = EXTENDED SCOPE=SPFILE;

shutdown immediate;

startup;

CREATE TABLE new_feature(
vcol  VARCHAR2(32767),
nvcol NVARCHAR2(16383),
rcol  RAW(32767));

desc new_feature
 
Table Related Queries
How much space is a table taking in the tablespace? SELECT SUBSTR(s.segment_name,1,20) TABLE_NAME,
SUBSTR(s.tablespace_name,1,20) TABLESPACE_NAME,
ROUND(DECODE(s.extents, 1, s.initial_extent,
(s.initial_extent + (s.extents-1) * s.next_extent))/1024000,2) ALLOCATED_MB,
ROUND((t.num_rows * t.avg_row_len / 1024000),2) REQUIRED_MB
FROM dba_segments s, dba_tables t
WHERE s.owner = t.owner
AND s.segment_name = t.table_name
ORDER BY s.segment_name;
Another space usage query SELECT owner, table_name, NVL(num_rows*avg_row_len,0)/1024000 MB
FROM dba_tables
ORDER BY owner, table_name;

Related Topics
Analyze
Buffer Pools
Clusters
Constraints
Data Types & Subtypes
DBMS_REDEFINITION
DBMS_RESULT_CACHE
DBMS_ROWID
DBMS_SHARED_POOL
DBMS_STATS
DDL Statements
External Tables
Flashback Archive
Global Temporary Tables
Identity Columns
Indexes
IOT (Index Organized Tables)
LOBs
Nested Tables
Object Privileges
Object Tables
ORA_ROWSCN
Partitioned Tables
Pseudocolumns
Recycle Bin
Result Cache
Table Flashback
Temporal Validity
Transparent Data Encryption
Triggers
Truncate
XMLType Tables

Morgan's Library Page Footer
This site is maintained by Dan Morgan. Last Updated: This site is protected by copyright and trademark laws under U.S. and International law. © 1998-2014 Daniel A. Morgan All Rights Reserved