Anda di halaman 1dari 54

System and Object Privileges

Learning objective

After completing this topic, you should be able to identify the steps for granting and
revoking system and object privileges.

1. Introducing privileges
Disclaimer
Although certain aspects of Oracle Database 11g are case and spacing insensitive, a
common coding convention has been used throughout all aspects of this course.
This convention uses lowercase characters for schema, role, user, and constraint names,
and for permissions, synonyms, and table names (with the exception of the DUAL table).
Lowercase characters are also used for column names and user-defined procedure,
function, and variable names shown in code.
Uppercase characters are used for Oracle keywords and functions, for view, table,
schema, and column names shown in text, for column aliases that are not shown in
quotes, for packages, and for data dictionary views.
The spacing convention requires one space after a comma and one space before and
after operators that are not Oracle-specific, such as +, -, /, and <. There should be no
space between an Oracle-specific keyword or operator and an opening bracket, a closing
bracket and a comma, between the last part of a statement and the closing semicolon, or
before a statement.
String literals in single quotes are an exception to all convention rules provided. Please
use this convention for all interactive parts of this course.
-----------------------------------------------------------------------------------------------------------In a multiple-user environment, you want to maintain security of the database access and
use.
With Oracle server database security, you can

control database access

give access to specific objects in the database

confirm given and received privileges with the Oracle data dictionary
Database security can be classified into two categories:

system security

database security
system security
System security covers access and use of the database at the system level, such as the
username and password, the disk space allocated to users, and the system operations
that users can perform.
database security
Database security covers access and use of the database objects and the actions that
users can perform on the objects.
A privilege is the right to execute particular SQL statements. The database administrator
(DBA) is a high-level user with the ability to create users and grant users access to the
database and its objects.
Users require system privileges to gain access to the database and object privileges to
manipulate the content of the objects in the database.
Users can also be given the privilege to grant additional privileges to other users or to
roles, which are named groups of related privileges.
A schema is a collection of objects such as tables, views, and sequences. The schema is
owned by a database user and has the same name as that user.
These are the types of privileges that allow actions to be performed on schemas:

system privilege

object privilege
system privilege
A system privilege is the right to perform a particular action or to perform an action on any
schema object of a particular type.
object privilege
An object privilege provides the user the ability to perform a particular action on a specific
schema object.

2. Granting system privileges


There are more than 100 distinct system privileges available for users and roles.
Typically, system privileges are provided by the DBA.
These are some typical DBA privileges:

CREATE USER

DROP USER

DROP ANY TABLE

BACKUP ANY TABLE

SELECT ANY TABLE

CREATE ANY TABLE


CREATE USER
With the CREATE USER privilege, the grantee can create other Oracle users.
DROP USER
With the DROP USER privilege, the grantee can drop another user.
DROP ANY TABLE
With the DROP ANY TABLE privilege, the grantee can drop a table in any schema.
BACKUP ANY TABLE
With the BACKUP ANY TABLE privilege, the grantee can back up any table in any schema
with the export utility.
SELECT ANY TABLE
With the SELECT ANY TABLE privilege, the grantee can query tables, views, or
materialized views in any schema.
CREATE ANY TABLE
With the CREATE ANY TABLE privilege, the grantee can create tables in any schema.
The DBA creates the user by executing the CREATE USER statement. The user does not
have any privileges at this point. The DBA can then grant privileges to that user. These
privileges determine what the user can do at the database level.
Here is the abridged syntax for creating a user.
In the syntax:

user is the name of the user to be created

password specifies that the user must log in with this password
CREATE USER user
IDENTIFIED BY password;

Note
Starting Oracle Database 11g, passwords are case sensitive. Uppercase and
lowercase characters are different characters when used in a password.
This sample code creates a user Demo with the password Demo.

CREATE USER demo


IDENTIFIED BY demo;
After the DBA creates a user, the DBA can assign privileges to that user. For example, an
application developer may have these system privileges assigned to them.

CREATE SESSION

CREATE TABLE

CREATE SEQUENCE

CREATE VIEW

CREATE PROCEDURE
CREATE SESSION
With the CREATE SESSION privilege, the user can connect to the database.
CREATE TABLE
With the CREATE TABLE privilege, the user can create tables in the user's schema.
CREATE SEQUENCE
With the CREATE SEQUENCE privilege, the user can create a sequence in the user's
schema.
CREATE VIEW
With the CREATE VIEW privilege, the user can create a view in the user's schema.
CREATE PROCEDURE
With the CREATE PROCEDURE privilege, the user can create a stored procedure, function,
or package in the user's schema.
In the syntax for granting system privileges:

privilege is the system privilege to be granted


user|role|PUBLIC is the name of the user, the name of the role, or PUBLIC, which designates that
every user is granted the privilege
GRANT privilege [, privilege...]
TO user [, user| role, PUBLIC...];

Note
Current system privileges can be found in the SESSION_PRIVS dictionary view.
Data dictionary is a collection of tables and views created and maintained by the
Oracle server. It contains information about the database.
The DBA uses the GRANT statement to allocate system privileges to the user. After the
user has been granted the privileges, the user can immediately use these privileges. In

this sample code, the demo user has been assigned the privileges to create sessions,
tables, sequences, and views.
GRANT create session, create table,
create sequence, create view
TO demo;
A role is a named group of related privileges that can be granted to the user. This method
makes it easier to revoke and maintain privileges.
A user can have access to several roles, and several users can be assigned the same
role. Roles are typically created for a database application.
First, the DBA must create the role. Then the DBA can assign privileges to the role and
assign the role to users.
In the syntax, role is the name of the role to be created.
CREATE ROLE role;
After the role is created, the DBA can use the GRANT statement to assign the role to users
as well as to assign privileges to the role.
This sample code creates a manager role and then enables the manager to create tables
and views. It then grants Bell and Kochhar the role of managers. Now Bell and
Kochhar can create tables and views.
If users have multiple roles granted to them, they receive all the privileges associated with
all the roles.
--code for creating a role
CREATE ROLE manager;
--code for granting privileges to a role
GRANT create table, create view
TO manager;
--code for granting a role to users
GRANT manager TO BELL, KOCHHAR;
The DBA creates an account and initializes a password for every user. You can change
your password by using the ALTER USER statement.
In the syntax for the ALTER USER statement:

user is the name of the user

password specifies the new password

ALTER USER user


IDENTIFIED BY password;

Note
SQL*Plus has a PASSWORD command PASSW that can be used to change the
password of a user when the user is logged in. This command is not available in
SQL Developer.
Although the ALTER USER statement can be used to change your password, there are
many other options. You must have the ALTER USER privilege to change any other
option.
This sample code shows that the demo user changes the password by using the ALTER
USER statement.
ALTER USER demo
IDENTIFIED BY employ;

Question
Which privilege allows a user to connect to the database?
Options:
1.

CREATE PROCEDURE

2.

CREATE SEQUENCE

3.

CREATE SESSION

4.

CREATE TABLE

Answer
The CREATE SESSION privilege allows a user to connect to the database.
Option 1 is incorrect. The CREATE PROCEDURE system privilege authorizes the
user to create a stored procedure, function, or package in a schema.
Option 2 is incorrect. The CREATE SEQUENCE system privilege authorizes the
user to create a sequence in a schema.
Option 3 is correct. The CREATE SESSION privilege authorizes a user to connect
to the database.
Option 4 is incorrect. The CREATE TABLE system privilege authorizes users to
create a table in a schema.

3. Granting and revoking object privileges


An object privilege is a privilege or right to perform a particular action on a specific table,
view, sequence, or procedure. Each object has a particular set of grantable privileges.
This Object Privileges table lists privileges for various objects.
The only privileges that apply to a sequence are SELECT and ALTER. UPDATE,
REFERENCES, and INSERT can be restricted by specifying a subset of updatable
columns.
A SELECT privilege can be restricted by creating a view with a subset of columns and
granting the SELECT privilege only on the view.
A privilege granted on a synonym is converted to a privilege on the base table referenced
by the synonym.

Note
With the REFERENCES privilege, you can ensure that other users can create
FOREIGN KEY constraints that reference your table.
Different object privileges are available for different types of schema objects. A user
automatically has all object privileges for schema objects contained in the user's schema.
A user can grant any object privilege on any schema object that the user owns to any
other user or role.
If the grant includes WITH GRANT OPTION, the grantee can further grant the object
privilege to other users otherwise, the grantee can use the privilege but cannot grant it
to other users.
GRANT {object_priv|ALL} [(columns)]
ON object
TO {user|role|PUBLIC}
[WITH GRANT OPTION];

Note
In the syntax, schema is the same as the owner's name.
These are the components of the syntax for granting object privileges.

object_priv

ALL

columns

ON object

TO

PUBLIC

WITH GRANT OPTION


object_priv
object_priv is an object privilege to be granted.
ALL
ALL specifies all object privileges.
columns
columns specifies the column from a table or view on which the privileges are granted.
ON object
ON object is the object on which the privileges are granted.
TO
TO identifies to whom the privilege is granted.
PUBLIC
PUBLIC grants object privileges to all users.
WITH GRANT OPTION
WITH GRANT OPTION enables the grantee to grant object privileges to other users and
roles.
These are the guidelines for granting object privileges:

to grant privileges on an object, the object must be in your own schema, or you must have been
granted the object privileges using WITH GRANT OPTION

an object owner can grant any object privilege on the object to any other user or role of the
database

the owner of an object automatically acquires all object privileges on that object

Note
DBAs generally allocate system privileges; any user who owns an object can grant
object privileges.
These are some examples where object privileges are granted to users:

grant query privileges on a table

grant privileges to update specific columns

use a SELECT statement

create a synonym for a table and issue a SELECT statement


grant query privileges on a table
This sample code grants the demo user the privilege to query the EMPLOYEES table.
<code>
--code to grant query privileges on a table
GRANT select
ON employees
TO demo;
grant privileges to update specific columns
This sample code grants UPDATE privileges on specific columns in the DEPARTMENTS
table to the demo user and to the manager role.
<code>
--code to grant privileges to update specific columns
GRANT update (department_name, location_id)
ON departments
TO demo, manager;
use a SELECT statement
This sample code should be used if the schema is ORAXX, and the demo user wants to use
a SELECT statement to obtain data from the EMPLOYEES table.
<code>
--code to use a SELECT statement
SELECT * FROM oraxx.employees;
create a synonym for a table and issue a SELECT statement
In this sample code, the demo user creates a synonym for the EMPLOYEES table and
issues a SELECT statement from the synonym.
<code>
--code to create a synonym for a table and issue a SELECT statement
CREATE SYNONYM emp FOR oraxx.employees;
SELECT * FROM emp;
A privilege that is granted with the WITH GRANT OPTION clause can be passed on to
other users and roles by the grantee. Object privileges granted with the WITH GRANT
OPTION clause are revoked when the grantor's privilege is revoked.
This sample code gives the demo user access to the DEPARTMENTS table with the
privileges to query the table and add rows to the table. The code also shows that demo
can give others these privileges.

GRANT select, insert


ON departments
TO demo
WITH GRANT OPTION;
An owner of a table can grant access to all users by using the PUBLIC keyword.
This sample code allows all users on the system to query data from Alice's
DEPARTMENTS table.
GRANT select
ON alice.departments
TO PUBLIC;
If you attempt to perform an unauthorized operation, such as deleting a row from a table
for which you do not have the DELETE privilege, the Oracle server does not permit the
operation to take place.
If you receive the Oracle server error message "Table or view does not exist," then you
have

named a table or view that does not exist


attempted to perform an operation on a table or view for which you do not have the appropriate
privilege
The data dictionary is organized in tables and views and contains information about the
database. You can access the data dictionary to view the privileges that you have.
These are various data dictionary views:

ROLE_SYS_PRIVS

ROLE_TAB_PRIVS

USER_ROLE_PRIVS

USER_SYS_PRIVS

USER_TAB_PRIVS_MADE

USER_TAB_PRIVS_RECD

USER_COL_PRIVS_MADE

USER_COL_PRIVS_RECD
ROLE_SYS_PRIVS
The ROLE_SYS_PRIVS view displays system privileges granted to roles.
ROLE_TAB_PRIVS
The ROLE_TAB_PRIVS view shows table privileges granted to roles.

USER_ROLE_PRIVS
The USER_ROLE_PRIVS view displays the roles accessible by the user.
USER_SYS_PRIVS
The USER_SYS_PRIVS view displays system privileges granted to the user.
USER_TAB_PRIVS_MADE
The USER_TAB_PRIVS_MADE view displays object privileges granted on the user's
objects.
USER_TAB_PRIVS_RECD
The USER_TAB_PRIVS_RECD view displays object privileges granted to the user.
USER_COL_PRIVS_MADE
The USER_COL_PRIVS_MADE view displays object privileges granted on the columns of
the user's objects.
USER_COL_PRIVS_RECD
The USER_COL_PRIVS_RECD view displays object privileges granted to the user on
specific columns.
The ALL_TAB_PRIVS_MADE dictionary view describes all the object grants made by the
user or made on the objects owned by the user.
You can remove privileges granted to other users by using the REVOKE statement. When
you use the REVOKE statement, the privileges that you specify are revoked from the users
you name and from any other users to whom those privileges were granted by the
revoked user.

Note
If a user were to leave the company and you revoke his or her privileges, you
must regrant any privileges that this user may have granted to other users. If you
drop the user account without revoking privileges from it, then the system
privileges granted by this user to other users are not affected by this action.
In the syntax for revoking object privileges, CASCADE is required to remove any referential
integrity constraints made to the CONSTRAINTS object by means of the REFERENCES
privilege.
REVOKE {privilege [, privilege...]|ALL}
ON object
FROM {user[, user...]|role|PUBLIC}
[CASCADE CONSTRAINTS];

This sample code revokes SELECT and INSERT privileges given to the demo user on the
DEPARTMENTS table.
REVOKE select, insert
ON departments
FROM demo;
If a user is granted a privilege with the WITH GRANT OPTION clause, the user can also
grant the privilege with the WITH GRANT OPTION clause, so that a long chain of
grantees is possible. However, no circular grants granting to a grant ancestor are
permitted. If the owner revokes a privilege from a user who granted the privilege to other
users, then the revoking cascades to all the privileges granted.
For example, if user A grants a SELECT privilege on a table to user B including the WITH
GRANT OPTION clause, user B can grant to user C the SELECT privilege with the WITH
GRANT OPTION clause, and user C can then grant to user D the SELECT privilege. If
user A revokes privileges from user B, then the privileges granted to user C and user D
are also revoked.

Question
When this code is run, what will the user Tony be able to do as a result?

GRANT select
ON emp_view
TO tony;
Options:
1.

Create indexes on the view

2.

Grant this privilege to other users

3.

Query the emp_view view

4.

Select any column in the base table on which the emp_view view is based

Answer
This code would give Tony the ability to query the emp_view view.
Option 1 is incorrect. This statement will not allow Tony to create indexes on the
emp_view view. INDEX is not one of the grantable object privileges available to
views.

Option 2 is incorrect. Tony has not been granted the privilege with the WITH
GRANT OPTION clause, which would have given him the ability to grant the
privilege to others.
Option 3 is correct. The SELECT privilege is an available privilege to views, and
this code would give Tony the ability to query or select from the emp_view view.
Option 4 is incorrect. Views can be used to restrict a SELECT privilege by
including only a subset of the columns of the table that it is based on and granting
the SELECT privilege only on the view. Therefore, Tony will not be given full
permissions to select any column on the table that the emp_view view is based
on as a result of this statement.

Question
Which query provides information on the object privileges granted to the user?
Options:
1.

SELECT * from USER_ROLE_PRIVS;

2.

SELECT * from USER_SYS_PRIVS;

3.

SELECT * from USER_TAB_PRIVS_MADE;

4.

SELECT * from USER_TAB_PRIVS_RECD;

Answer
This query provides information on the object privileges granted to the user:
SELECT * from USER_TAB_PRIVS_RECD;
Option 1 is incorrect. The USER_ROLE_PRIVS data dictionary view provides
details on the roles accessible by the user.
Option 2 is incorrect. The USER_SYS_PRIVS data dictionary view provides details
on the system privileges granted to the user.
Option 3 is incorrect. The USER_TAB_PRIVS_MADE data dictionary view is used to
provide information on the object privileges granted on the user's objects.
Option 4 is correct. The USER_TAB_PRIVS_RECD data dictionary view is used to
provide information on the object privileges granted to the user.

Question
Which statement is true about object privileges?

Options:
1.

Grantees can grant privileges that they have been granted by default

2.

The ALL keyword is used to grant object privileges to all users

3.

The same object privileges are available for each type of schema object

4.

Users can grant any object privilege on any schema object they own

Answer
Users can grant any object privilege on any schema object they own.
Option 1 is incorrect. If a grant includes the WITH GRANT OPTION clause, then
the grantee can further grant the object privilege to other users otherwise, the
grantee can use the privilege but cannot grant it to other users.
Option 2 is incorrect. It is the PUBLIC keyword, not the ALL keyword, which gives
object privileges to all users. The ALL keyword is used to specify all object
privileges and would be used to give all the available privileges of an object to a
specified user or role.
Option 3 is incorrect. Each object has a particular set of grantable privileges. The
same object privileges are not available for each schema object.
Option 4 is correct. The owner of an object automatically acquires all object
privileges on that object.

Summary
DBAs maintain security of database access and use by assigning privileges to users.
Users require system privileges to gain access to the database and object privileges to
manipulate the content of the database objects.
The DBA can establish system privileges for a user by using the GRANT statement. A DBA
can also create roles by using the CREATE ROLE statement to pass along a collection of
system or object privileges to multiple users. Users can change their passwords by using
the ALTER USER statement.
A user automatically has all object privileges for schema objects contained in the user's
schema. A user can pass any available object privilege to other users or to all users by
using the GRANT statement. You can remove privileges from users by using the REVOKE
statement. Users can view privileges by using data dictionary views.

Altering existing objects

Abstract

This article discusses the use of the ALTER TABLE statement to add, modify, and drop a
column. This article also discusses the SET UNUSED and DROP UNUSED COLUMNS
options to mark and delete one or more columns marked as unused.

ALTER TABLE statement


After you create a table, you may need to change the table structure because you omitted
a column, your column definition needs to be changed, or you need to remove columns.
You can do this by using the ALTER TABLE statement. Using the ALTER TABLE
statement you can

add a new column

modify an existing column

define a default value for the new column

drop a column

You can add columns to a table, modify columns, and drop columns from a table by using the
ALTER TABLE statement. This is the syntax for the ALTER TABLE statement.
ALTER TABLE table
ADD (column datatype [DEFAULT expr ]
[, column datatype ]...);
ALTER TABLE table
MODIFY (column datatype [DEFAULT expr ]
[, column datatype ]...);
ALTER TABLE table
DROP (column);
In the syntax

table is the name of the table

ADD|MODIFY|DROP is the type of modification

column is the name of the column

datatype is the data type and length of the column

DEFAULT expr specifies the default value for a column


Adding a column
These are the guidelines for adding a column to a table:

You can add or modify columns.

You cannot specify where the column is to appear. The new column becomes the last column.
This sample code adds a column named JOB _ID to the DEPT80 table. The JOB _ID
column becomes the last column in the table.
ALTER TABLE dept80
ADD (job_id VARCHAR2(9));

Figure 1: Adding a column

Note : If a table already contains rows when a column is added, then the new column is
initially null or takes the default value for all the rows. You can add a mandatory NOT
NULL column to a table that contains data in other columns only if you specify a default
value. You can add a NOT NULL column to an empty table without the default value.
Modifying a column
You can modify a column definition by using the ALTER TABLE statement with the
MODIFY clause. Column modification can include changes to a column's data type, size,
and default value.
These are some guidelines for modifying a column:

You can increase the width or precision of a numeric column.

You can increase the width of character columns.

You can also decrease the width of a column if:

the column contains only null values

the table has no rows

the decrease in column width is not less than the existing values in that column

You can change the data type if the column contains only null values. The exception to
this is CHAR -to-VARCHAR2 conversions, which can be done with data in the columns.

You can also convert a CHAR column to the VARCHAR2 data type or convert a VARCHAR2
column to the CHAR data type only if the column contains null values or if you do not change the
size.
A change to the default value of a column affects only subsequent insertions to the table.
This sample code uses the ALTER TABLE statement to modify a column.
ALTER TABLE dept80
MODIFY (last_name VARCHAR2(30));

Figure 2: Modifying a column

Dropping a column
You can drop a column from a table by using the ALTER TABLE statement with the DROP
COLUMN clause.
These are the guidelines for dropping a column:

The column may or may not contain data.

Using the ALTER TABLE DROP COLUMN statement, only one column can be dropped at a time.

The table must have at least one column remaining in it after it is altered.

After a column is dropped, it cannot be recovered.

A column cannot be dropped if it is part of a constraint or part of an index key unless the cascade
option is added.

Dropping a column can take some time if the column has a large number of values. In this case, it
may be better to set it to be unused and drop it when there are fewer users on the system to avoid
extended locks.
Note : Certain columns can never be dropped, such as columns that form part of the
partitioning key of a partitioned table or columns that form part of the primary key of an
index-organized table.
This sample code uses the ALTER TABLE statement to drop a column.
ALTER TABLE dept80
DROP COLUMN job_id;

Figure 3: Dropping a column

SET UNUSED option


The SET UNUSED option marks one or more columns as unused so that they can be
dropped when the demand on system resources is higher. Specifying this clause does not
actually remove the target columns from each row in the table - that is, it does not restore
the disk space used by these columns. Therefore, the response time is faster than if you
executed the DROP clause.
Unused columns are treated as if they were dropped, even though their column data
remains in the table's rows. After a column has been marked as unused, you have no
access to that column. A SELECT * query will not retrieve data from unused columns. In
addition, the names and types of columns marked unused will not be displayed during a
DESCRIBE statement, and you can add to the table a new column with the same name as
an unused column. The SET UNUSED information is stored in the USER _UNUSED _COL
_TABS dictionary view.
This is the syntax for the SET UNUSED option.
ALTER TABLE <table _name >
SET UNUSED (<column _name >);
OR
ALTER TABLE <table_name >
SET UNUSED COLUMN <column_name >;
Note : The guidelines for setting a column to UNUSED are similar to those for dropping a
column.

DROP UNUSED COLUMNS option


DROP UNUSED COLUMNS removes from the table all columns currently marked as
unused. You can use this statement when you want to reclaim the extra disk space from
unused columns in the table. If the table contains no unused columns, the statement
returns with no errors.

This is the syntax for the DROP UNUSED COLUMNS option.


ALTER TABLE <table_name >
DROP UNUSED COLUMNS ;
ALTER TABLE dept80
SET UNUSED (last_name );

Figure 4: Using the SET UNUSED option

ALTER TABLE dept80


DROP UNUSED COLUMNS ;

Figure 5: Using the UNUSED COLUMNS option

Summary
You can add, modify, and drop columns from a table by using the ALTER TABLE
statement.
When a new column is added, it automatically becomes the last column. A column's data
type, size, and default value can be modified. A column with or without data can be
dropped and after a column is dropped, it cannot be recovered.
The SET UNUSED option marks one or more columns as unused so that they can be
dropped when the demand on system resources is lower. The DROP UNUSED COLUMNS
option removes from the table all columns currently marked as unused.

Managing Indexes and Constraints


Learning objective

After completing this topic, you should be able to recognize the steps for adding and
manipulating constraints and for creating indexes.

1. Adding and deferring constraints

You can add a constraint for existing tables by using the ALTER TABLE statement with
the ADD clause.
In the syntax, table is the name of the table, constraint is the name of the constraint, type
is the constraint type, and column is the name of the column affected by the constraint.
ALTER TABLE <table_name>
ADD [CONSTRAINT <constraint_name>]
type (<column_name>);
The constraint name syntax is optional, although recommended. If you do not name your
constraints, the system generates constraint names.
Here are the guidelines for adding a constraint:

you can add, drop, enable, or disable a constraint, but you cannot modify its structure
you can add a NOT NULL constraint to an existing column by using the MODIFY clause of the
ALTER TABLE statement

Note
You can define a NOT NULL column only if the table is empty or if the column has
a value for every row.
This sample code modifies the EMP2 table to add a PRIMARY KEY constraint on the
EMPLOYEE_ID column. Because no constraint name is provided, the constraint is
automatically named by the Oracle server.
ALTER TABLE emp2
MODIFY employee_id PRIMARY KEY;
This sample code creates a FOREIGN KEY constraint on the EMP2 table. The constraint
ensures that a manager exists as a valid employee in the EMP2 table.
ALTER TABLE emp2
ADD CONSTRAINT emp_mgr_fk
FOREIGN KEY(manager_id)
REFERENCES emp2(employee_id);
The ON DELETE CASCADE action allows parent key data that is referenced from the child
table to be deleted, but not updated. When data in the parent key is deleted, all rows in
the child table that depend on the deleted parent key values are also deleted.
To specify this referential action, include the ON DELETE CASCADE option in the
definition of the FOREIGN KEY constraint.

ALTER TABLE Emp2 ADD CONSTRAINT emp_dt_fk


FOREIGN KEY (Department_id)
REFERENCES departments(department_id) ON DELETE CASCADE;
Constraints can have these attributes:

DEFERRABLE or NOT DEFERRABLE

INITIALLY DEFERRED or INITIALLY IMMEDIATE


These attributes can be different for each constraint.
You can defer checking constraints for validity until the end of the transaction. A constraint
is deferred if the system checks that it is satisfied only on commit.
If a deferred constraint is violated, then commit causes the transaction to roll back.
ALTER TABLE dept2
ADD CONSTRAINT dept2_id_pk
PRIMARY KEY (department_id)
DEFERRABLE INITIALLY DEFERRED
If a constraint is immediate, that is it is not deferred, it is checked at the end of each
statement. If it is violated, the statement is rolled back immediately.
If a constraint causes an action for example, DELETE CASCADE that action is always
taken as part of the statement that caused it, whether the constraint is deferred or
immediate.
SET CONSTRAINTS dept2_id_pk IMMEDIATE
You use the SET CONSTRAINTS statement to specify for a particular transaction whether
a deferrable constraint is checked following each Data Manipulation Language (DML)
statement or when the transaction is committed.
To create deferrable constraints, you must create a nonunique index for that constraint.
SET CONSTRAINTS dept2_id_pk IMMEDIATE
This sample code changes all constraints for a session.
ALTER SESSION
SET CONSTRAINTS= IMMEDIATE
Here is a scenario where constraints need to be deferred.
Company policy dictates that department number 40 should be changed to 45. Changing

the DEPARTMENT_ID column affects employees assigned to this department. Therefore,


you make the primary key and foreign keys deferrable and initially deferred. You update
both department and employee information, and at the time of commit, all rows are
validated.
A constraint that is defined as deferrable can be specified as:

INITIALLY DEFERRED

INITIALLY IMMEDIATE
INITIALLY DEFERRED
INITIALLY DEFERRED waits to check the constraint until the transaction ends. In this
sample code, the bonus_ck constraint is created as DEFERRABLE INITIALLY
DEFERRED.
<code>
CREATE TABLE emp_new_sal (salary NUMBER
CONSTRAINT sal_ck
CHECK (salary > 100)
DEFERRABLE INITIALLY IMMEDIATE,
bonus NUMBER
CONSTRAINT bonus_ck
CHECK (bonus > 0 )
DEFERRABLE INITIALLY DEFERRED );
INITIALLY IMMEDIATE
INITIALLY IMMEDIATE checks the constraint at the end of the statement execution. The
INITIALLY IMMEDIATE clause is the default. In this sample code, the sal_ck constraint
is created as DEFERRABLE INITIALLY IMMEDIATE.
<code>
CREATE TABLE emp_new_sal (salary NUMBER
CONSTRAINT sal_ck
CHECK (salary > 100)
DEFERRABLE INITIALLY IMMEDIATE,
bonus NUMBER
CONSTRAINT bonus_ck
CHECK (bonus > 0 )
DEFERRABLE INITIALLY DEFERRED );
After creating the EMP_NEW_SAL table as shown in this sample code, you attempt to
insert values into the table and observe the results.
When both the sal_ck and bonus_ck constraints are satisfied, the rows are inserted
without an error.

Here are some examples of testing the constraints by inserting values into the table:

inserting a row that violates sal_ck

inserting a row that violates bonus_ck

set the DEFERRED status to all constraints that can be deferred

set the IMMEDIATE status to constraints set as DEFERRED


inserting a row that violates sal_ck
This sample code inserts a row that violates sal_ck. In the CREATE TABLE statement,
sal_ck is specified as an initially immediate constraint. This means that the constraint is
verified immediately after the INSERT statement and you observe an error.
<Code>
INSERT INTO emp_new_sal VALUES(90,5);
inserting a row that violates bonus_ck
This sample code inserts a row that violates bonus_ck. In the CREATE TABLE statement,
bonus_ck is specified as deferrable and also initially deferred. Therefore, the constraint is
not verified until you COMMIT or set the constraint back to immediate. The row insertion is
successful. But, you observe an error when you commit the transaction. The commit failed
due to constraint violation. Therefore, at this point, the transaction is rolled back by the
database.
<Code>
INSERT INTO emp_new_sal VALUES(110, -1);
COMMIT;
set the DEFERRED status to all constraints that can be deferred
This sample code sets the DEFERRED status to all constraints that can be deferred. Note
that you can also set the DEFERRED status to a single constraint if required. Now, if you
attempt to insert a row that violates the sal_ck constraint, the statement is executed
successfully. But, you observe an error when you commit the transaction. The transaction
fails and is rolled back. This is because both the constraints are checked upon COMMIT.
<Code>
SET CONSTRAINTS ALL DEFERRED;
INSERT INTO emp_new_sal VALUES(90,5);
COMMIT;
set the IMMEDIATE status to constraints set as DEFERRED
Set the IMMEDIATE status to both the constraints that were set as DEFERRED. You
observe an error if you attempt to insert a row that violates either sal_ck or bonus_ck.
<Code>

SET CONSTRAINTS ALL IMMEDIATE;


INSERT INTO emp_new_sal VALUES(110, -1);
If you create a table without specifying constraint deferability, then the constraint is
checked immediately at the end of each statement.
For example, with the CREATE TABLE statement of the NEWEMP_DETAILS table, if you
do not specify the newemp_det_pk constraint deferability, then the constraint is checked
immediately.
CREATE TABLE newemp_details(emp_id NUMBER, emp_name
VARCHAR2(20),
CONSTRAINT newemp_det_pk PRIMARY KEY(emp_id));
When you attempt to defer the newemp_det_pk constraint that is not deferrable, you
observe an error.
SET CONSTRAINT newemp_det_pk DEFERRED;

Question
You have attempted to insert a value of 90 into the EMP_SAL table created with
this code.
With regard to the results, which statements are accurate?

CREATE TABLE emp_sal (salary NUMBER


CONSTRAINT sal_ck
CHECK (salary >100)
DEFERRABLE INITIALLY DEFERRED)
Options:
1.

The constraint would be checked at the end of the statement execution

2.

The constraint would be checked when the transaction is committed

3.

The INSERT statement would fail immediately and produce an error

4.

The INSERT statement would be rolled back upon committing

Answer
When the transaction is committed, the constraint would be checked and the
INSERT statement would be rolled back.
Option 1 is incorrect. Constraints configured as DEFERRED INITIALLY
DEFERRED wait until the transaction ends to check the constraint, which would be

when it attempts to commit the transaction. These constraints are not checked at
the end of statement execution.
Option 2 is correct. A constraint that is defined as deferrable can be specified as
either INITIALLY DEFERRED or INITIALLY IMMEDIATE. If defined as
INITIALLY DEFERRED, the Oracle server waits until the transaction ends to
check the constraint.
Option 3 is incorrect. The INSERT statement would initially be permitted because
the constraint is DEFERRABLE INITIALLY DEFERRED. It is only upon an attempt
to commit the transaction that the constraint would be checked. In this situation,
the value of 90 would be found to violate the constraint.
Option 4 is correct. The value being inserted violates the sal_ck constraint. Upon
attempting to commit the transaction, the constraint would be checked and the
transaction would be rolled back.

2. Manipulating constraints
To drop a constraint, you can identify the constraint name from the USER_CONSTRAINTS
and USER_CONS_COLUMNS data dictionary views. Then, you use the ALTER TABLE
statement with the DROP clause. The CASCADE option of the DROP clause causes any
dependent constraints also to be dropped.
In the syntax, table is the name of the table, column is the name of the column affected
by the constraint, and constraint is the name of the constraint.
ALTER TABLE table
DROP PRIMARY KEY | UNIQUE (column) |
CONSTRAINT constraint [CASCADE];
When you drop an integrity constraint, that constraint is no longer enforced by the Oracle
server and is no longer available in the data dictionary.
This sample code removes the manager constraint from the EMP2 table.
ALTER TABLE emp2
DROP CONSTRAINT emp_mgr_fk;
This sample code removes the PRIMARY KEY constraint on the DEPT2 table and drops
the associated FOREIGN KEY constraint on the EMP2.DEPARTMENT_ID column.
ALTER TABLE dept2
DROP PRIMARY KEY CASCADE;

You can disable a constraint without dropping it or recreating it by using the ALTER
TABLE statement with the DISABLE clause.
In the syntax for disabling a constraint, table is the name of the table and constraint is the
name of the constraint.
ALTER TABLE table
DISABLE CONSTRAINT constraint [CASCADE];
These are the guidelines for disabling constraints:

you can use the DISABLE clause in both the CREATE TABLE statement and the ALTER TABLE
statement

the CASCADE clause disables dependent integrity constraints

disabling a UNIQUE KEY or PRIMARY KEY constraint removes the unique index
This sample code disables the constraint emp_dt_fk.
ALTER TABLE emp2
DISABLE CONSTRAINT emp_dt_fk;
You can enable a constraint without dropping it or re-creating it by using the ALTER
TABLE statement with the ENABLE clause.
In the syntax for enabling a constraint, table is the name of the table and constraint is the
name of the constraint.
ALTER TABLE table
ENABLE CONSTRAINT constraint;
Here are the guidelines for enabling constraints:

constraint applies to all table data

enabling a UNIQUE or PRIMARY KEY constraint creates a UNIQUE or PRIMARY KEY index

the ENABLE clause can be used in CREATE TABLE and ALTER TABLE

enabling a PRIMARY KEY constraint does not enable foreign keys

enabling a UNIQUE KEY constraint or a PRIMARY KEY constraint requires privileges


constraint applies to all table data
If you enable a constraint, that constraint applies to all the data in the table. All the data in
the table must comply with the constraint.
enabling a UNIQUE or PRIMARY KEY constraint creates a UNIQUE or PRIMARY KEY
index

If you enable a UNIQUE key or a PRIMARY KEY constraint, a UNIQUE or PRIMARY KEY
index is created automatically. If an index already exists, then it can be used by these
keys.
the ENABLE clause can be used in CREATE TABLE and ALTER TABLE
You can use the ENABLE clause in both the CREATE TABLE statement and the ALTER
TABLE statement.
enabling a PRIMARY KEY constraint does not enable foreign keys
Enabling a PRIMARY KEY constraint that was disabled with the CASCADE option does not
enable any foreign keys that are dependent on the primary key.
enabling a UNIQUE KEY constraint or a PRIMARY KEY constraint requires privileges
To enable a UNIQUE KEY constraint or a PRIMARY KEY constraint, you must have the
privileges necessary to create an index on the table.
To cascade constraints, the CASCADE CONSTRAINTS clause is used along with the DROP
COLUMN clause. The CASCADE CONSTRAINTS clause drops all referential integrity
constraints that refer to the primary and unique keys defined on the dropped columns.
The CASCADE CONSTRAINTS clause also drops all multicolumn constraints defined on
the dropped columns.
Here is a sample code that uses the CASCADE CONSTRAINTS clause. Assume that the
TEST1 table is created by using this sample code.
CREATE TABLE test1 (
col1_pk NUMBER PRIMARY KEY,
col2_fk NUMBER,
col1 NUMBER,
col2 NUMBER,
CONSTRAINT fk_constraint FOREIGN KEY (col2_fk) REFERENCES
test1,
CONSTRAINT ck1 CHECK (col1_pk > 0 and col1 > 0),
CONSTRAINT ck2 CHECK (col2_fk > 0));
If we use these sample ALTER TABLE statements, an error is returned.
--col1_pk is a parent key.
ALTER TABLE test1 DROP (col1_pk);
--col1 is referenced by the multicolumn
constraint, ck1.
ALTER TABLE test1 DROP (col1);
Submitting this sample code drops the EMPLOYEE_ID column, the PRIMARY KEY
constraint, and any FOREIGN KEY constraints referencing the PRIMARY KEY constraint
for the EMP2 table.

ALTER TABLE emp2 DROP COLUMN employee_id CASCADE CONSTRAINTS;


This sample code drops the col1_pk, col2_fk, col1 keys and any FOREIGN KEY
constraints referencing the PRIMARY KEY constraint for the TEST1 table.
ALTER TABLE test1
DROP (col1_pk, col2_fk, col1) CASCADE CONSTRAINTS;
If all columns referenced by the constraints defined on the dropped columns are also
dropped, then CASCADE CONSTRAINTS is not required.
For example, assuming that no other referential constraints from other tables refer to the
COL1_PK column, it is valid to submit this statement without the CASCADE
CONSTRAINTS clause for the TEST1 table.
ALTER TABLE test1 DROP (col1_pk, col2_fk, col1);
You can rename columns and constraints of existing tables by using the ALTER TABLE
statement. This sample code creates the marketing table with the primary key
mktg_pk defined on the TEAM_ID column.
CREATE TABLE marketing (team_id NUMBER(10),
target VARCHAR2(50),
CONSTRAINT mktg_pk PRIMARY KEY(team_id));
In the MARKETING table, you can use the ALTER TABLE statement to rename:

columns

constraints
columns
You can use the RENAME COLUMN clause of the ALTER TABLE statement to rename table
columns. When you rename a table column, the new name must not conflict with the name
of any existing column in the table. You cannot use any other clauses in conjunction with
the RENAME COLUMN clause. This sample code shows that the TEAM_ID column of the
MARKETING table is renamed ID.
constraints
You can use the RENAME CONSTRAINT clause of the ALTER TABLE statement to rename
any existing constraint for a table. When you rename any existing constraint for a table, the
new name must not conflict with any of your existing constraint names. You can use the
RENAME CONSTRAINT clause to rename system-generated constraint names. This
sample code shows that mktg_pk is renamed new_mktg_pk.

Question

Which clause is used to drop all referential integrity constraints referring to the
primary and unique keys defined on dropped columns?
Options:
1.

CASCADE CONSTRAINTS

2.

ENABLE CONSTRAINT

3.

RENAME COLUMN

4.

RENAME CONSTRAINT

Answer
The CASCADE CONSTRAINTS clause is used to drop all referential integrity
constraints that refer to the primary key and unique keys defined on the dropped
columns.
Option 1 is correct. The CASCADE CONSTRAINTS clause is used along with the
DROP COLUMN clause to drop all referential integrity constraints that refer to the
primary key and unique keys defined on the dropped columns.
Option 2 is incorrect. The ENABLE CONSTRAINT clause is used to activate an
integrity constraint that is currently disabled.
Option 3 is incorrect. The RENAME COLUMN clause of the ALTER TABLE
statement is used to rename table columns.
Option 4 is incorrect. The RENAME CONSTRAINT clause of the ALTER TABLE
statement is used to rename any existing constraint for a table.

3. Creating and removing indexes


You can create indexes in two ways:

manually

automatically
Two types of indexes can be created:

unique index

nonunique index
unique index

The Oracle server automatically creates a unique index when you define a column or
group of columns in a table to have a PRIMARY KEY or a UNIQUE key constraint. The
name of the index is the name given to the constraint.
nonunique index
A nonunique index can be created by a user. For example, you can create an index for a
FOREIGN KEY column to be used in joins to improve retrieval speed.
You can create an index on one or more columns by issuing the CREATE INDEX
statement or during the creation of a table using the CREATE TABLE statement. You can
manually create a unique index, but it is recommended that you create a unique
constraint, which implicitly creates a unique index.
In this sample code, the CREATE INDEX clause is used with the CREATE TABLE
statement to create a primary key index explicitly.
You can name your indexes at the time of primary key creation to be different from the
name of the PRIMARY KEY constraint.
CREATE TABLE new_emp
(employee_id NUMBER(6)
PRIMARY KEY USING INDEX
(CREATE INDEX emp_id_idx ON
new_emp(employee_id)),
first_name VARCHAR2(20),
last_name VARCHAR2(25));
You can query the USER_INDEXES data dictionary view for information about your
indexes.
SELECT index_name, table_name
FROM user_indexes
WHERE TABLE_NAME = 'new_emp';
Here is an example of database behavior when you create an index that is not explicitly
named.
This sample code creates an unnamed primary key index.
CREATE TABLE emp_unnamed_index
(employee_id NUMBER(6) PRIMARY KEY ,
first_name VARCHAR2(20),
last_name VARCHAR2(25));

You can then query the USER_INDEXES data dictionary view using this code to see the
Oracle server generic name that was given to the index that was created for the PRIMARY
KEY column.
SELECT index_name, table_name
FROM user_indexes
WHERE TABLE_NAME = 'emp_unnamed_index';
You can also use an existing index for your PRIMARY KEY column for example, when
you are expecting a large data load and want to speed up the operation. You may want to
disable the constraints while performing the load and then enable them, in which case
having a unique index on the primary key will still cause the data to be verified during the
load.
You can first create a nonunique index on the column designated as PRIMARY KEY, and
then create the PRIMARY KEY column and specify that it should use the existing index.
Here are the steps:
Step 1: Create the table.
Step 2: Create the index.
Step 3: Create the primary key.
A function-based index is based on expressions. The index expression is built from table
columns, constants, SQL functions, and user-defined functions.
CREATE INDEX upper_dept_name_idx
ON dept2(UPPER(department_name));
Function-based indexes defined with the UPPER(column_name) or
LOWER(column_name) keywords allow non-case-sensitive searches.
Here is the sample code for defining a function-based index with an
UPPER(column_name)keyword.
CREATE INDEX upper_last_name_idx ON emp2 (UPPER(last_name));
SELECT *
FROM dept2
WHERE UPPER(department_name) = 'SALES';
Consider this second example of creating a function-based index to facilitate processing
queries.

CREATE INDEX upper_last_name_idx ON emp2 (UPPER(last_name));


SELECT * FROM emp2 WHERE UPPER(last_name) = 'KING';
The Oracle server uses the index only when that particular function is used in a query.
For example, this sample code may use the index, but without the WHERE clause, the
Oracle server may perform a full table scan.
SELECT *
FROM employees
WHERE UPPER (last_name) IS NOT NULL
ORDER BY UPPER (last_name);

Note
The QUERY_REWRITE_ENABLED initialization parameter must be set to TRUE for a
function-based index to be used.
The Oracle server treats indexes with columns marked DESC as function-based indexes.
The columns marked DESC are sorted in descending order.
You cannot modify indexes. To change an index, you must drop it and then recreate it.
You can remove an index definition from the data dictionary by issuing the DROP INDEX
statement.
To drop an index, you must be the owner of the index or have the DROP ANY INDEX
privilege.
In the syntax for dropping an index, index is the name of the index.
DROP INDEX index;
If you drop a table, then indexes, constraints, and triggers are automatically dropped, but
views and sequences remain.
Here is a sample code for dropping an index.
DROP INDEX upper_dept_name_idx;
Oracle Database provides a feature for dropping tables. When you drop a table, the
database does not immediately release the space associated with the table. Rather, the
database renames the table and places it in a recycle bin, where it can later be recovered
with the FLASHBACK TABLE statement if you find that you dropped the table in error.
If you want to immediately release the space associated with the table at the time you
issue the DROP TABLE statement, then include the PURGE clause as in this sample code.

DROP TABLE dept80 PURGE;


You specify PURGE only if you want to drop the table and release the space associated
with it in a single step. If you specify PURGE, then the database does not place the table
and its dependent objects into the recycle bin.
Using the PURGE clause is equivalent to first dropping the table and then purging it from
the recycle bin. This clause saves you one step in the process. It also provides enhanced
security if you want to prevent sensitive material from appearing in the recycle bin.

Note
You cannot roll back a DROP TABLE statement with the PURGE clause, and you
cannot recover the table if you drop it with the PURGE clause. This feature was not
available in earlier releases.

Question
What can you do to create indexes manually?
Options:
1.

Create a PRIMARY KEY constraint

2.

Create a UNIQUE KEY constraint

3.

Issue a CREATE INDEX statement

4.

Issue a CREATE TABLE statement

Answer
You can use the CREATE INDEX or CREATE TABLE statement to create an index
manually.
Option 1 is incorrect. This is considered automatic index creation. The Oracle
server automatically creates a unique index when you define a column or group of
columns in a table to have a PRIMARY KEY constraint.
Option 2 is incorrect. This is considered automatic index creation. The Oracle
server automatically creates a unique index when you define a column or group of
columns in a table to have a UNIQUE KEY constraint.
Option 3 is correct. You can create an index on one or more columns by issuing
the CREATE INDEX statement.
Option 4 is correct. The CREATE TABLE statement can be used to explicitly
create an index.

Question
Which statements are true about using the PURGE clause of the DROP TABLE
statement?
Options:
1.

It enhances security

2.

Space is released immediately

3.

The statement can be rolled back

4.

The table is placed in a recycle bin

Answer
Using the PURGE clause of the DROP TABLE statement enhances security and
releases space immediately.
Option 1 is correct. The PURGE clause of the DROP TABLE command enhances
security if you want to prevent sensitive material from appearing in the recycle bin.
Option 2 is correct. When you drop a table using the PURGE clause, the database
immediately releases the space associated with the table.
Option 3 is incorrect. You cannot roll back a DROP TABLE statement with the
purge clause, and you cannot recover the table if you drop it with the PURGE
clause.
Option 4 is incorrect. If you use the PURGE clause of the DROP TABLE statement,
the table and its dependent objects do not go to the recycle bin.

Summary
You can add constraints by using the ALTER TABLE statement with the ADD clause.
Constraints can be DEFERRABLE, NOT DEFERRABLE, INITIALLY DEFERRED, or
INITIALLY IMMEDIATE. You can use the SET CONSTRAINTS statement to specify, for
a particular transaction, whether a deferrable constraint is checked.
You use ALTER TABLE with the DROP clause to drop constraints, with the DISABLE
clause to disable constraints, or with the ENABLE clause to enable constraints. You use
the CASCADE CONSTRAINTS clause with DROP COLUMN to cascade constraints. You can
use ALTER TABLE to rename columns and constraints.
You can create unique or nonunique indexes. The CREATE INDEX clause is used with

the CREATE TABLE statement to create a primary key index explicitly. To change an
index, you must drop it and recreate it. You use DROP INDEX to drop an index.

Flashback Operations and External Tables


Learning objective

After completing this topic, you should be able to identify the steps for recovering your
database using flashback, and for manipulating external data.

1. Performing the FLASHBACK TABLE operation


Oracle Flashback Table enables you to recover tables to a specified point in time with a
single statement. You can restore table data along with associated indexes, and
constraints, when the database is online, undoing changes to only the specified tables.
The Flashback Table feature is similar to a self-service repair tool. For example, if you
have accidentally deleted important rows from a table and then wanted to recover the
deleted rows, you can use the FLASHBACK TABLE statement to restore the table to the
time before the deletion and see the missing rows in the table.
When using the FLASHBACK TABLE statement, you can revert the table and its contents
to a certain time or to a system change number (SCN).

Note
SCN is an integer value associated with each change in the database. It is a
unique incremental number in the database. Every time you commit a transaction,
a new SCN is recorded.
Oracle Database provides a SQL data definition language (DDL) command, FLASHBACK
TABLE, to restore the state of a table to an earlier point in time in case it is inadvertently
deleted or modified. The FLASHBACK TABLE command is a self-service repair tool to
restore data in a table along with associated attributes such as indexes or views. This is
done when the database is online by rolling back only the subsequent changes to the
given table.
As compared to traditional recovery mechanisms, the self-service repair feature offers
significant benefits such as ease of use, availability, and faster restoration. It also takes
the burden off the database administrator (DBA) to find and restore application-specific
properties. The Flashback Table feature does not address physical corruption caused by
a bad disk.

You can invoke a FLASHBACK TABLE operation on one or more tables, and even on
tables in different schemas. You specify the point in time to which you want to revert by
providing a valid time stamp. By default, database triggers are disabled during the
flashback operation for all tables involved. You can override this default behavior by
specifying the ENABLE TRIGGERS clause.
FLASHBACK TABLE [schema.]table[,
[ schema.]table ]...
TO { TIMESTAMP | SCN } expr
[ { ENABLE | DISABLE } TRIGGERS ];
The recycle bin is actually a data dictionary table containing information about dropped
objects. Dropped tables and any associated objects such as, indexes, constraints, nested
tables, and so on are not removed and still occupy space. They continue to count against
user space quotas until specifically purged from the recycle bin or the situation where
they must be purged by the database because of table space constraints.
Here is a sample code to view objects in the recycle bin.
SELECT original_name, operation, droptime FROM
recyclebin;
Each user can be thought of as an owner of a recycle bin because, unless a user has the
SYSDBA privilege, the only objects that the user has access to in the recycle bin are those
that the user owns. A user can view his or her objects in the recycle bin by using this
statement:
SELECT * FROM RECYCLEBIN;
When you drop a user, any objects belonging to that user are not placed in the recycle bin
and any objects in the recycle bin are purged. You can purge the recycle bin using this
statement:
PURGE RECYCLEBIN;
Say you accidently dropped the EMP2 table using this code and now you need to restore
it.
DROP emp2;
This sample code restores the EMP2 table to a state before a DROP statement.
FLASHBACK TABLE emp2 TO BEFORE DROP;

Question

Identify the true statements about the Oracle Flashback Table feature.
Options:
1.

It enables you to recover only to a specified point in time

2.

The database must be offline when performing a flashback operation

3.

The operation can be performed on one or more tables at once

4.

You can use it to restore table data

Answer
You can perform the Flashback Table operation on one or more tables and use
this feature to restore table data.
Option 1 is incorrect. Oracle Flashback Table enables you to revert the table and
its content to a certain time or to an SCN. Oracle Flashback table is not limited to
recovering only to a specified point in time.
Option 2 is incorrect. You can restore table data along with associated indexes,
and constraints, when the database is online, undoing changes to only the
specified tables.
Option 3 is correct. You can invoke a FLASHBACK TABLE operation on one or
more tables, and even on tables in different schemas.
Option 4 is correct. The FLASHBACK TABLE command is a self-service repair tool
to restore data in a table along with associated attributes such as indexes or
views.

2. Creating and using external tables


An external table is a read-only table whose metadata is stored in the database and the
data is stored outside the database. This external table definition can be thought of as a
view that is used for running any SQL query against external data without requiring that
the external data first be loaded into the database. The external table data can be queried
and joined directly and in parallel without requiring that the external data first be loaded in
the database. You can use SQL, PL/SQL, and Java to query the data in an external table.
The main differences between external tables and regular tables are:

externally organized tables are read-only

no data manipulation language (DML) operations are possible in external tables

no indexes can be created on external tables

However, you can create an external table and unload data using the CREATE TABLE
AS SELECT command.
The Oracle server provides these two major access drivers for external tables:

ORACLE_LOADER

ORACLE_DATAPUMP
ORACLE_LOADER
The ORACLE_LOADER or loader access driver is used for reading data from external files
whose format can be interpreted by the SQL*Loader utility. Note that all SQL*Loader
functionalities are not supported with external tables.
ORACLE_DATAPUMP
The ORACLE_DATAPUMP access driver can be used to both import and export data using a
platform-independent format. The ORACLE_DATAPUMP access driver writes rows from a
SELECT statement to be loaded into an external table as part of a CREATE
TABLE...ORGANIZATION EXTERNAL...AS SELECT statement. You can then use a
SELECT statement to read data out of that data file. You can also create an external table
definition on another system and use that data file. This allows data to be moved between
Oracle databases.
You use the CREATE DIRECTORY statement to create a directory object. A directory
object specifies an alias for a directory on the server's file system where an external data
source resides. You can use directory names when referring to an external data source,
rather than hard code the operating system path name, for greater file management
flexibility.
CREATE OR REPLACE DIRECTORY emp_dir
AS '//emp_dir';
You must have the CREATE ANY DIRECTORY system privileges to create directories.
When you create a directory, you are automatically granted the READ and WRITE object
privileges and can grant READ and WRITE privileges to other users and roles. The DBA
can also grant these privileges to other users and roles.
GRANT READ ON DIRECTORY emp_dir TO hr;
A user needs READ privileges to access all directories used in external tables and WRITE
privileges for the log, bad, and discard file locations being used. In addition, a WRITE
privilege is necessary when the external table framework is being used to unload data.
Oracle also provides the ORACLE_DATAPUMP type, with which you can unload data (that
is, read data from a table in the database and insert it into an external table) and then
reload it into an Oracle database. This is a one-time operation that can be done when the

table is created. After the creation and initial population is done, you cannot update,
insert, or delete any rows.
Here is the syntax for creating the directory object.
CREATE [OR REPLACE] DIRECTORY directory AS 'path_name';
In the directory object syntax, these items are used:

OR REPLACE

directory

path_name
OR REPLACE
You can specify OR REPLACE to re-create the directory database object if it already exists.
You can use this clause to change the definition of an existing directory without dropping,
re-creating, and re-granting database object privileges previously granted on the directory.
Users who were previously granted privileges on a redefined directory can continue to
access the directory without requiring that the privileges be re-granted.
directory
You use directory to specify the name of the directory object to be created. The maximum
length of the directory name is 30 bytes. You cannot qualify a directory object with a
schema name.
path_name
You use path_name to specify the full path name of the operating system directory to be
accessed. The path name is case-sensitive.
You create external tables using the ORGANIZATION EXTERNAL clause of the CREATE
TABLE statement. You are not, in fact, creating a table. Rather, you are creating metadata
in the data dictionary that you can use to access external data. You use the
ORGANIZATION clause to specify the order in which the data rows of the table are stored.
By specifying EXTERNAL in the ORGANIZATION clause, you indicate that the table is a
read-only table located outside the database.
CREATE TABLE <table_name>
( <col_name> <datatype>, )
ORGANIZATION EXTERNAL
(TYPE <access_driver_type>
DEFAULT DIRECTORY <directory_name>
ACCESS PARAMETERS
( ) )
LOCATION ('<location_specifier>') )
REJECT LIMIT [0 | <number> | UNLIMITED];

Note
The external files must already exist outside the database.
The clauses used in the CREATE TABLE command are

TYPE

DEFAULT DIRECTORY

ACCESS PARAMETERS

LOCATION

REJECT LIMIT
TYPE
TYPE <access_driver_type> indicates the access driver of the external table. The access
driver is the application programming interface (API) that interprets the external data for
the database. If you do not specify TYPE, Oracle uses the default access driver,
ORACLE_LOADER. The other option is ORACLE_DATAPUMP.
DEFAULT DIRECTORY
The DEFAULT DIRECTORY clause is used to specify one or more Oracle database
directory objects that correspond to directories on the file system where the external data
sources may reside.
ACCESS PARAMETERS
The optional ACCESS PARAMETERS clause enables you to assign values to the
parameters of the specific access driver for this external table.
LOCATION
The LOCATION clause is used to specify one external locator for each external data
source. Usually, <location_specifier> is a file, but it need not be.
REJECT LIMIT
The REJECT LIMIT clause enables you to specify how many conversion errors can occur
during a query of the external data before an Oracle error is returned and the query is
aborted. The default value is 0.
Here is the syntax for using the ORACLE_DATAPUMP access driver.
CREATE TABLE <table_name>
ORGANIZATION EXTERNAL (TYPE ORACLE_DATAPUMP
DEFAULT DIRECTORY
ACCESS PARAMETERS ( )
LOCATION ()
PARALLEL 4
REJECT LIMIT UNLIMITED

AS
SELECT * FROM ;
Suppose that there is a flat file that has records in this format.
In this format the records are delimited by new lines, and the fields are all terminated by a
comma ( , ). The name of the file is /emp_dir/emp.dat.
To convert this file as the data source for an external table, whose metadata will reside in
the database, you need to create a directory object, emp_dir.
CREATE DIRECTORY emp_dir AS '/emp_dir';
Next you need to run this CREATE TABLE command. This sample code illustrates the
table specification to create an external table for the file /emp_dir/emp.dat.
CREATE TABLE oldemp (
fname char(25), lname CHAR(25))
ORGANIZATION EXTERNAL
(TYPE ORACLE_LOADER
DEFAULT DIRECTORY emp_dir
ACCESS PARAMETERS
(RECORDS DELIMITED BY NEWLINE
NOBADFILE
NOLOGFILE
FIELDS TERMINATED BY ','
(fname POSITION ( 1:20) CHAR,
lname POSITION (22:41) CHAR))
LOCATION ('emp.dat'))
PARALLEL 5
REJECT LIMIT 200;
The clauses used in the CREATE TABLE command are

TYPE

ACCESS PARAMETERS

PARALLEL

REJECT LIMIT
TYPE
The TYPE specification is given only to illustrate its use. ORACLE_LOADER is the default
access driver if not specified.
ACCESS PARAMETERS
The ACCESS PARAMETERS option provides values to parameters of the specific access
driver, which are interpreted by the access driver, not by the Oracle server.

PARALLEL
The PARALLEL clause enables five parallel execution servers to simultaneously scan the
external data sources (files) when executing the INSERT INTO TABLE statement. For
example, if PARALLEL=5 were specified, then more than one parallel execution server can
be working on a data source. Because external tables can be very large, for performance
reasons, it is advisable to specify the PARALLEL clause, or a parallel hint for the query.
REJECT LIMIT
The REJECT LIMIT clause specifies that if more than 200 conversion errors occur during
a query of the external data, then the query is aborted and an error is returned. These
conversion errors can arise when the access driver tries to transform the data in the data
file to match the external table definition.
After the CREATE TABLE command executes successfully, the OLDEMP external table
can be described and queried like a relational table.
An external table does not describe any data that is stored in the database and how data
is stored in the external source. Instead, it describes how the external table layer must
present the data to the server. It is the responsibility of the access driver and the external
table layer to do the necessary transformations required on the data in the data file so
that it matches the external table definition.
When the database server accesses data in an external source, it calls the appropriate
access driver to get the data from an external source in a form that the database server
expects. It is important to remember that the description of the data in the data source is
separate from the definition of the external table. The source file can contain more or
fewer fields than there are columns in the table. Also, the data types for fields in the data
source can be different from the columns in the table. The access driver ensures that the
data from the data source is processed so that it matches the definition of the external
table.
You can perform the unload and reload operations with external tables using the
ORACLE_DATAPUMP access driver.

Note
In the context of external tables, loading data refers to the act of data being read
from an external table and loaded into a table in the database. Unloading data
refers to the act of reading data from a table and inserting it into an external table.
This sample code illustrates the table specification to create an external table by using
the ORACLE_DATAPUMP access driver. Data is then populated into the two files:
emp1.exp and emp2.exp.
CREATE TABLE emp_ext
(employee_id, first_name, last_name)

ORGANIZATION EXTERNAL
(
TYPE ORACLE_DATAPUMP
DEFAULT DIRECTORY emp_dir
LOCATION
('emp1.exp','emp2.exp')
)
PARALLEL
AS
SELECT employee_id, first_name, last_name
FROM employees;
To populate data read from the EMPLOYEES table into an external table, you first create a
directory object, emp_dir.
CREATE DIRECTORY emp_dir AS '/emp_dir' ;
Next, you need to run the CREATE TABLE command.
CREATE TABLE emp_ext
(employee_id, first_name, last_name)
ORGANIZATION EXTERNAL
(
TYPE ORACLE_DATAPUMP
DEFAULT DIRECTORY emp_dir
LOCATION
('emp1.exp','emp2.exp')
)
PARALLEL
AS
SELECT employee_id, first_name, last_name
FROM employees;

Note
The emp_dir directory is the same as that created in the previous example using
ORACLE_LOADER.
You can query the external table by executing this code.
SELECT * FROM emp_ext;

Question
Which are true statements about the characteristics of external tables?

Options:
1.

Their data is stored inside the database

2.

Their metadata is stored outside the database

3.

They are read/write tables

4.

They cannot have indexes created on them

Answer
You cannot create indexes on external tables.
Option 1 is incorrect. The data of an external table is stored outside the database.
Option 2 is incorrect. The metadata of an external table is stored in the database.
Option 3 is incorrect. All externally organized tables are read-only. No DML
operations are possible.
Option 4 is correct. All externally organized tables do not allow DML operations.
They are read-only. You cannot create indexes on externally organized tables.

Question
Which clause is used during the creation of an external table to indicate the
access driver of the external table?
Options:
1.

EXTERNAL

2.

LOCATION

3.

REJECT LIMIT

4.

TYPE

Answer
The TYPE clause is used during the creation of an external table to indicate the
access driver of the external table.
Option 1 is incorrect. By specifying EXTERNAL in the ORGANIZATION clause, you
indicate that the table is a read-only table located outside the database.
EXTERNAL does not indicate the access driver of the external table.
Option 2 is incorrect. The LOCATION clause is used to specify one external locator
for each external data source. It is not used to indicate the access driver of an
external table.

Option 3 is incorrect. The REJECT LIMIT clause is not used to indicate the
access driver of the external table. It is used to specify how many conversion
errors can occur during a query of the external data before an Oracle error is
returned and the query is aborted.
Option 4 is correct. TYPE is used to indicate the access driver of the external
table. If you do not specify TYPE, Oracle uses the default access driver,
ORACLE_LOADER.

Summary
Oracle Flashback Table enables you to recover tables to a specified point in time with a
single statement. You can restore table data along with associated indexes and
constraints by using FLASHBACK mechanics.
You can create an external table by using the external_table clause. An external
table is a read-only table whose metadata is stored in the database and the data is stored
outside the database. You can use SQL, PL/SQL, and Java to query the data in an
external table.

Working with Tables, Indexes and Constraints


Learning objective

After completing this topic, you should be able to alter a table by dropping columns and
adding constraints and indexes.

Exercise overview
In this exercise, you are required to use the CREATE TABLE or ALTER TABLE
commands to add, modify, drop, and restore columns.
This involves the following tasks:

creating tables and modifying columns

dropping and restoring tables

dropping columns and using constraints

removing tables and creating indexes


You are an Oracle SQL administrator for a company. As part of your responsibilities to
update the employee information, you have to modify the structure of the table, create
new columns, copy information to the existing tables, and delete the tables created for
updating information.

You also need to add constraints to make sure that the employee is not assigned to a
nonexistent department.

Task 1: Adding and modifying columns


You need to use the CREATE TABLE statement to create two new tables. You will also
need to use the ALTER TABLE statement to change the table structure to allow for larger
values.

Supplement
Selecting the link title opens the resource in a new browser window.

Launch window
View the table instance chart.

Step 1 of 3
You want to create the EMP2 table based on the table instance chart provided. You
also need to verify that the table was created.
Identify the code that successfully completes this task.
Options:
1.

CREATE TABLE emp2


(id NUMBER(7), last_name VARCHAR2(7), first_name VARCHAR2(25),
dept_id NUMBER(25));
DESCRIBE emp2

2.

CREATE TABLE emp2


(id NUMBER(7), last_name VARCHAR2(25), first_name
VARCHAR2(25), dept_id NUMBER(7));
DESCRIBE emp2

3.

CREATE TABLE emp2


(id NUMBER 7, last_name VARCHAR2 25, first_name VARCHAR2 25,
dept_id NUMBER 7);
DESCRIBE emp2

4.

CREATE TABLE emp2


(id VARCHAR2(7), last_name NUMBER(25), first_name
VARCHAR2(25), dept_id NUMBER(7));
DESCRIBE emp2

Result

You should use this code to create the table


CREATE TABLE emp2
(id NUMBER(7),
last_name VARCHAR2(25),
first_name VARCHAR2(25),
dept_id NUMBER(7));
DESCRIBE emp2
Option 1 is incorrect. The VARCHAR2 data type for the LAST_NAME column should
have a variable-length character value of 25, and the NUMBER data type for the
DEPT_ID column should have a length value of 7.
Option 2 is correct. This statement will create a table called EMP2 with an ID
column having a maximum number of 7 digits, a LAST_NAME column having a
maximum of 25 characters, a FIRST_NAME column having a maximum of 25
characters, and a DEPT_ID column having a NUMBER data type value of 7.
Option 3 is incorrect. This statement is missing parentheses around the values for
the NUMBER and VARCHAR2 data types.
Option 4 is incorrect. The ID column should be created with a number data type
and the LAST_NAME column should be created with the VARCHAR2 data type.

Step 2 of 3
Which statement will modify the EMP2 table to allow for longer employee last
names, and verify that the table was created?
Options:
1.

ALTER TABLE emp2


MODIFY (first_name NUMBER(50));
DESCRIBE emp2

2.

ALTER TABLE emp2


MODIFY (first_name VARCHAR2 50);
DESCRIBE emp2

3.

ALTER TABLE emp2


MODIFY (last_name VARCHAR2(25));
DESCRIBE emp2

4.

ALTER TABLE emp2


MODIFY (last_name VARCHAR2(50));
DESCRIBE emp2

Result

You should use this code to allow for longer employee last names
ALTER TABLE emp2
MODIFY (last_name VARCHAR2(50));
DESCRIBE emp2
Option 1 is incorrect. The data type should be a VARCHAR2 data type not a
NUMBER data type. It should also allow for longer character values on the
LAST_NAME column and not the FIRST_NAME column as indicated.
Option 2 is incorrect. This statement is missing the parentheses around the value
for VARCHAR2 data type. It should also allow for longer character values on the
LAST_NAME column and not the FIRST_NAME column as indicated.
Option 3 is incorrect. This statement will not allow for longer employee last names
as the VARCHAR2 data type is still set to a length value of 25.
Option 4 is correct. This statement will alter the EMP2 table by modifying the value
of the data type for the LAST_NAME column to 50 characters instead of the original
maximum value of 25.

Step 3 of 3
Create the EMPLOYEES2 table based on the structure of the EMPLOYEES table.
Include only the EMPLOYEE_ID, FIRST_NAME, LAST_NAME, SALARY, and
DEPARTMENT_ID columns. Name the columns in your new table ID,
FIRST_NAME, LAST_NAME, SALARY, and DEPT_ID, respectively.
Options:
1.

CREATE TABLE employees2 AS


SELECT employee_id id, first_name, last_name,
department_id dept_id
FROM employees;

2.

CREATE TABLE employees2 AS


SELECT employee_id id, first_name, last_name, salary,
department_id dept_id
FROM employees;

3.

CREATE TABLE employees AS


SELECT employee_id id, first_name, last_name, salary,
department_id dept_id
FROM employees2;

4.

CREATE TABLE employees2 AS


SELECT employee_id, first_name, last_name, salary,
department_id
FROM employees;

Result
You should use this code to create the table
CREATE TABLE employees2 AS
SELECT employee_id id, first_name, last_name, salary,
department_id dept_id
FROM employees;
Option 1 is incorrect. This statement is missing the requested SALARY column
within the SELECT statement.
Option 2 is correct. This statement will create a table called EMPLOYEES2 based
on the structure of the EMPLOYEES table. It will only include the EMPLOYEE_ID,
FIRST_NAME, LAST_NAME, SALARY, and DEPARTMENT_ID columns. It will also
rename the EMPLOYEE_ID column to ID and the DEPARTMENT_ID column to
DEPT_ID.
Option 3 is incorrect. The CREATE TABLE statement should be followed by the
table name EMPLOYEES2 and the FROM clause should be followed by the table
name EMPLOYEES.
Option 4 is incorrect. This statement is missing the column aliases of ID and
DEPT_ID for the EMPLOYEE_ID and DEPARTMENT_ID columns.

Task 2: Dropping and restoring tables


You now want to delete the EMP2 table that you previously created and then view the
recycle bin to see if the table is present.

Step 1 of 3
You need to delete the EMP2 table that stored longer employee last names.
Type the code to drop the EMP2 table that was previously created.

MISSING CODE

Result
You use the code
DROP TABLE emp2;

to drop a table. Oracle Database provides this feature for dropping tables. When
you drop a table, the database does not immediately release the space associated
with the table. Rather, the database renames the table and places it in a recycle
bin.

Step 2 of 3
You now want to verify that the EMP2 table is present in the recyclin bin. You want
to view the original name, the operation on how the table was deleted, and at what
time it was dropped.
Type the code to query the recycle bin.

MISSING CODE

Result
You use the code
SELECT original_name, operation, droptime FROM recyclebin;
to query the recycle bin. The recycle bin is actually a data dictionary table
containing information about dropped objects. Dropped tables and any associated
objectssuch as indexes, constraints, nested tables, and so on are not
removed and still occupy space. They continue to count against user space quotas
until specifically purged from the recycle bin.
You now want to restore the EMP2 table to a state before the DROP statement.

Step 3 of 3
You need to restore the EMP2 table to a state before the DROP statement and
verify that is was restored.
Type the code to restore the EMP2 table.

<Missing code>
DESC emp2;

Result
You use the code
FLASHBACK TABLE emp2 TO BEFORE DROP;
DESC emp2;
to restore a table to a state before the DROP statement. Oracle Flashback Table

enables you to recover tables to a specified point in time with a single statement.
You can restore table data along with associated indexes, and constraints, while
the database is online, undoing changes to only the specified tables.

Task 3: Dropping columns and using constraints


You now want to drop the FIRST_NAME column and mark the DEPT_ID column as
UNUSED in the EMPLOYEES2 table. You will also add a PRIMARY KEY constraint and a
CHECK constraint to a table.

Step 1 of 4
You need to drop the FIRST_NAME column from the EMPLOYEES2 table and
confirm your modification by checking the description of the table.
Type the code to drop the FIRST_NAME column from the table.

ALTER TABLE employees2


MISSING CODE
DESCRIBE employees2

Result
You use the code
DROP COLUMN first_name;
to drop the FIRST_NAME column from the EMPLOYEES2 table. You can drop a
column from a table by using the ALTER TABLE statement with the DROP
COLUMN clause. Remember, dropping a column can take some time if the column
has a large number of values. In this case, it may be better to set it to be unused
and drop it when there are fewer users on the system to avoid extended locks.

Step 2 of 4
You need to mark the DEPT_ID column as UNUSED in the EMPLOYEES2 table.
Complete the code.

ALTER TABLE employees2


MISSING CODE
DESCRIBE employees2

Result

You use the code


ALTER TABLE employees2
SET UNUSED (dept_id);
DESCRIBE employees2
to mark the DEPT_ID column as UNUSED in the EMPLOYEES2 table. The SET
UNUSED option marks one or more columns as unused so that they can be
dropped when the demand on system resources is lower. Specifying this clause
does not actually remove the target columns from each row in the table (that is, it
does not restore the disk space used by these columns).

Step 3 of 4
You need to add a table-level PRIMARY KEY constraint to the EMP2 table on the ID
column. The name of the constraint should be my_emp_id_pk and should be
named at creation.
Identify the code that successfully completes this task.
Options:
1.

ALTER TABLE emp2


ADD CONSTRAINT my_emp_id_pk PRIMARY KEY (id);

2.

ALTER TABLE emp2


ADD CONSTRAINT my_empid_pk PRIMARY KEY employee_id;

3.

ALTER TABLE emp2


MODIFY CONSTRAINT my_emp_id_pk PRIMARY KEY (employee_id);

4.

ALTER TABLE emp2


MODIFY CONSTRAINT my_emp_id_pk PRIMARY KEY (id);

Result
You should use this code to add a table-level PRIMARY KEY constraint to the
EMP2 table on the ID column.
ALTER TABLE emp2
ADD CONSTRAINT my_emp_id_pk PRIMARY KEY (id);
Option 1 is correct. This statement will add a table-level PRIMARY KEY constraint
to the EMP2 table on the ID column.
Option 2 is incorrect. The name of the constraint should be my_emp_id_pk, not
my_empid_pk. This statement is also missing the parentheses around the ID
column.
Option 3 is incorrect. You add a constraint to an existing table by using the ALTER
TABLE statement with the ADD clause not the MODIFY clause. The MODIFY clause

is used to add a NOT NULL constraint to an existing column. This statement is


also missing the parentheses around the ID column.
Option 4 is incorrect. You add a constraint to an existing table by using the ALTER
TABLE statement with the ADD clause, not the MODIFY clause. The MODIFY
clause is used to add a NOT NULL constraint to an existing column.

Step 4 of 4
You need to modify the EMP2 table by adding a COMMISSION column of the
NUMBER data type, precision 2, scale 2, and add a constraint called
my_emp_comm_ck to the COMMISSION column that ensures that a commission
value is greater than zero.
Complete the code.

ALTER TABLE emp2


MISSING CODE

Result
You use the code
ALTER TABLE emp2
ADD commission NUMBER(2,2) CONSTRAINT my_emp_comm_ck CHECK
(commission > 0);
to add a column to the EMP2 table by using the ADD clause in an ALTER TABLE
statement, which at the same time adds the my_emp_comm_ck check constraint
on the COMMISSION column.

Task 4: Removing tables and creating indexes


You now want to completely remove the EMP2 table from the database. You then need to
create an index for a PRIMARY KEY column.

Step 1 of 2
You need to drop the EMP2 table so that it cannot be restored and check the
recycle bin.
Complete the code.

<Missing Code>
SELECT original_name, operation, droptime
FROM recyclebin;

Result
You use the code
DROP TABLE emp2 PURGE;
SELECT original_name, operation, droptime
FROM recyclebin;
to drop the EMP2 table so that it cannot be restored. You specify PURGE only if you
want to drop the table and release the space associated with it in a single step. If
you specify PURGE, then the database does not place the table and its dependent
objects into the recycle bin.

Step 2 of 2
You need to create the DEPT_NAMED_INDEX table with a PRIMARY KEY
constraint on the DEPTNO column. You want to create an index named
dept_pk_idx for the PRIMARY KEY column.
Complete the code.

CREATE TABLE DEPT_NAMED_INDEX


(deptno NUMBER(4)
MISSING CODE
(CREATE INDEX dept_pk_idx ON
DEPT_NAMED_INDEX(deptno)),
dname VARCHAR2(30));

Result
You use the code
PRIMARY KEY USING INDEX
to create the DEPT_NAMED_INDEX table with a PRIMARY KEY constraint. You
use the PRIMARY KEY USING INDEX clause to create an index for the PRIMARY
KEY column with the CREATE INDEX statement.

Anda mungkin juga menyukai