Transaction Management

This chapter defines a transaction and describes how you can manage your work using transactions. It includes:

  • Introduction to Transactions
  • Transaction Management Overview
  • Discrete Transaction Management
  • Autonomous Transactions

Introduction to Transactions

A transaction is a logical unit of work that contains one or more SQL statements. A transaction is an atomic unit. The effects of all the SQL statements in a transaction can be either all committed (applied to the database) or all rolled back (undone from the database).

A transaction begins with the first executable SQL statement. A transaction ends when it is committed or rolled back, either explicitly with a COMMIT or ROLLBACK statement or implicitly when a DDL statement is issued.

To illustrate the concept of a transaction, consider a banking database. When a bank customer transfers money from a savings account to a checking account, the transaction can consist of three separate operations:

  • Decrement the savings account
  • Increment the checking account
  • Record the transaction in the transaction journal

Oracle must allow for two situations. If all three SQL statements can be performed to maintain the accounts in proper balance, the effects of the transaction can be applied to the database. However, if a problem such as insufficient funds, invalid account number, or a hardware failure prevents one or two of the statements in the transaction from completing, the entire transaction must be rolled back so that the balance of all accounts is correct.

Figure 16-1 illustrates the banking transaction example.

Figure 16-1 A Banking Transaction

Text description of cncpt025.gif follows

Statement Execution and Transaction Control

A SQL statement that runs successfully is different from a committed transaction. Executing successfully means that a single statement was:

  • Parsed
  • Found to be a valid SQL construction
  • Run without error as an atomic unit. For example, all rows of a multirow update are changed.

However, until the transaction that contains the statement is committed, the transaction can be rolled back, and all of the changes of the statement can be undone. A statement, rather than a transaction, runs successfully.

Committing means that a user has explicitly or implicitly requested that the changes in the transaction be made permanent. An explicit request means that the user issued a COMMIT statement. An implicit request can be made through normal termination of an application or in data definition language, for example. The changes made by the SQL statements of your transaction become permanent and visible to other users only after your transaction has been committed. Only other users' transactions that started after yours will see the committed changes.

You can name a transaction using the SET TRANSACTION ... NAME statement before you start the transaction. This makes it easier to monitor long-running transactions and to resolve in-doubt distributed transactions.

Statement-Level Rollback

If at any time during execution a SQL statement causes an error, all effects of the statement are rolled back. The effect of the rollback is as if that statement had never been run. This operation is a statement-level rollback.

Errors discovered during SQL statement execution cause statement-level rollbacks. An example of such an error is attempting to insert a duplicate value in a primary key. Single SQL statements involved in a deadlock (competition for the same data) can also cause a statement-level rollback. Errors discovered during SQL statement parsing, such as a syntax error, have not yet been run, so they do not cause a statement-level rollback.

A SQL statement that fails causes the loss only of any work it would have performed itself. It does not cause the loss of any work that preceded it in the current transaction. If the statement is a DDL statement, then the implicit commit that immediately preceded it is not undone.

The user can also request a statement-level rollback by issuing a ROLLBACK statement.


Note:

Users cannot directly refer to implicit savepoints in rollback statements.


Resumable Space Allocation

Oracle provides a means for suspending, and later resuming, the execution of large database operations in the event of space allocation failures. This enables an administrator to take corrective action, instead of the Oracle database server returning an error to the user. After the error condition is corrected, the suspended operation automatically resumes. This feature is called resumable space allocation and the statements that are affected are called resumable statements.

A statement runs in a resumable mode only when the client explicitly enables resumable semantics for the session using the ALTER SESSION statement.

Resumable space allocation is suspended when one of the following conditions occur:

  • Out of space condition
  • Maximum extents reached condition
  • Space quota exceeded condition

For nonresumable space allocation, these conditions result in errors and the statement is rolled back.

Suspending a statement automatically results in suspending the transaction. Thus all transactional resources are held through a statement suspend and resume.

When the error condition disappears (for example, as a result of user intervention or perhaps sort space released by other queries), the suspended statement automatically resumes execution.

Transaction Management Overview

A transaction in Oracle begins when the first executable SQL statement is encountered. An executable SQL statement is a SQL statement that generates calls to an instance, including DML and DDL statements.

When a transaction begins, Oracle assigns the transaction to an available undo tablespace or rollback segment to record the rollback entries for the new transaction.

A transaction ends when any of the following occurs:

  • A user issues a COMMIT or ROLLBACK statement without a SAVEPOINT clause.
  • A user runs a DDL statement such as CREATE, DROP, RENAME, or ALTER. If the current transaction contains any DML statements, Oracle first commits the transaction, and then runs and commits the DDL statement as a new, single statement transaction.
  • A user disconnects from Oracle. The current transaction is committed.
  • A user process terminates abnormally. The current transaction is rolled back.

After one transaction ends, the next executable SQL statement automatically starts the following transaction.


Note:

Applications should always explicitly commit or roll back transactions before program termination.


Commit Transactions

Committing a transaction means making permanent the changes performed by the SQL statements within the transaction.

Before a transaction that modifies data is committed, the following has occurred:

  • Oracle has generated rollback segment records in buffers in the SGA that store rollback segment data. The rollback information contains the old data values changed by the SQL statements of the transaction.
  • Oracle has generated redo log entries in the redo log buffer of the SGA. The redo log record contains the change to the data block and the change to the rollback block. These changes may go to disk before a transaction is committed.
  • The changes have been made to the database buffers of the SGA. These changes may go to disk before a transaction is committed.


    Note:

    The data changes for a committed transaction, stored in the database buffers of the SGA, are not necessarily written immediately to the datafiles by the database writer (DBWn) background process. This writing takes place when it is most efficient for the database to do so. It can happen before the transaction commits or, alternatively, it can happen some time after the transaction commits.


When a transaction is committed, the following occurs:

  1. The internal transaction table for the associated rollback segment records that the transaction has committed, and the corresponding unique system change number (SCN) of the transaction is assigned and recorded in the table.
  2. The log writer process (LGWR) writes redo log entries in the SGA's redo log buffers to the online redo log file. It also writes the transaction's SCN to the online redo log file. This atomic event constitutes the commit of the transaction.
  3. Oracle releases locks held on rows and tables.
  4. Oracle marks the transaction complete.

Rollback of Transactions

Rolling back means undoing any changes to data that have been performed by SQL statements within an uncommitted transaction. Oracle uses undo tablespaces or rollback segments to store old values. The redo log contains a record of changes.

Oracle lets you roll back an entire uncommitted transaction. Alternatively, you can roll back the trailing portion of an uncommitted transaction to a marker called a savepoint.

All types of rollbacks use the same procedures:

  • Statement-level rollback (due to statement or deadlock execution error)
  • Rollback to a savepoint
  • Rollback of a transaction due to user request
  • Rollback of a transaction due to abnormal process termination
  • Rollback of all outstanding transactions when an instance terminates abnormally
  • Rollback of incomplete transactions during recovery

In rolling back an entire transaction, without referencing any savepoints, the following occurs:

  1. Oracle undoes all changes made by all the SQL statements in the transaction by using the corresponding undo tablespace or rollback segment.
  2. Oracle releases all the transaction's locks of data.
  3. The transaction ends.

Savepoints In Transactions

You can declare intermediate markers called savepoints within the context of a transaction. Savepoints divide a long transaction into smaller parts.

Using savepoints, you can arbitrarily mark your work at any point within a long transaction. You then have the option later of rolling back work performed before the current point in the transaction but after a declared savepoint within the transaction. For example, you can use savepoints throughout a long complex series of updates, so if you make an error, you do not need to resubmit every statement.

Savepoints are similarly useful in application programs. If a procedure contains several functions, then you can create a savepoint before each function begins. Then, if a function fails, it is easy to return the data to its state before the function began and re-run the function with revised parameters or perform a recovery action.

After a rollback to a savepoint, Oracle releases the data locks obtained by rolled back statements. Other transactions that were waiting for the previously locked resources can proceed. Other transactions that want to update previously locked rows can do so.

When a transaction is rolled back to a savepoint, the following occurs:

  1. Oracle rolls back only the statements run after the savepoint.
  2. Oracle preserves the specified savepoint, but all savepoints that were established after the specified one are lost.
  3. Oracle releases all table and row locks acquired since that savepoint but retains all data locks acquired previous to the savepoint.

The transaction remains active and can be continued.


Note:

Whenever a session is waiting on a transaction, a rollback to savepoint does not free row locks. To make sure a transaction doesn't hang if it cannot obtain a lock, use

FOR UPDATE ... NOWAIT

before issuing UPDATE or DELETE statements.


Transaction Naming

You can name a transaction, using a simple and memorable text string. This name is a reminder of what the transaction is about. Transaction names replace commit comments for distributed transactions, with the following advantages:

  • It is easier to monitor long-running transactions and to resolve in-doubt distributed transactions.
  • You can view transaction names along with transaction IDs in applications. For example, a database administrator can view transaction names in Enterprise Manager when monitoring system activity.
  • Transaction names are written to the transaction auditing redo record, if compatibility is set to Oracle9i or higher.
  • LogMiner can use transaction names to search for a specific transaction from transaction auditing records in the redo log.
  • You can use transaction names to find a specific transaction in data dictionary tables, such as V$TRANSACTION.

How Transactions Are Named

Name a transaction using the SET TRANSACTION ... NAME statement before you start the transaction.

When you name a transaction, you associate the transaction's name with its ID. Transaction names do not have to be unique; different transactions can have the same transaction name at the same time by the same owner. You can use any name that enables you to distinguish the transaction.

Commit Comment

In previous releases, you could associate a comment with a transaction by using a commit comment. However, a comment can be associated with a transaction only when a transaction is being committed.

Commit comments are still supported for backward compatibility. However, Oracle Corporation strongly recommends that you use transaction names. Commit comments are ignored in named transactions.


Note:

In a future release, commit comments will be deprecated.


The Two-Phase Commit Mechanism

In a distributed database, Oracle must coordinate transaction control over a network and maintain data consistency, even if a network or system failure occurs.

A distributed transaction is a transaction that includes one or more statements that update data on two or more distinct nodes of a distributed database.

A two-phase commit mechanism guarantees that all database servers participating in a distributed transaction either all commit or all roll back the statements in the transaction. A two-phase commit mechanism also protects implicit DML operations performed by integrity constraints, remote procedure calls, and triggers.

The Oracle two-phase commit mechanism is completely transparent to users who issue distributed transactions. In fact, users need not even know the transaction is distributed. A COMMIT statement denoting the end of a transaction automatically triggers the two-phase commit mechanism to commit the transaction. No coding or complex statement syntax is required to include distributed transactions within the body of a database application.

The recoverer (RECO) background process automatically resolves the outcome of in-doubt distributed transactions--distributed transactions in which the commit was interrupted by any type of system or network failure. After the failure is repaired and communication is reestablished, the RECO process of each local Oracle server automatically commits or rolls back any in-doubt distributed transactions consistently on all involved nodes.

In the event of a long-term failure, Oracle allows each local administrator to manually commit or roll back any distributed transactions that are in doubt as a result of the failure. This option enables the local database administrator to free any locked resources that are held indefinitely as a result of the long-term failure.

If a database must be recovered to a point in the past, Oracle's recovery facilities enable database administrators at other sites to return their databases to the earlier point in time also. This operation ensures that the global database remains consistent.

Discrete Transaction Management

Application developers can improve the performance of short, nondistributed transactions by using the BEGIN_DISCRETE_TRANSACTION procedure. This procedure streamlines transaction processing so that short transactions can run more rapidly.

During a discrete transaction, all changes made to any data are deferred until the transaction commits. Of course, other concurrent transactions are unable to see the uncommitted changes of a transaction whether the transaction is discrete or not.

The following events occur during a discrete transaction:

  1. Oracle generates redo information, but stores it in a separate location in memory.
  2. When the transaction issues a commit request, Oracle writes the redo information to the redo log file along with other group commits.
  3. Oracle applies the changes to the database block directly to the block.
  4. Oracle returns control to the application after the commit completes.

This transaction design eliminates the need to generate undo information, because the block is not modified until the transaction is committed, and the redo information is stored in the redo log buffers.

There is no interaction between discrete transactions, which always generate redo, and the NOLOGGING mode, which applies only to direct path operations. Discrete transactions can therefore be issued against tables that have the NOLOGGING attribute set.

Autonomous Transactions

Autonomous transactions are independent transactions that can be called from within another transaction. An autonomous transaction lets you leave the context of the calling transaction, perform some SQL operations, commit or roll back those operations, and then return to the calling transaction's context and continue with that transaction.

Once invoked, an autonomous transaction is totally independent of the main transaction that called it. It does not see any of the uncommitted changes made by the main transaction and does not share any locks or resources with the main transaction. Changes made by an autonomous transaction become visible to other transactions upon commit of the autonomous transactions.

One autonomous transaction can call another. There are no limits, other than resource limits, on how many levels of autonomous transactions can be called.

Deadlocks are possible between an autonomous transaction and its calling transaction. Oracle detects such deadlocks and returns an error. The application developer is responsible for avoiding deadlock situations.

Autonomous transactions are useful for implementing actions that need to be performed independently, regardless of whether the calling transaction commits or rolls back, such as transaction logging and retry counters.

Autonomous PL/SQL Blocks

You can call autonomous transactions from within a PL/SQL block. Use the pragma AUTONOMOUS_TRANSACTION. A pragma is a compiler directive. You can declare the following kinds of PL/SQL blocks to be autonomous:

  • Stored procedure or function
  • Local procedure or function
  • Package
  • Type method
  • Top-level anonymous block

When an autonomous PL/SQL block is entered, the transaction context of the caller is suspended. This operation ensures that SQL operations performed in this block (or other blocks called from it) have no dependence or effect on the state of the caller's transaction context.

When an autonomous block invokes another autonomous block or itself, the called block does not share any transaction context with the calling block. However, when an autonomous block invokes a non-autonomous block (that is, one that is not declared to be autonomous), the called block inherits the transaction context of the calling autonomous block.

Transaction Control Statements in Autonomous Blocks

Transaction control statements in an autonomous PL/SQL block apply only to the currently active autonomous transaction. Examples of such statements are:

SET TRANSACTION
COMMIT
ROLLBACK
SAVEPOINT
ROLLBACK TO SAVEPOINT

Similarly, transaction control statements in the main transaction apply only to that transaction and not to any autonomous transaction that it calls. For example, rolling back the main transaction to a savepoint taken before the beginning of an autonomous transaction does not roll back the autonomous transaction.

Oracle Commands

Oracle divides database command into six groups. The six command groups are:

1. Data definition language (DDL) commands. These commands create tables, create declarative constraints, create stored procedures, and create triggers. Most types of database objects (table, views, procedures, triggers, tablespace, users, and so on) have CREATE, ALTER, and DROP commands; in other words, there are many DDL commands.

2. Data manipulation language (DML) commands. Data manipulation language (DML) commands let users move data into and out of a database. DML commands include SELECT, INSERT, UPDATE, and DELETE.

3. Data control language (DLC) commands. Data control language are commands to control which users can access specific data (tables , views, and so on). Data control statements include the GRANT and REVOKE commands, which you sue to grant and revoke privileges, as well as the SET ROLE command, which enables or disables roles in your current session.

4. Transaction control commands. Transaction control commands are used to identify the start and stop point of a transaction, to rollback a transaction, and to define check and savepoints. Transaction control commands include COMMIT, ROLLBACK, and SAVEPOINT.

5. System control commands. These are database administrative commands.

6. Embedded SQL commands. These commands support embedded SQL within application third-generation language programs. This allows C programs to execute SQL statements and called stored procedures from within the high-level source code.

Oracle concepts

Oracle Architecture
Oracle Commands
Grant user privileges
Transaction Management

Oracle Concepts - grant user privileges

Once we have created a user, we probably want that user to be able to do something in our database. A created user has no privileges, they can not even connect to the database. In this section we will address this problem by learning how to give users the privileges they need to actually get some work done. First we will look at system privileges, followed by object privileges. We will then look at how you can use roles to make user administration much easier.

Oracle System Privileges

System privileges allow the user to perform system level activities. This might include such things as being able to actually connect to the system, or it might include the ability to do things like create objects in schemas other than your own schema. In the next sections we will discuss the grant command, which you use to grant system privileges. Also the revoke command is used to revoke privileges from users.

Granting Oracle System Level Privileges

The grant command is used to grant system level privileges. System level privileges are those privileges that you need to actually do something on the system. For example you grant system level privileges to a user so that they can:

* Connect to the database (create session)

* Create objects (create table, create index)

* Perform DBA activities, like backup the database (SYSDBA, SYSOPER)

* Alter session related parameters (alter session)

Basically, even if you create a user account, it will not be able to do anything until you have granted it a basic set of privileges. Typically you would always grant the create session privilege so that the user can connect to the database.

The grant command is pretty simple to use, you just need to know what privilege you want to grant and who you want to grant that privilege to. For example, if you want the user to be able to create an index, you would grant that user the create index privilege with the grant command as seen here:

GRANT CREATE INDEX TO Robert;

There are a number of different privileges that you can assign to a given user, way to many to list here. You can find a list of the different privileges that can be assigned to a given user in the Oracle SQL Reference Guide under the grant command documentation.

You can also grant multiple privileges in the same grant command by simply separating the privileges by a comma as seen in this example:

GRANT CREATE INDEX, SELECT ANY TABLE TO Robert;

Note the use of the word “ANY” in “SELECT ANY TABLE.” Using the ANY keyword in reference to a system privilege means that the user can perform the privilege on any objects owned by any user except for SYS. By default, if you are granted a privilege, you cannot assign your privilege to others. You can’t grant or revoke that privilege to or from anyone else. Sometime you want to grant privileges to users and have them be able to grant those privileges to other users. When this is the case, we include the with admin keyword in the grant command. When this keyword is used, it will allow the user granted the privilege to grant that privilege to other users. Here is an example of the usage of the with admin option keyword.

GRANT CREATE INDEX TO Robert WITH ADMIN OPTION;

Revoking System Level Privileges

The revoke command is used to revoke system level privileges that were previously granted with the grant command. Simply enter the privilege you wish to revoke in the body of the revoke command as seen in this example:

REVOKE CREATE INDEX FROM Robert;

To be able to revoke a privilege from another user, you must have been granted that privilege with the admin option, as demonstrated earlier in this section. Revoking system level privileges will only impact the user that you are revoking the privileges from. Any user that was granted system privileges by that user will still continue to have those privileges.

You can revoke all privileges from a user with the all privileges option of the revoke command as seen in this example:

REVOKE ALL PRIVILEGES FROM Robert;

Oracle Object Privileges

Once you have created users and given them system privileges, they will start creating objects (and as DBA you too will be creating objects no doubt!). Once objects are created, only the user who created those objects will be able to actually do anything with them. This is not particularly useful since you don’t want to be giving out your user id and password to everyone in the world. Oracle gives us the grant and revoke commands so that we can give other users access to objects in the database. Let’s look at these commands in more detail.

Granting Object Level Privileges

In order to allow other users to access your objects you can use the grant command (yes, the very same grant command used to grant system privileges) to allow different kinds of access to your objects. For example, we can grant the user TOM access to the EMP table in the SCOTT account (or schema) with this command:

GRANT SELECT ON emp TO scott;

Only the schema that owns the object can grant privileges to that object unless the with grant option is included in the command. The with grant option allows you to give the user you are assigning the privilege to the right to grant that privilege to other users. Here is an example of the use of the with grant option:

GRANT SELECT ON emp TO scott WITH GRANT OPTION

Revoking Object Level Privileges

When we no longer wish a user to have access rights to an object we can use the revoke command to remove those rights as seen in this example:

REVOKE SELECT on emp FROM scott;

There is one major difference in the revocation of object privileges and system privileges. With objects, if you revoke a privilege from a user who had been granted it previously with the with grant option, Oracle acts a bit different. In this case, the revoke operation will affect not only the user that you are revoking the privilege from, but all other users who that user had granted privileges to will have those privileges revoked as well. Hence, be careful revoking object privileges, you might find that you end up breaking something!

SQL: VIEWS

A view is, in essence, a virtual table. It does not physically exist. Rather, it is created by a query joining one or more tables.

Creating a VIEW

The syntax for creating a VIEW is:

CREATE VIEW view_name AS
SELECT columns
FROM table
WHERE predicates;


For example:

CREATE VIEW sup_orders AS
SELECT suppliers.supplier_id, orders.quantity, orders.price
FROM suppliers, orders
WHERE suppliers.supplier_id = orders.supplier_id
and suppliers.supplier_name = 'IBM';

This would create a virtual table based on the result set of the select statement. You can now query the view as follows:

SELECT *
FROM sup_orders;


Updating a VIEW

You can update a VIEW without dropping it by using the following syntax:

CREATE OR REPLACE VIEW view_name AS
SELECT columns
FROM table
WHERE predicates;


For example:

CREATE or REPLACE VIEW sup_orders AS
SELECT suppliers.supplier_id, orders.quantity, orders.price
FROM suppliers, orders
WHERE suppliers.supplier_id = orders.supplier_id
and suppliers.supplier_name = 'Microsoft';


Dropping a VIEW

The syntax for dropping a VIEW is:

DROP VIEW view_name;

For example:

DROP VIEW sup_orders;


Frequently Asked Questions


Question: Can you update the data in a view?

Answer: A view is created by joining one or more tables. When you update record(s) in a view, it updates the records in the underlying tables that make up the view.

So, yes, you can update the data in a view providing you have the proper privileges to the underlying tables.

SQL: Local Temporary tables

Local temporary tables are distinct within modules and embedded SQL programs within SQL sessions.

The basic syntax is:

DECLARE LOCAL TEMPORARY TABLE table_name ( ...);

SQL: Global Temporary tables

Global temporary tables are distinct within SQL sessions.

The basic syntax is:

CREATE GLOBAL TEMPORARY TABLE table_name ( ...);


For example:

CREATE GLOBAL TEMPORARY TABLE supplier
( supplier_id numeric(10) not null,

supplier_name varchar2(50) not null,

contact_name varchar2(50)
)


This would create a global temporary table called supplier .

SQL: DROP Table

The basic syntax for a DROP TABLE is:

DROP TABLE table_name;


For example:

DROP TABLE supplier;

This would drop table called supplier.

SQL: ALTER Table

The ALTER TABLE command allows you to add, modify, or drop a column from an existing table.


Adding column(s) to a table

Syntax #1

To add a column to an existing table, the ALTER TABLE syntax is:

ALTER TABLE table_name
ADD column_name column-definition;

For example:

ALTER TABLE supplier
ADD supplier_name varchar2(50);

This will add a column called supplier_name to the supplier table.


Syntax #2

To add multiple columns to an existing table, the ALTER TABLE syntax is:

ALTER TABLE table_name
ADD ( column_1 column-definition,

column_2 column-definition,

...

column_n column_definition );

For example:

ALTER TABLE supplier
ADD ( supplier_name varchar2(50),

city varchar2(45) );

This will add two columns (supplier_name and city) to the supplier table.


Modifying column(s) in a table

Syntax #1

To modify a column in an existing table, the ALTER TABLE syntax is:

ALTER TABLE table_name
MODIFY column_name column_type;

For example:

ALTER TABLE supplier
MODIFY supplier_name varchar2(100) not null;

This will modify the column called supplier_name to be a data type of varchar2(100) and force the column to not allow null values.


Syntax #2

To modify multiple columns in an existing table, the ALTER TABLE syntax is:

ALTER TABLE table_name
MODIFY ( column_1 column_type,

column_2 column_type,

...

column_n column_type );

For example:

ALTER TABLE supplier
MODIFY ( supplier_name varchar2(100) not null,

city varchar2(75) );

This will modify both the supplier_name and city columns.


Drop column(s) in a table

Syntax #1

To drop a column in an existing table, the ALTER TABLE syntax is:

ALTER TABLE table_name
DROP COLUMN column_name;

For example:

ALTER TABLE supplier
DROP COLUMN supplier_name;

This will drop the column called supplier_name from the table called supplier.


Rename column(s) in a table
(NEW in Oracle 9i Release 2)

Syntax #1

Starting in Oracle 9i Release 2, you can now rename a column.

To rename a column in an existing table, the ALTER TABLE syntax is:

ALTER TABLE table_name
RENAME COLUMN old_name to new_name;

For example:

ALTER TABLE supplier
RENAME COLUMN supplier_name to sname;

This will rename the column called supplier_name to sname.

SQL: CREATE Table from another table

You can also create a table from an existing table by copying the existing table's columns.

It is important to note that when creating a table in this way, the new table will be populated with the records from the existing table (based on the SELECT Statement).


Syntax #1 - Copying all columns from another table

The basic syntax is:

CREATE TABLE new_table
AS (SELECT * FROM old_table);


For example:

CREATE TABLE suppliers
AS (SELECT *
FROM companies
WHERE id > 1000);

This would create a new table called suppliers that included all columns from the companies table.

If there were records in the companies table, then the new suppliers table would also contain the records selected by the SELECT statement.


Syntax #2 - Copying selected columns from another table

The basic syntax is:

CREATE TABLE new_table
AS (SELECT column_1, column2, ... column_n FROM old_table);


For example:

CREATE TABLE suppliers
AS (SELECT id, address, city, state, zip
FROM companies
WHERE id > 1000);

This would create a new table called suppliers, but the new table would only include the specified columns from the companies table.

Again, if there were records in the companies table, then the new suppliers table would also contain the records selected by the SELECT statement.


Syntax #3 - Copying selected columns from multiple tables

The basic syntax is:

CREATE TABLE new_table
AS (SELECT column_1, column2, ... column_n
FROM old_table_1, old_table_2, ... old_table_n);


For example:

CREATE TABLE suppliers
AS (SELECT companies.id, companies.address, categories.cat_type
FROM companies, categories
WHERE companies.id = categories.id
AND companies.id > 1000);

This would create a new table called suppliers based on columns from both the companies and categories tables.

SQL: CREATE Table

The basic syntax for a CREATE TABLE is:

CREATE TABLE table_name
(column1 datatype null/not null,
column2 datatype null/not null,
...
);

Each column must have a datatype. The column should either be defined as "null" or "not null" and if this value is left blank, the database assumes "null" as the default.


For example:

CREATE TABLE supplier
( supplier_id numeric(10) not null,

supplier_name varchar2(50) not null,

contact_name varchar2(50)
)

SQL Topics: Tables

CREATE Table

CREATE Table from another table


ALTER Table

DROP Table


Global Temporary tables

Local Temporary tables

SQL: DELETE Statement

The DELETE statement allows you to delete a single record or multiple records from a table.

The syntax for the DELETE statement is:

DELETE FROM table
WHERE predicates;


Example #1 - Simple example

Let's take a look at a simple example:

DELETE FROM suppliers
WHERE supplier_name = 'IBM';

This would delete all records from the suppliers table where the supplier_name is IBM.

You may wish to check for the number of rows that will be deleted. You can determine the number of rows that will be deleted by running the following SQL statement before performing the delete.

SELECT count(*)
FROM suppliers
WHERE supplier_name = 'IBM';


Example #2 - More complex example

You can also perform more complicated deletes.

You may wish to delete records in one table based on values in another table. Since you can't list more than one table in the FROM clause when you are performing a delete, you can use the EXISTS clause.

For example:

DELETE FROM suppliers
WHERE EXISTS
( select customers.name
from customers
where customers.customer_id = suppliers.supplier_id
and customers.customer_name = 'IBM' );

This would delete all records in the suppliers table where there is a record in the customers table whose name is IBM, and the customer_id is the same as the supplier_id.

Learn more about the EXISTS condition.

If you wish to determine the number of rows that will be deleted, you can run the following SQL statement before performing the delete.

SELECT count(*) FROM suppliers
WHERE EXISTS
( select customers.name
from customers
where customers.customer_id = suppliers.supplier_id
and customers.customer_name = 'IBM' );


Frequently Asked Questions


Question: How would I write an SQL statement to delete all records in TableA whose data in field1 & field2 DO NOT match the data in fieldx & fieldz of TableB?

Answer: You could try something like this:

DELETE FROM TableA
WHERE NOT EXISTS
( select *
from TableB
where TableA .field1 = TableB.fieldx
and TableA .field2 = TableB.fieldz );

SQL: INSERT Statement

The INSERT statement allows you to insert a single record or multiple records into a table.

The syntax for the INSERT statement is:

INSERT INTO table
(column-1, column-2, ... column-n)
VALUES
(value-1, value-2, ... value-n);


Example #1 - Simple example

Let's take a look at a very simple example.

INSERT INTO suppliers
(supplier_id, supplier_name)
VALUES
(24553, 'IBM');

This would result in one record being inserted into the suppliers table. This new record would have a supplier_id of 24553 and a supplier_name of IBM.


Example #2 - More complex example

You can also perform more complicated inserts using sub-selects.

For example:

INSERT INTO suppliers
(supplier_id, supplier_name)
SELECT account_no, name
FROM customers
WHERE city = 'Newark';

By placing a "select" in the insert statement, you can perform multiples inserts quickly.

With this type of insert, you may wish to check for the number of rows being inserted. You can determine the number of rows that will be inserted by running the following SQL statement before performing the insert.

SELECT count(*)
FROM customers
WHERE city = 'Newark';


Frequently Asked Questions


Question: I am setting up a database with clients. I know that you use the "insert" statement to insert information in the database, but how do I make sure that I do not enter the same client information again?

Answer: You can make sure that you do not insert duplicate information by using the EXISTS condition.

For example, if you had a table named clients with a primary key of client_id, you could use the following statement:

INSERT INTO clients
(client_id, client_name, client_type)
SELECT supplier_id, supplier_name, 'advertising'
FROM suppliers
WHERE not exists (select * from clients
where clients.client_id = suppliers.supplier_id);

This statement inserts multiple records with a subselect.

If you wanted to insert a single record, you could use the following statement:

INSERT INTO clients
(client_id, client_name, client_type)
SELECT 10345, 'IBM', 'advertising'
FROM dual
WHERE not exists (select * from clients
where clients.client_id = 10345);

The use of the dual table allows you to enter your values in a select statement, even though the values are not currently stored in a table.

SQL: UPDATE Statement

The UPDATE statement allows you to update a single record or multiple records in a table.

The syntax the UPDATE statement is:

UPDATE table
SET column = expression
WHERE predicates;


Example #1 - Simple example

Let's take a look at a very simple example.

UPDATE suppliers
SET name = 'HP'
WHERE name = 'IBM';

This statement would update all supplier names in the suppliers table from IBM to HP.


Example #2 - More complex example

You can also perform more complicated updates.

You may wish to update records in one table based on values in another table. Since you can't list more than one table in the UPDATE statement, you can use the EXISTS clause.

For example:

UPDATE suppliers
SET supplier_name = ( SELECT customers.name
FROM customers
WHERE customers.customer_id = suppliers.supplier_id)
WHERE EXISTS
( SELECT customers.name
FROM customers
WHERE customers.customer_id = suppliers.supplier_id);

Whenever a supplier_id matched a customer_id value, the supplier_name would be overwritten to the customer name from the customers table.

SQL: MINUS Query

The MINUS query returns all rows in the first query that are not returned in the second query.

Each SQL statement within the MINUS query must have the same number of fields in the result sets with similar data types.

The syntax for an MINUS query is:

select field1, field2, . field_n
from tables
MINUS
select field1, field2, . field_n
from tables;


Example #1

The following is an example of an MINUS query:

select supplier_id
from suppliers
MINUS
select supplier_id
from orders;

In this example, the SQL would return all supplier_id values that are in the suppliers table and not in the orders table. What this means is that if a supplier_id value existed in the suppliers table and also existed in the orders table, the supplier_id value would not appear in this result set.


Example #2 - With ORDER BY Clause

The following is an MINUS query that uses an ORDER BY clause:

select supplier_id, supplier_name
from suppliers
where supplier_id > 2000
MINUS
select company_id, company_name
from companies
where company_id > 1000
ORDER BY 2;

Since the column names are different between the two "select" statements, it is more advantageous to reference the columns in the ORDER BY clause by their position in the result set. In this example, we've sorted the results by supplier_name / company_name in ascending order, as denoted by the "ORDER BY 2".

The supplier_name / company_name fields are in position #2 in the result set.

SQL: INTERSECT Query

The INTERSECT query allows you to return the results of 2 or more "select" queries. However, it only returns the rows selected by all queries. If a record exists in one query and not in the other, it will be omitted from the INTERSECT results.

Each SQL statement within the INTERSECT query must have the same number of fields in the result sets with similar data types.

The syntax for an INTERSECT query is:

select field1, field2, . field_n
from tables
INTERSECT
select field1, field2, . field_n
from tables;


Example #1

The following is an example of an INTERSECT query:

select supplier_id
from suppliers
INTERSECT
select supplier_id
from orders;

In this example, if a supplier_id appeared in both the suppliers and orders table, it would appear in your result set.

Example #2 - With ORDER BY Clause

The following is an INTERSECT query that uses an ORDER BY clause:

select supplier_id, supplier_name
from suppliers
where supplier_id > 2000
INTERSECT
select company_id, company_name
from companies
where company_id > 1000
ORDER BY 2;

Since the column names are different between the two "select" statements, it is more advantageous to reference the columns in the ORDER BY clause by their position in the result set. In this example, we've sorted the results by supplier_name / company_name in ascending order, as denoted by the "ORDER BY 2".

The supplier_name / company_name fields are in position #2 in the result set.

SQL: UNION ALL Query

The UNION ALL query allows you to combine the result sets of 2 or more "select" queries. It returns all rows (even if the row exists in more than one of the "select" statements).

Each SQL statement within the UNION ALL query must have the same number of fields in the result sets with similar data types.

The syntax for a UNION ALL query is:

select field1, field2, . field_n
from tables
UNION ALL
select field1, field2, . field_n
from tables;


Example #1

The following is an example of a UNION ALL query:

select supplier_id
from suppliers
UNION ALL
select supplier_id
from orders;

If a supplier_id appeared in both the suppliers and orders table, it would appear multiple times in your result set. The UNION ALL does not remove duplicates.

Example #2 - With ORDER BY Clause

The following is a UNION query that uses an ORDER BY clause:

select supplier_id, supplier_name
from suppliers
where supplier_id > 2000
UNION ALL
select company_id, company_name
from companies
where company_id > 1000
ORDER BY 2;

Since the column names are different between the two "select" statements, it is more advantageous to reference the columns in the ORDER BY clause by their position in the result set. In this example, we've sorted the results by supplier_name / company_name in ascending order, as denoted by the "ORDER BY 2".

The supplier_name / company_name fields are in position #2 in the result set.

SQL: UNION Query

The UNION query allows you to combine the result sets of 2 or more "select" queries. It removes duplicate rows between the various "select" statements.

Each SQL statement within the UNION query must have the same number of fields in the result sets with similar data types.

The syntax for a UNION query is:

select field1, field2, . field_n
from tables
UNION
select field1, field2, . field_n
from tables;


Example #1

The following is an example of a UNION query:

select supplier_id
from suppliers
UNION
select supplier_id
from orders;

In this example, if a supplier_id appeared in both the suppliers and orders table, it would appear once in your result set. The UNION removes duplicates.

Example #2 - With ORDER BY Clause

The following is a UNION query that uses an ORDER BY clause:

select supplier_id, supplier_name
from suppliers
where supplier_id > 2000
UNION
select company_id, company_name
from companies
where company_id > 1000
ORDER BY 2;

Since the column names are different between the two "select" statements, it is more advantageous to reference the columns in the ORDER BY clause by their position in the result set. In this example, we've sorted the results by supplier_name / company_name in ascending order, as denoted by the "ORDER BY 2".

The supplier_name / company_name fields are in position #2 in the result set.

Frequently Asked Questions

Question: I need to compare two dates and return the count of a field based on the date values. For example, I have a date field in a table called last updated date. I have to check if trunc(last_updated_date >= trun(sysdate-13).

Answer: Since you are using the COUNT function which is an aggregate function, we'd recommend using a UNION query. For example, you could try the following:

SELECT a.code as Code, a.name as Name, count(b.Ncode)
FROM cdmaster a, nmmaster b
WHERE a.code = b.code
and a.status = 1
and b.status = 1
and b.Ncode <> 'a10'
and trunc(last_updated_date) <= trunc(sysdate-13)
group by a.code, a.name
UNION
SELECT a.code as Code, a.name as Name, count(b.Ncode)
FROM cdmaster a, nmmaster b
WHERE a.code = b.code
and a.status = 1
and b.status = 1
and b.Ncode <> 'a10'
and trunc(last_updated_date) > trunc(sysdate-13)
group by a.code, a.name;

The UNION query allows you to perform a COUNT based on one set of criteria.

trunc(last_updated_date) <= trunc(sysdate-13)

As well as perform a COUNT based on another set of criteria.

trunc(last_updated_date) > trunc(sysdate-13)

SQL: Joins

A join is used to combine rows from multiple tables. A join is performed whenever two or more tables is listed in the FROM clause of an SQL statement.

There are different kinds of joins. Let's take a look at a few examples.


Inner Join (simple join)

Chances are, you've already written an SQL statement that uses an inner join. It is the most common type of join. Inner joins return all rows from multiple tables where the join condition is met.

For example,

SELECT suppliers.supplier_id, suppliers.supplier_name, orders.order_date
FROM suppliers, orders
WHERE suppliers.supplier_id = orders.supplier_id;

This SQL statement would return all rows from the suppliers and orders tables where there is a matching supplier_id value in both the suppliers and orders tables.


Let's look at some data to explain how inner joins work:

We have a table called suppliers with two fields (supplier_id and supplier_ name).
It contains the following data:

supplier_id supplier_name
10000 IBM
10001 Hewlett Packard
10002 Microsoft
10003 Nvidia

We have another table called orders with three fields (order_id, supplier_id, and order_date).
It contains the following data:

order_id supplier_id order_date
500125 10000 2003/05/12
500126 10001 2003/05/13

If we run the SQL statement below:

SELECT suppliers.supplier_id, suppliers.supplier_name, orders.order_date
FROM suppliers, orders
WHERE suppliers.supplier_id = orders.supplier_id;


Our result set would look like this:

supplier_id name order_date
10000 IBM 2003/05/12
10001 Hewlett Packard 2003/05/13

The rows for Microsoft and Nvidia from the supplier table would be omitted, since the supplier_id's 10002 and 10003 do not exist in both tables.


Outer Join

Another type of join is called an outer join. This type of join returns all rows from one table and only those rows from a secondary table where the joined fields are equal (join condition is met).

For example,

select suppliers.supplier_id, suppliers.supplier_name, orders.order_date
from suppliers, orders
where suppliers.supplier_id = orders.supplier_id(+);

This SQL statement would return all rows from the suppliers table and only those rows from the orders table where the joined fields are equal.

The (+) after the orders.supplier_id field indicates that, if a supplier_id value in the suppliers table does not exist in the orders table, all fields in the orders table will display as > in the result set.

The above SQL statement could also be written as follows:

select suppliers.supplier_id, suppliers.supplier_name, orders.order_date
from suppliers, orders
where orders.supplier_id(+) = suppliers.supplier_id


Let's look at some data to explain how outer joins work:

We have a table called suppliers with two fields (supplier_id and name).
It contains the following data:

supplier_id supplier_name
10000 IBM
10001 Hewlett Packard
10002 Microsoft
10003 Nvidia

We have a second table called orders with three fields (order_id, supplier_id, and order_date).
It contains the following data:

order_id supplier_id order_date
500125 10000 2003/05/12
500126 10001 2003/05/13

If we run the SQL statement below:

select suppliers.supplier_id, suppliers.supplier_name, orders.order_date
from suppliers, orders
where suppliers.supplier_id = orders.supplier_id(+);


Our result set would look like this:

supplier_id supplier_name order_date
10000 IBM 2003/05/12
10001 Hewlett Packard 2003/05/13
10002 Microsoft
10003 Nvidia

The rows for Microsoft and Nvidia would be included because an outer join was used. However, you will notice that the order_date field for those records contains a value.

SQL: ORDER BY Clause

The ORDER BY clause allows you to sort the records in your result set. The ORDER BY clause can only be used in SELECT statements.

The syntax for the ORDER BY clause is:

SELECT columns
FROM tables
WHERE predicates
ORDER BY column ASC/DESC;

The ORDER BY clause sorts the result set based on the columns specified. If the ASC or DESC value is omitted, the system assumed ascending order.

ASC indicates ascending order. (default)
DESC indicates descending order.


Example #1

SELECT supplier_city
FROM suppliers
WHERE supplier_name = 'IBM'
ORDER BY supplier_city;

This would return all records sorted by the supplier_city field in ascending order.


Example #2

SELECT supplier_city
FROM suppliers
WHERE supplier_name = 'IBM'
ORDER BY supplier_city DESC;

This would return all records sorted by the supplier_city field in descending order.


Example #3

You can also sort by relative position in the result set, where the first field in the result set is 1. The next field is 2, and so on.

SELECT supplier_city
FROM suppliers
WHERE supplier_name = 'IBM'
ORDER BY 1 DESC;

This would return all records sorted by the supplier_city field in descending order, since the supplier_city field is in position #1 in the result set.


Example #4

SELECT supplier_city, supplier_state
FROM suppliers
WHERE supplier_name = 'IBM'
ORDER BY supplier_city DESC, supplier_state ASC;

This would return all records sorted by the supplier_city field in descending order, with a secondary sort by supplier_state in ascending order.

SQL: HAVING Clause

The HAVING clause is used in combination with the GROUP BY clause. It can be used in a SELECT statement to filter the records that a GROUP BY returns.

The syntax for the HAVING clause is:

SELECT column1, column2, ... column_n, aggregate_function (expression)
FROM tables
WHERE predicates
GROUP BY column1, column2, ... column_n
HAVING condition1 ... condition_n;

aggregate_function can be a function such as SUM, COUNT, MIN, or MAX.


Example using the SUM function

For example, you could also use the SUM function to return the name of the department and the total sales (in the associated department). The HAVING clause will filter the results so that only departments with sales greater than $1000 will be returned.

SELECT department, SUM(sales) as "Total sales"
FROM order_details
GROUP BY department
HAVING SUM(sales) > 1000;


Example using the COUNT function

For example, you could use the COUNT function to return the name of the department and the number of employees (in the associated department) that make over $25,000 / year. The HAVING clause will filter the results so that only departments with more than 10 employees will be returned.

SELECT department, COUNT(*) as "Number of employees"
FROM employees
WHERE salary > 25000
GROUP BY department
HAVING COUNT(*) > 10;


Example using the MIN function

For example, you could also use the MIN function to return the name of each department and the minimum salary in the department. The HAVING clause will return only those departments where the starting salary is $35,000.

SELECT department, MIN(salary) as "Lowest salary"
FROM employees
GROUP BY department
HAVING MIN(salary) = 35000;


Example using the MAX function

For example, you could also use the MAX function to return the name of each department and the maximum salary in the department. The HAVING clause will return only those departments whose maximum salary is less than $50,000.

SELECT department, MAX(salary) as "Highest salary"
FROM employees
GROUP BY department
HAVING MAX(salary) <>

SQL: GROUP BY Clause

The GROUP BY clause can be used in a SELECT statement to collect data across multiple records and group the results by one or more columns.

The syntax for the GROUP BY clause is:

SELECT column1, column2, ... column_n, aggregate_function (expression)
FROM tables
WHERE predicates
GROUP BY column1, column2, ... column_n;

aggregate_function can be a function such as SUM, COUNT, MIN, or MAX.


Example using the SUM function

For example, you could also use the SUM function to return the name of the department and the total sales (in the associated department).

SELECT department, SUM(sales) as "Total sales"
FROM order_details
GROUP BY department;

Because you have listed one column in your SELECT statement that is not encapsulated in the SUM function, you must use a GROUP BY clause. The department field must, therefore, be listed in the GROUP BY section.


Example using the COUNT function

For example, you could use the COUNT function to return the name of the department and the number of employees (in the associated department) that make over $25,000 / year.

SELECT department, COUNT(*) as "Number of employees"
FROM employees
WHERE salary > 25000
GROUP BY department;


Example using the MIN function

For example, you could also use the MIN function to return the name of each department and the minimum salary in the department.

SELECT department, MIN(salary) as "Lowest salary"
FROM employees
GROUP BY department;


Example using the MAX function

For example, you could also use the MAX function to return the name of each department and the maximum salary in the department.

SELECT department, MAX(salary) as "Highest salary"
FROM employees
GROUP BY department;

Recent Tutorials