+ All Categories
Home > Documents > Oracle Plsql

Oracle Plsql

Date post: 13-Nov-2014
Category:
Upload: api-3701383
View: 697 times
Download: 7 times
Share this document with a friend
Popular Tags:
69
Oracle PL/SQL Jayashree Page 1 of 69 CONTENTS PL/SQL.......................................................................................................................................................... 3 INTRODUCTION TO PL/SQL ...................................................................................................................... 4 Topics ..................................................................................................................................................... 4 New Features in PL/SQL ........................................................................................................................ 5 PL/SQL Architecture .............................................................................................................................. 6 PL/SQL Block Structure ......................................................................................................................... 7 PL/SQL Data Types ................................................................................................................................ 8 Declaring Variables and Constants...................................................................................................... 10 Conditional Control Statements ........................................................................................................... 12 Iterative Control Statements ................................................................................................................. 12 Loop Labels .......................................................................................................................................... 13 Sequential Control: GOTO and NULL Statements............................................................................... 13 SQL Support in PL/SQL ....................................................................................................................... 15 User-Defined Records .......................................................................................................................... 16 Review Questions.................................................................................................................................. 18 CURSORS .................................................................................................................................................. 19 Topics ................................................................................................................................................... 19 What are Cursors? ............................................................................................................................... 20 Explicit Cursors .................................................................................................................................... 20 Cursor Attributes .................................................................................................................................. 22 Cursor FOR Loops ............................................................................................................................... 23 Passing Parameters to Cursors ............................................................................................................ 24 Using Cursor Variables ........................................................................................................................ 25 Review Questions.................................................................................................................................. 29 Exercises ............................................................................................................................................... 29 PROCESSING TRANSACTIONS IN PL/SQL ............................................................................................... 30 Topics ................................................................................................................................................... 30 Processing Transactions....................................................................................................................... 31 Overriding Default Locking.................................................................................................................. 33 ERROR HANDLING IN PL/SQL................................................................................................................ 35 Topics ................................................................................................................................................... 35 Exceptions ............................................................................................................................................ 36 Scope Rules........................................................................................................................................... 38 Using EXCEPTION_INIT..................................................................................................................... 39 Propagation of Exception ..................................................................................................................... 39 Re-raising an Exception ....................................................................................................................... 40 SQLCODE and SQLERRM .................................................................................................................. 41 Review Questions.................................................................................................................................. 44 Exercises ............................................................................................................................................... 44 SUBPROGRAMS AND PACKAGES .............................................................................................................. 46 Topics ................................................................................................................................................... 46 What are Subprograms? ....................................................................................................................... 47 Procedures............................................................................................................................................ 48 Functions .............................................................................................................................................. 49 Declaring Subprograms ....................................................................................................................... 50 Stored Subprograms ............................................................................................................................. 51 Positional and Named Notation ........................................................................................................... 52 Overloading .......................................................................................................................................... 52 Recursion .............................................................................................................................................. 54 Packages............................................................................................................................................... 54 Package STANDARD ........................................................................................................................... 57
Transcript
Page 1: Oracle Plsql

Oracle PL/SQL

Jayashree Page 1 of 69

CONTENTS

PL/SQL.......................................................................................................................................................... 3

INTRODUCTION TO PL/SQL...................................................................................................................... 4 Topics ..................................................................................................................................................... 4 New Features in PL/SQL........................................................................................................................ 5 PL/SQL Architecture .............................................................................................................................. 6 PL/SQL Block Structure ......................................................................................................................... 7 PL/SQL Data Types................................................................................................................................ 8 Declaring Variables and Constants...................................................................................................... 10 Conditional Control Statements ........................................................................................................... 12 Iterative Control Statements................................................................................................................. 12 Loop Labels .......................................................................................................................................... 13 Sequential Control: GOTO and NULL Statements............................................................................... 13 SQL Support in PL/SQL ....................................................................................................................... 15 User-Defined Records .......................................................................................................................... 16 Review Questions.................................................................................................................................. 18

CURSORS .................................................................................................................................................. 19 Topics ................................................................................................................................................... 19 What are Cursors? ............................................................................................................................... 20 Explicit Cursors.................................................................................................................................... 20 Cursor Attributes .................................................................................................................................. 22 Cursor FOR Loops ............................................................................................................................... 23 Passing Parameters to Cursors ............................................................................................................ 24 Using Cursor Variables........................................................................................................................ 25 Review Questions.................................................................................................................................. 29 Exercises............................................................................................................................................... 29

PROCESSING TRANSACTIONS IN PL/SQL............................................................................................... 30 Topics ................................................................................................................................................... 30 Processing Transactions....................................................................................................................... 31 Overriding Default Locking.................................................................................................................. 33

ERROR HANDLING IN PL/SQL................................................................................................................ 35 Topics ................................................................................................................................................... 35 Exceptions ............................................................................................................................................ 36 Scope Rules........................................................................................................................................... 38 Using EXCEPTION_INIT..................................................................................................................... 39 Propagation of Exception..................................................................................................................... 39 Re-raising an Exception ....................................................................................................................... 40 SQLCODE and SQLERRM .................................................................................................................. 41 Review Questions.................................................................................................................................. 44 Exercises............................................................................................................................................... 44

SUBPROGRAMS AND PACKAGES .............................................................................................................. 46 Topics ................................................................................................................................................... 46 What are Subprograms?....................................................................................................................... 47 Procedures............................................................................................................................................ 48 Functions .............................................................................................................................................. 49 Declaring Subprograms ....................................................................................................................... 50 Stored Subprograms ............................................................................................................................. 51 Positional and Named Notation ........................................................................................................... 52 Overloading.......................................................................................................................................... 52 Recursion.............................................................................................................................................. 54 Packages............................................................................................................................................... 54 Package STANDARD ........................................................................................................................... 57

Page 2: Oracle Plsql

Oracle PL/SQL

Jayashree Page 2 of 69

ORACLE Product-specific Packages ................................................................................................... 57 Advantages of Packages ....................................................................................................................... 58 Exercises............................................................................................................................................... 59

DATABASE TRIGGERS .............................................................................................................................. 60 Topics ................................................................................................................................................... 60 Introduction to Triggers ....................................................................................................................... 61 Creating a Database Trigger ............................................................................................................... 61 Triggers Examples................................................................................................................................ 63 INSTEAD OF Triggers ......................................................................................................................... 66 Trigger Execution................................................................................................................................. 68 Exercises............................................................................................................................................... 69

Page 3: Oracle Plsql

Oracle PL/SQL

Jayashree Page 3 of 69

PL/SQL

• Introduction to PL/SQL

• Cursors

• Processing Transactions in PL/SQL

• Error Handling in PL/SQL : Exceptions

• Subprograms and Packages

• Database Triggers

Page 4: Oracle Plsql

Oracle PL/SQL

Jayashree Page 4 of 69

Introduction to PL/SQL

Topics

• New Features in PL/SQL

• PL/SQL Architecture

• PL/SQL Block Structure

• PL/SQL Data Types

• Declaring Variables and Constants

• Conditional Control Statements

• Iterative Control Statements

• Loop Labels

• Sequential Control : GOTO and NULL Statements

• SQL Support in PL/SQL

Page 5: Oracle Plsql

Oracle PL/SQL

Jayashree Page 5 of 69

PL/SQL is Oracle Corporation's procedural language extension to SQL, the standard data access language for object-relational databases. PL/SQL offers modern software engineering features such as data encapsulation, exception handling, information hiding, and object orientation, and so brings state-of-the-art programming to the Oracle Server and Toolset.

New Features in PL/SQL

• External Procedures

• Object Types

• Collections

• LOB Types External Procedures

• To support special-purpose processing and promote reuse of code, PL/SQL provides an interface for calling routines written in other languages. This makes the strengths and capabilities of those languages available to you.

• An external procedure is a third-generation-language routine stored in a dynamic link library (DLL), registered with PL/SQL, and called by you to do special-purpose processing. At run time, PL/SQL loads the library dynamically, then calls the routine as if it were a PL/SQL subprogram. Typically, external procedures are used to interface with embedded systems, solve scientific and engineering problems, analyze data, or control real-time devices and processes.

Object Types

• Object-oriented programming is based on the concept of interacting objects. In, PL/SQL, objects are instances of object types. When you define an object type using the CREATE TYPE statement (in SQL*Plus for example), you create an abstract template for some real-world object.

• An object type encapsulates a data structure along with the functions and procedures needed to manipulate the data. At run time, when the data structure is filled with values, you have created an object. You can create as many objects as you need. Each object stores different real-world values.

• Object types, which map directly into classes defined in object-oriented languages such as C++, reduce complexity by breaking down a large system into logical entities. This allows you to create software components that are modular, maintainable, and reusable.

Page 6: Oracle Plsql

Oracle PL/SQL

Jayashree Page 6 of 69

Collections

• The collection types TABLE and VARRAY allow you to declare nested tables and variable-size arrays (varrays for short). A collection is an ordered group of elements, all of the same type. Each element has a unique subscript that determines its position in the collection.

• Collections work like the arrays found in most third-generation programming languages. They can store instances of an object type and, conversely, can be attributes of an object type. Also, collections can be passed as parameters. So, you can use them to move columns of data into and out of database tables or between client-side applications and stored subprograms.

LOB Types

• The LOB (large object) datatypes BFILE, BLOB, CLOB, and NCLOB let you store blocks of unstructured data up to four gigabytes in size. And, they allow efficient, random, piece-wise access to the data.

• LOB types store values, called locators, that specify the location of large objects stored out-of-line or in an external file. PL/SQL operates on LOBs through the locators. To manipulate LOBs, you use the supplied package DBMS_LOB.

PL/SQL Architecture

• The PL/SQL runtime system is a technology, not an independent product. This technology acts as an engine that executes PL/SQL blocks and subprograms.

• The engine can be installed in an Oracle Server or in an application development tool such as Oracle Forms or Oracle Reports.

• So, PL/SQL can reside in two environments:

• the Oracle Server

• Oracle tools

The PL/SQL Engine

• The PL/SQL engine executes procedural statements but sends SQL statements to the SQL Statement Executor in the Oracle Server.

• Application development tools that lack a local PL/SQL engine must rely on Oracle to process PL/SQL blocks and subprograms.

Page 7: Oracle Plsql

Oracle PL/SQL

Jayashree Page 7 of 69

• When it contains the PL/SQL engine, an Oracle Server can process PL/SQL blocks and subprograms as well as single SQL statements. The Oracle Server passes the blocks and subprograms to its local PL/SQL engine.

PL/SQL Block Structure

DECLARE

< Declarations >

BEGIN

< Executable Statements >

EXCEPTION

< Exception Handlers >

END;

• PL/SQL is a block-structured language - the basic units (procedures, functions, and anonymous blocks) that make up a PL/SQL program are logical blocks, which can contain any number of nested sub-blocks.

• A block (or sub-block) lets you group logically related declarations and statements. The declarations are local to the block and cease to exist when the block completes.

• Only the executable part is required.

• You can nest sub-blocks in the executable and exception-handling parts of a PL/SQL block or subprogram but not in the declarative part.

ORACLE Server

PL/SQL

Block

PL/SQL

Block

SQL Statement Executor

Procedural

Statement

Executor

Non-SQL

SQL

PL/SQL Engine

Page 8: Oracle Plsql

Oracle PL/SQL

Jayashree Page 8 of 69

PL/SQL Data Types Every constant and variable has a datatype, which specifies a storage format, constraints, and valid range of values. PL/SQL provides a variety of predefined datatypes. A scalar type has no internal components. A composite type has internal components that can be manipulated individually. A reference type holds values, called pointers, that designate other program items. A LOB type holds values, called locators, that specify the location of large objects (graphic images for example) stored out-of-line. Scalar Types

BINARY_INTEGER CHAR

DEC CHARACTER

DECIMAL LONG

DOUBLE-PRECISION LONG RAW

INTEGER RAW

FLOAT ROWID

INT INTEGER STRING

NATURAL VARCHAR2

NUMBER NUMERIC POSITIVE DATE

REAL SMALLINT BOOLEAN

SIGNTYPE

Composite Types

RECORD

TABLE

Reference Types

REFCURSOR

REF object_name

LOB Types

BFILE

BLOB

CLOB

Subtypes

A base type is the datatype from which a subtype is derived. A subtype associates a base type with a constraint and so defines a subset of values.

Page 9: Oracle Plsql

Oracle PL/SQL

Jayashree Page 9 of 69

BINARY_INTEGER NUMBER CHAR VARCHAR2

NATURAL DEC CHARACTER STRING

POSITIVE DECIMAL DEC VARCHAR

SIGNTYPE DOUBLE PRECISION

INTEGER INT

NUMERIC

REAL

SMALLINT

User-Defined Subtypes

You can define your own subtypes in the declarative part of any PL/SQL block, subprogram, or package using the syntax SUBTYPE subtype_name IS base_type;

Examples: DECLARE

SUBTYPE EmpDate IS DATE; -- based on DATE type

SUBTYPE Counter IS NATURAL; -- based on NATURAL subtype

TYPE NameList IS TABLE OF VARCHAR2(10);

SUBTYPE EmpRoster IS NameList; -- based on TABLE type

TYPE TimeRec IS RECORD (minutes INTEGER, hours INTEGER);

SUBTYPE Time IS TimeRec; -- based on RECORD type

SUBTYPE ID_Num IS emp.empno%TYPE;-- based on column type

CURSOR c1 IS SELECT * FROM dept;

SUBTYPE DeptFile IS c1%ROWTYPE;--based on cursor rowtype

However, you cannot specify a constraint on the base type. For example: DECLARE

SUBTYPE Accumulator IS NUMBER(7,2); -- illegal;

SUBTYPE Delimiter IS CHAR(1); -- illegal;

SUBTYPE Word IS VARCHAR2(15); -- illegal

You can use a simple workaround to define size-constrained subtypes indirectly: DECLARE

temp VARCHAR2(15);

SUBTYPE Word IS temp%TYPE; -- maximum size of Word is 15

Page 10: Oracle Plsql

Oracle PL/SQL

Jayashree Page 10 of 69

Using Subtypes

Once you define a subtype, you can declare items of that type. Examples:

DECLARE

SUBTYPE Counter IS NATURAL;

rows Counter;

employees Counter;

DECLARE

SUBTYPE Accumulator IS NUMBER;

total Accumulator(7,2);

Declaring Variables and Constants

• PL/SQL allows you to declare variables and constants, and then use them in SQL and procedural statements anywhere an expression can be used.

• Forward references are not allowed. So, you must declare a variable or constant before referencing it in other statements, including other declarative statements.

• Variables can have any SQL data type, such as CHAR, DATE, and NUMBER, or any PL/SQL data type, such as BOOLEAN and BINARY_INTEGER.

• Examples: emp_no NUMBER(4);

in_stock BOOLEAN;

• Initial values can also be assigned to a variable at the time of declaration.

Example: deptno NUMBER(4) := 10;

• Constants are declared by specifying the key word CONSTANT before the datatype.

Example: credit_limit CONSTANT REAL := 5000.00;

• You can use the keyword DEFAULT instead of the assignment operator to initialize variables.

Examples: blood_type CHAR DEFAULT 'O';

valid BOOLEAN DEFAULT FALSE;

• Besides assigning an initial value, declarations can impose the NOT NULL constraint, as the following example shows: acct_id INTEGER(4) NOT NULL := 9999;

The NOT NULL constraint must be followed by an initialization clause.

Page 11: Oracle Plsql

Oracle PL/SQL

Jayashree Page 11 of 69

Using %TYPE Attribute

• The %TYPE attribute provides the data type of a variable or database column.

Examples : credit REAL(7,2);

debit credit%TYPE;

balance NUMBER(7,2);

minimum_balance balance%TYPE := 10.00;

• The %TYPE attribute is particularly useful when declaring variables that refer to database columns.

Example : my_dname scott.dept.dname%TYPE;

• Using %TYPE to declare my_dname has two advantages. First, you need not know the exact data type of dname. Second, if the database definition of dname changes, the data type of my_dname changes accordingly at run time.

Using %ROWTYPE Attribute

• The %ROWTYPE attribute provides a record type that represents a row in a table (or view).

• The record can store an entire row of data selected from the table

Example : emp_rec emp%ROWTYPE;

• Columns in a row and corresponding fields in a record have the same names and data

types.

• To reference a field, you use dot notation. For example, you might reference the deptno field as emp_rec.deptno

Page 12: Oracle Plsql

Oracle PL/SQL

Jayashree Page 12 of 69

Conditional Control Statements IF condition THEN

sequence_of_statements;

END IF;

IF condition THEN

sequence_of_statements1;

ELSE

sequence_of_statements2;

END IF;

IF condition1 THEN

sequence_of_statements1;

ELSIF condition2 THEN

sequence_of_statements2;

ELSE

sequence_of_statements3;

END IF;

Iterative Control Statements LOOP

sequence_of_statements;

END LOOP;

EXIT;

EXIT WHEN condition;

WHILE condition LOOP

sequence_of_statements;

END LOOP;

FOR counter IN [REVERSE] lower_bound..higher_bound LOOP

sequence_of_statements;

END LOOP;

Page 13: Oracle Plsql

Oracle PL/SQL

Jayashree Page 13 of 69

Loop Labels

• Like PL/SQL blocks, loops can be labeled. The label, an undeclared identifier enclosed by double angle brackets, must appear at the beginning of the LOOP statement, as follows:

<<label_name>> LOOP

sequence_of_statements;

END LOOP;

• Optionally, the label name can also appear at the end of the LOOP statement, as the

following example shows: <<my_loop>> LOOP

...

END LOOP my_loop;

• With either form of EXIT statement, you can complete not only the current loop, but

any enclosing loop. Simply label the enclosing loop that you want to complete. Then, use the label in an EXIT statement, as follows:

<<outer>> LOOP

...

LOOP

...

EXIT outer WHEN ... -- exit both loops

END LOOP;

...

END LOOP outer;

Sequential Control: GOTO and NULL Statements

• The GOTO statement branches to a label unconditionally.

• The label must be unique within its scope and must precede an executable statement or a PL/SQL block.

Page 14: Oracle Plsql

Oracle PL/SQL

Jayashree Page 14 of 69

GOTO Statement : Examples

• BEGIN

...

GOTO insert_row;

...

<<insert_row>>

INSERT INTO emp VALUES ...

END;

• DECLARE

done BOOLEAN;

BEGIN

...

FOR i IN 1..50 LOOP

IF done THEN

GOTO end_loop;

END IF;

...

<<end_loop>>

NULL; -- an executable statement

END LOOP;

END;

• DECLARE

my_ename CHAR(10);

BEGIN

...

<<get_name>>

SELECT ename INTO my_ename FROM emp WHERE ...

...

BEGIN

...

GOTO get_name; -- branch to enclosing block

END;

END;

Restrictions on using GO TO

• A GOTO statement cannot branch into an IF statement, LOOP statement, or sub-block.

• Also, a GOTO statement cannot branch from one IF statement clause to another.

• A GOTO statement cannot branch from an enclosing block into a sub-block

Page 15: Oracle Plsql

Oracle PL/SQL

Jayashree Page 15 of 69

• A GOTO statement cannot branch from an exception handler into the current block. However, a GOTO statement can branch from an exception handler into an enclosing block.

The NULL Statement

• The NULL statement explicitly specifies inaction; it does nothing other than pass control to the next statement. It can, however, improve readability.

Example :

EXCEPTION

WHEN ZERO_DIVIDE THEN

ROLLBACK;

WHEN VALUE_ERROR THEN

INSERT INTO errors VALUES ...

COMMIT;

WHEN OTHERS THEN

NULL;

END;

• The NULL statement is a handy way to create stubs when designing applications from the top down.

• A stub is dummy subprogram that allows you to defer the definition of a procedure or function until you test and debug the main program.

Example : PROCEDURE debit_account(acct_id INTEGER, amount REAL)IS

BEGIN

NULL;

END debit_account;

SQL Support in PL/SQL

Data Manipulation INSERT, UPDATE, DELETE, SELECT,

LOCK TABLE

Transaction Control COMMIT, ROLLBACK, SAVEPOINT,

SET TRANSACTION

SQL Functions AVG, COUNT, MAX, MIN, STDDEV, SUM,

VARIANCE

SQL Pseudocolumns CURRVAL, LEVEL, NEXTVAL, ROWID, ROWNUM

SQL Operators all comparison, set, and row operators

Page 16: Oracle Plsql

Oracle PL/SQL

Jayashree Page 16 of 69

User-Defined Records

• The user can define logically related variables into a composite data type as records.

• Declaring Records : records must be declared in two steps - first, define a RECORD type, then declare user-defined records of that type.

• Defining a RECORD type : TYPE type_name IS RECORD ( field_name1 field_type [NOT NULL {:= | DEFAULT} expr],

field_name2 field_type [NOT NULL {:= | DEFAULT} expr],

...);

where field_type stands for the following syntax:

{datatype_name | variable%TYPE | record_variable%TYPE

| table.column%TYPE | table%ROWTYPE | cursor%ROWTYPE |

cursor_variable%ROWTYPE}

• To reference individual fields in a record, use dot notation record_name.field_name

• Fields declared as NOT NULL must be initialized.

• Even if the fields match exactly, records of different types cannot be assigned to each other.

• A user-defined record and a %ROWTYPE record always have different data types

• You cannot use the INSERT statement to insert user-defined records into a database table.

• Records cannot be tested for equality, inequality, or nullity.

User-Defined Records : Example

TYPE deptrectype IS RECORD

( deptno dept.deptno%TYPE,

dname dept.dname%TYPE,

loc dept.loc%TYPE );

deptrec deptrectype;

Page 17: Oracle Plsql

Oracle PL/SQL

Jayashree Page 17 of 69

To store data into deptrec : SELECT deptno, dname, loc INTO deptrec

FROM dept WHERE deptno = 10;

To reference a field in deptrec : deptrec.deptno := …;

PL/SQL lets you define records that contain objects, collections, and other records (called nested records). However, object types cannot have attributes of type RECORD. DECLARE

TYPE TimeRec IS RECORD (

seconds SMALLINT,

minutes SMALLINT,

hours SMALLINT);

TYPE FlightRec IS RECORD (

flight_no INTEGER,

plane_id VARCHAR2(10),

captain Employee, -- declare object

passengers PassengerList, -- declare varray

depart_time TimeRec, -- declare nested record

airport_code VARCHAR2(10));

You can specify a RECORD type in the RETURN clause of a function specification.

DECLARE

TYPE EmpRec IS RECORD (

emp_id INTEGER

last_name VARCHAR2(15),

dept_num INTEGER(2),

job_title VARCHAR2(15),

salary REAL(7,2));

...

FUNCTION nth_highest_salary (n INTEGER) RETURN EmpRec IS

...

Page 18: Oracle Plsql

Oracle PL/SQL

Jayashree Page 18 of 69

Review Questions

1. _______________________________ attribute can be used in PL/SQL to declare a variable to be of the same type as another variable or a table column.

2. Initialization of variables cannot be done in the DECLARE part of a PL/SQL block.

(T / F) 3. A loop label or block label should be declared in the DECLARE section, prior to its

use in the body of the block. (T /F) 4. Nesting of blocks is allowed in any portion of a PL/SQL block. (T / F) 5. The PL/SQL statement which helps in creating the stubs is _____________________ 6. A PL/SQL table is similar to a base table, as both are made up of columns/fields.

(T / F) 7. ________________________________________ statement allows for breaking out

of a loop unconditionally.

8. The user can define logically related variables into a composite data type as __________________________

Page 19: Oracle Plsql

Oracle PL/SQL

Jayashree Page 19 of 69

Cursors

Topics

• What are Cursors?

• Explicit Cursors

• Cursor Attributes

• Cursor FOR Loops

• Passing Parameters to Cursors

• Using Cursor Variables

Page 20: Oracle Plsql

Oracle PL/SQL

Jayashree Page 20 of 69

What are Cursors?

• Oracle uses work areas to execute SQL statements and store processing information.

• A PL/SQL construct called a cursor lets you name a work area and access its stored information.

• There are two kinds of cursors: implicit and explicit.

• PL/SQL implicitly declares a cursor for all SQL data manipulation statements, including queries that return only one row.

• For queries that return more than one row, you can explicitly declare a cursor to process the rows individually.

Explicit Cursors

• The set of rows returned by a query can consist of zero, one, or multiple rows, depending on how many rows meet your search criteria.

• When a query returns multiple rows, you can explicitly declare a cursor to process the rows.

• You can declare a cursor in the declarative part of any PL/SQL block, subprogram, or package.

• You can use three commands to control a cursor:

• OPEN

• FETCH

• CLOSE Declaring a cursor :

• When you declare a cursor, you name it and associate it with a specific query.

• Syntax : CURSOR cursor-name IS select-statement;

• Example : DECLARE CURSOR c1 IS

SELECT ename, sal FROM emp WHERE deptno = 10;

Page 21: Oracle Plsql

Oracle PL/SQL

Jayashree Page 21 of 69

Opening a Cursor :

• Opening the cursor executes the query and identifies the active set, which consists of all rows that meet the query search criteria. For cursors declared using the FOR UPDATE clause, the OPEN statement also locks those rows.

• Syntax : OPEN cursor-name;

• Example : OPEN c1;

Fetching with a Cursor :

• The FETCH statement retrieves the rows in the active set one at a time. After each fetch, the cursor advances to the next row in the active set.

• Syntax : FETCH cursor-name INTO variables;

• Example : FETCH c1 INTO my_ename, my_sal;

• For each column value returned by the query associated with the cursor, there must be a corresponding variable in the INTO list. Also, their data types must be compatible.

Closing a Cursor :

• The CLOSE statement disables the cursor, and the active set becomes undefined.

• Syntax : CLOSE cursor-name;

• Example : CLOSE c1;

• Once a cursor is closed, you can reopen it. Any other operation on a closed cursor raises the predefined exception INVALID_CURSOR.

Page 22: Oracle Plsql

Oracle PL/SQL

Jayashree Page 22 of 69

Cursor Attributes Explicit Cursor Attributes

• Each cursor or cursor variable has four attributes: %FOUND, %ISOPEN %NOTFOUND, and %ROWCOUNT.

• When appended to the cursor or cursor variable, these attributes return useful information about the execution of a data manipulation statement.

%NOTFOUND Evaluates to true, if last fetch failed, i.e. , no more rows left

%FOUND Evaluates to true, if last fetch succeeded

%ROWCOUNT Returns the number of rows fetched

%ISOPEN Evaluates to true, if the cursor is open

Implicit Cursor Attributes

• Implicit cursor attributes return information about the execution of an INSERT, UPDATE, DELETE, or SELECT INTO statement.

SQL%NOTFOUND Is true if DML statement was not successful

SQL%FOUND Is true if DML statement was successful

SQL%ROWCOUNT Returns number of rows affected by a DML statement

SQL%ISOPEN Is always false because ORACLE automatically closes an implicit cursor after executing its SQL statement

• If a SELECT INTO statement returns more than one row, PL/SQL raises the

predefined exception TOO_MANY_ROWS and %ROWCOUNT yields 1, not the actual number of rows that satisfy the query.

Page 23: Oracle Plsql

Oracle PL/SQL

Jayashree Page 23 of 69

Example: Update the salaries of all employees by 100 if the current salary is more

than 1000.

DECLARE

var_empno emp.empno%type;

var_sal emp.sal%type;

CURSOR c1 IS

SELECT empno, sal FROM emp;

BEGIN

OPEN c1;

LOOP

FETCH c1 INTO var_empno, var_sal;

EXIT WHEN c1%NOTFOUND;

IF var_sal > 1000 THEN

var_sal := var_sal + 100;

UPDATE emp SET sal = var_sal

WHERE empno = var_empno;

dbms_output.put_line(‘Salary updated for’

||var_empno);

END IF;

END LOOP;

CLOSE c1;

COMMIT;

END;

Note: 1. Execute the following SQL*PLUS command prior to the use of

dbms_output.put_line procedure: SQL> SET SERVEROUTPUT ON

2. Using ‘WHERE CURRENT OF <cursor-name>’ in the above example speeds up the update since the condition is the same as the select.

Cursor FOR Loops • In most situations that require an explicit cursor, you can simplify coding by using a

cursor FOR loop instead of the OPEN, FETCH, and CLOSE statements.

• A cursor FOR loop implicitly declares its loop index as a %ROWTYPE record, opens a cursor, repeatedly fetches rows of values from the active set into fields in the record, and closes the cursor when all rows have been processed. The individual values of the fields of the row in the record can be referenced by the dot notation: index.column_name.

• Syntax : FOR index IN cursor-name LOOP statements;

END LOOP;

Page 24: Oracle Plsql

Oracle PL/SQL

Jayashree Page 24 of 69

• Example : Cursor FOR Loop DECLARE

result temp.col1%TYPE;

CURSOR c1 IS

SELECT n1, n2, n3 FROM data_table WHERE

exper_num = 1;

BEGIN

FOR c1rec IN c1 LOOP

/* calculate and store the results */

result := c1rec.n2 / (c1rec.n1 + c1rec.n3);

INSERT INTO temp VALUES (result, NULL, NULL);

END LOOP;

COMMIT;

END;

Note: Using the COMMIT inside the loop closes the cursor; Avoid it.

Passing Parameters to Cursors

• You can pass parameters to the cursor used in a cursor FOR loop.

• Example : In the following example, you pass a department number. Then, you compute the total wages paid to employees in that department. Also, you determine how many employees have salaries higher than $2000 and how many have commissions larger than their salaries.

DECLARE

CURSOR emp_cursor(dnum NUMBER) IS

SELECT sal, comm FROM emp WHERE deptno = dnum;

total_wages NUMBER(11,2) := 0;

high_paid NUMBER(4) := 0;

higher_comm NUMBER(4) := 0;

BEGIN

FOR emp_record IN emp_cursor(20) LOOP

emp_record.comm := NVL(emp_record.comm, 0);

total_wages := total_wages + emp_record.sal +

emp_record.comm;

IF emp_record.sal > 2000.00 THEN

high_paid := high_paid + 1;

END IF;

IF emp_record.comm > emp_record.sal THEN

higher_comm := higher_comm + 1;

END IF;

END LOOP;

Page 25: Oracle Plsql

Oracle PL/SQL

Jayashree Page 25 of 69

INSERT INTO temp VALUES (high_paid, higher_comm, 'Total

Wages: ' || TO_CHAR(total_wages));

COMMIT; END;

Using Cursor Variables

• Like a cursor, a cursor variable points to the current row in the result set of a multi-row query. But, cursors differ from cursor variables the way constants differ from variables. Whereas a cursor is static, a cursor variable is dynamic because it is not tied to a specific query. You can open a cursor variable for any type-compatible query. This gives you more flexibility.

• Also, you can assign new values to a cursor variable and pass it as a parameter to subprograms, including subprograms stored in an Oracle database. This gives you an easy way to centralize data retrieval.

• Cursor variables are like C or Pascal pointers, which hold the memory location (address) of some item instead of the item itself. So, declaring a cursor variable creates a pointer, not an item. A cursor variable has datatype REF CURSOR.

Defining REF CURSOR Types To create cursor variables, you take two steps. First, you define a REF CURSOR type, then declare cursor variables of that type. Syntax for defining: TYPE ref_type_name IS REF CURSOR RETURN return_type;

Examples: DECLARE

TYPE DeptCurTyp IS REF CURSOR RETURN dept%ROWTYPE;

DECLARE

TYPE EmpCurTyp IS REF CURSOR RETURN emp%ROWTYPE;

-- strong

TYPE GenericCurTyp IS REF CURSOR; -- weak

Declaring Cursor Variables DECLARE

TYPE DeptCurTyp IS REF CURSOR RETURN dept%ROWTYPE;

dept_cv DeptCurTyp; -- declare cursor variable

Page 26: Oracle Plsql

Oracle PL/SQL

Jayashree Page 26 of 69

DECLARE

TYPE TmpCurTyp IS REF CURSOR RETURN emp%ROWTYPE;

tmp_cv TmpCurTyp; -- declare cursor variable

TYPE EmpCurTyp IS REF CURSOR RETURN tmp_cv%ROWTYPE;

emp_cv EmpCurTyp; -- declare cursor variable

DECLARE

TYPE EmpRecTyp IS RECORD (

empno NUMBER(4),

ename VARCHAR2(1O),

sal NUMBER(7,2));

TYPE EmpCurTyp IS REF CURSOR RETURN EmpRecTyp;

emp_cv EmpCurTyp; -- declare cursor variable

DECLARE

TYPE EmpCurTyp IS REF CURSOR RETURN emp%ROWTYPE;

PROCEDURE open_emp_cv (emp_cv IN OUT EmpCurTyp) IS ...

Controlling Cursor Variables: You use three statements to control a cursor variable: OPEN-FOR, FETCH, and CLOSE.

Opening a Cursor Variable The OPEN-FOR statement associates a cursor variable with a multi-row query, executes the query, and identifies the result set. The statement syntax is OPEN {cursor_variable_name | :host_cursor_variable_name}

FOR select_statement;

• Cursor variables do not take parameters

• The query cannot be FOR UPDATE Examples:

IF NOT emp_cv%ISOPEN THEN

/* Open cursor variable. */

OPEN emp_cv FOR SELECT * FROM emp;

END IF;

Note: Other OPEN-FOR statements can open the same cursor variable for different queries. You need not close a cursor variable before reopening it. When you reopen a cursor variable for a different query, the previous query is lost.

CREATE PACKAGE emp_data AS

...

TYPE EmpCurTyp IS REF CURSOR RETURN emp%ROWTYPE;

PROCEDURE open_emp_cv (emp_cv IN OUT EmpCurTyp);

END emp_data;

Page 27: Oracle Plsql

Oracle PL/SQL

Jayashree Page 27 of 69

CREATE PACKAGE BODY emp_data AS

...

PROCEDURE open_emp_cv (emp_cv IN OUT EmpCurTyp) IS

BEGIN

OPEN emp_cv FOR SELECT * FROM emp;

END open_emp_cv;

END emp_data;

Example

CREATE PACKAGE emp_data AS

TYPE GenericCurTyp IS REF CURSOR;

TYPE EmpCurTyp IS REF CURSOR RETURN emp%ROWTYPE;

PROCEDURE open_emp_cv (emp_cv IN OUT EmpCurTyp,

choice IN NUMBER);

END emp_data;

CREATE PACKAGE BODY emp_data AS

PROCEDURE open_emp_cv (emp_cv IN OUT EmpCurTyp,

choice IN NUMBER) IS

BEGIN

IF choice = 1 THEN

OPEN emp_cv FOR

SELECT * FROM emp WHERE comm IS NOT NULL;

ELSIF choice = 2 THEN

OPEN emp_cv FOR

SELECT * FROM emp WHERE sal > 2500;

ELSIF choice = 3 THEN

OPEN emp_cv FOR

SELECT * FROM emp WHERE deptno = 20;

END IF;

END open_emp_cv;

END emp_data;

Fetching from a Cursor Variable The FETCH statement retrieves rows one at a time from the result set of a multi-row query. The statement syntax follows: FETCH {cursor_variable_name | :host_cursor_variable_name}

INTO {variable_name[, variable_name]... | record_name};

Closing a Cursor Variable

The CLOSE statement disables a cursor variable. After that, the associated result set is undefined. The statement syntax follows: CLOSE {cursor_variable_name | :host_cursor_variable_name);

Page 28: Oracle Plsql

Oracle PL/SQL

Jayashree Page 28 of 69

Example: Using a bind variable

CREATE PACKAGE emp_data AS

TYPE EmpRecTyp IS RECORD (

emp_id NUMBER(4),

emp_name CHAR(10),

job_title CHAR(9),

dept_name CHAR(14),

dept_loc CHAR(13));

TYPE EmpCurTyp IS REF CURSOR RETURN EmpRecTyp;

PROCEDURE get_staff (dept_no IN NUMBER,

emp_cv IN OUT EmpCurTyp);

END;

/

CREATE PACKAGE BODY emp_data AS

PROCEDURE get_staff (dept_no IN NUMBER,

emp_cv IN OUT EmpCurTyp) IS

BEGIN

OPEN emp_cv FOR

SELECT empno, ename, job, dname, loc FROM emp, dept

WHERE emp.deptno = dept_no AND

emp.deptno = dept.deptno

ORDER BY empno;

END;

END;

/

COLUMN EMPNO HEADING Number

COLUMN ENAME HEADING Name

COLUMN JOB HEADING JobTitle

COLUMN DNAME HEADING Department

COLUMN LOC HEADING Location

SET AUTOPRINT ON

VARIABLE cv REFCURSOR

EXECUTE emp_data.get_staff(20, :cv)

Page 29: Oracle Plsql

Oracle PL/SQL

Jayashree Page 29 of 69

Review Questions

1. You can use the _______________________________________________ packaged procedure to output something to the screen.

2. The two kinds of cursors are _____________________________________________ 3. PL/SQL implicitly declares a cursor for all DML statements, including queries that

return multiple rows. (T / F) 4. The PL/SQL statement that executes the query associated with a cursor is

_____________________________________________ 5. The SELECT statement used in a PL/SQL block need not necessarily have an INTO

clause always. (T / F) 6. The name of the implicit cursor is _______________________________________ 7. The explicit cursor attribute which evaluates to true if the last fetch succeeded is

_______________________________________________________

Exercises

1. Write an anonymus PL/SQL block that retrieves the five highest paid employees from the EMP table.

2. Consider two tables having a column each of numbers. Get a number from each of the

two tables, then insert the sum of the rows into a third table. Stop when all rows have been fetched from either of the two tables.

3. In the EMP table, give a raise in sal of 10% to all clerks, and 20% to all salesmen.

Write these increments in a separate table, as well as update in the EMP table.

Page 30: Oracle Plsql

Oracle PL/SQL

Jayashree Page 30 of 69

Processing Transactions in PL/SQL

Topics

• Processing Transactions

• Overriding Default Locking

– Using the FOR UPDATE Clause

– Using the LOCK TABLE Command

Page 31: Oracle Plsql

Oracle PL/SQL

Jayashree Page 31 of 69

Processing Transactions

• When a table is being queried by one user and updated by another at the same time, Oracle generates a read-consistent view of the data for the query. That is, once a query begins and as it proceeds, the data read by the query does not change. As update activity continues, Oracle takes snapshots of the table's data and records changes in a rollback segment. Oracle uses information in the rollback segment to build read-consistent query results and to undo changes if necessary.

• Oracle uses locks to control concurrent access to data. A lock gives you temporary ownership of a database resource such as a table or row of data. Thus, data cannot be changed by other users until you finish with it. You need never explicitly lock a resource because default locking mechanisms protect Oracle data and structures. However, you can request data locks on tables or rows when it is to your advantage to override default locking. You can choose from several modes of locking such as row share and exclusive.

• Oracle is transaction oriented; that is, it uses transactions to ensure data integrity. A transaction is a series of one or more logically related SQL statements that accomplish a task. Oracle treats the series of SQL statements as a unit so that all the changes brought about by the statements are either committed (made permanent) or rolled back (undone) at the same time. If your program fails in the middle of a transaction, the database is automatically restored to its former state.

• The first SQL statement in your program begins a transaction. When one transaction ends, the next SQL statement automatically begins another transaction. Thus, every SQL statement is part of a transaction.

• The COMMIT and ROLLBACK statements ensure that all database changes brought about by SQL operations are either made permanent or undone at the same time. All the SQL statements executed since the last commit or rollback make up the current transaction.

• The COMMIT statement ends the current transaction and makes permanent any changes made during that transaction. Until you commit the changes, other users cannot access the changed data; they see the data as it was before you made the changes.

• The COMMIT statement releases all row and table locks. It also erases any savepoints marked since the last commit or rollback.

Page 32: Oracle Plsql

Oracle PL/SQL

Jayashree Page 32 of 69

• The ROLLBACK statement ends the current transaction and undoes any changes made during that transaction. Rolling back is useful for two reasons. First, if you make a mistake like deleting the wrong row from a table, a rollback restores the original data. Second, if you start a transaction that you cannot finish because an exception is raised or a SQL statement fails, a rollback lets you return to the starting point to take corrective action and perhaps try again.

Example: DECLARE

emp_id INTEGER;

...

BEGIN

SELECT empno, ... INTO emp_id, ... FROM new_emp WHERE

...

INSERT INTO emp VALUES (emp_id, ...);

INSERT INTO tax VALUES (emp_id, ...);

INSERT INTO pay VALUES (emp_id, ...);

...

EXCEPTION

WHEN DUP_VAL_ON_INDEX THEN

ROLLBACK;

...

END;

• SAVEPOINT names and marks the current point in the processing of a transaction.

Used with the ROLLBACK TO statement, savepoints let you undo parts of a transaction instead of the whole transaction.

• When you roll back to a savepoint, any savepoints marked after that savepoint are erased. However, the savepoint to which you roll back is not erased.

• The number of active savepoints per session is unlimited.

• Implicit Rollbacks : Before executing an INSERT, UPDATE, or DELETE statement, Oracle marks an implicit savepoint (unavailable to you). If the statement fails, Oracle rolls back to the savepoint.

• If you exit a stored subprogram with an unhandled exception, PL/SQL does not assign values to OUT parameters. Also, PL/SQL does not roll back database work done by the subprogram.

Page 33: Oracle Plsql

Oracle PL/SQL

Jayashree Page 33 of 69

Example: DECLARE

emp_id emp.empno%TYPE;

BEGIN

...

UPDATE emp SET ... WHERE empno = emp_id;

DELETE FROM emp WHERE ...

...

SAVEPOINT do_insert;

INSERT INTO emp VALUES (emp_id, ...);

EXCEPTION

WHEN DUP_VAL_ON_INDEX THEN

ROLLBACK TO do_insert;

END;

Overriding Default Locking

• With the SELECT FOR UPDATE statement, you can explicitly lock specific rows of

a table to make sure they do not change before an update or delete is executed. However, Oracle automatically obtains row-level locks at update or delete time. So, use the FOR UPDATE clause only if you want to lock the rows before the update or delete.

• You can explicitly lock entire tables using the LOCK TABLE statement.

Using the FOR UPDATE Clause

DECLARE

CURSOR c1 IS

SELECT empno, sal FROM emp

WHERE job = 'SALESMAN' AND comm > sal FOR UPDATE;

• The FOR UPDATE clause identifies the rows that will be updated or deleted, then locks each row in the active set. This is useful when you want to base an update on the existing values in a row. In that case, you must make sure that the row is not changed by another user before the update.

• All rows are locked when you open the cursor, not as they are fetched. The rows are unlocked when you commit or roll back the transaction. So, you cannot fetch from a FOR UPDATE cursor after a commit.

• When querying multiple tables, you can use the FOR UPDATE clause to confine row

locking to particular tables. Rows in a table are locked only if the FOR UPDATE OF clause refers to a column in that table.

Page 34: Oracle Plsql

Oracle PL/SQL

Jayashree Page 34 of 69

• Example : DECLARE

CURSOR c1 IS

SELECT ename, sal, dname FROM emp, dept

WHERE emp.deptno = dept.deptno FOR UPDATE OF sal;

Using the CURRENT OF clause

You can use the CURRENT OF clause in UPDATE or DELETE statement to refer to the latest row fetched from a cursor : DECLARE

CURSOR c1 IS SELECT empno, job, sal FROM emp FOR UPDATE;

...

BEGIN

OPEN c1;

LOOP

FETCH c1 INTO ...

...

UPDATE emp SET sal = new_sal WHERE CURRENT OF c1;

END LOOP;

...

END;

Using the LOCK TABLE Command

• The LOCK TABLE statement can be used to lock entire database tables in a specified lock mode so that you can share or deny access to them. For example, the statement below locks the emp table in row share mode. Row share locks allow concurrent access to a table; they prevent other users from locking the entire table for exclusive use. Table locks are released when your transaction issues a commit or rollback.

LOCK TABLE emp IN ROW SHARE MODE NOWAIT;

The optional keyword NOWAIT tells Oracle not to wait, if the table has been locked by another user.

• A table lock never keeps other users from querying a table, and a query never acquires a table lock. Only if two different transactions try to modify the same row will one transaction wait for the other to complete.

Page 35: Oracle Plsql

Oracle PL/SQL

Jayashree Page 35 of 69

Error Handling in PL/SQL

Topics

• Exceptions

• Scope Rules

• Using EXCEPTION_INIT

• Propagation of Exception

• Re-raising an Exception

• SQLCODE and SQLERRM

Page 36: Oracle Plsql

Oracle PL/SQL

Jayashree Page 36 of 69

Exceptions

• In PL/SQL, a warning or error condition is called an exception. Exceptions can be internally defined (by the runtime system) or user defined.

• When an error occurs, an exception is raised. That is, normal execution stops and the control transfers to the exception-handling part of your PL/SQL block or subprogram.

• Internal exceptions are raised implicitly (automatically) by the runtime system.

• User-defined exceptions must be raised explicitly by RAISE statements, which can also raise predefined exceptions.

• To handle raised exceptions, you write separate routines called exception handlers.

• After an exception handler runs, the current block stops executing and the enclosing block resumes with the next statement. If there is no enclosing block, control returns to the host environment.

Pre-Defined Exceptions

Exception Raised when ...

ACCESS_INTO_NULL you try to assign values to the attributes of an uninitialized (atomically null) object.

COLLECTION_IS_NULL you you try to apply collection methods other than EXISTS to an uninitialized (atomically null) nested table or varray, or you try to assign values to the elements of an uninitialized nested table or varray.

CURSOR_ALREADY_OPEN you try to open an already open cursor. You must close a cursor before you can reopen it. A cursor FOR loop automatically opens the cursor to which it refers. So, you cannot open that cursor inside the loop.

DUP_VAL_ON_INDEX you try to store duplicate values in a database column that is constrained by a unique index.

INVALID_CURSOR you try an illegal cursor operation such as closing an unopened cursor.

INVALID_NUMBER in a SQL statement, the convertion of character string to a number fails because the character string does not represent a valid number. In procedural statements, VALUE_ERROR is raised.

Page 37: Oracle Plsql

Oracle PL/SQL

Jayashree Page 37 of 69

LOGIN_DENIED you try logging on to Oracle with an invalid username and/or password.

NO_DATA_FOUND a SELECT INTO statement returns no rows, or you reference a deleted element in a nested table, or you reference an uninitialized element in an index-by table. The FETCH statement is expected to return no rows eventually, so when that happens, no exception is raised. SQL group functions such as AVG and SUM always return a value or a null. So, a SELECT INTO statement that calls a group function will never raise NO_DATA_FOUND.

NOT_LOGGED_ON your PL/SQL program issues a database call without being connected to Oracle.

PROGRAM_ERROR PL/SQL has an internal problem. ROWTYPE_MISMATCH the host cursor variable and PL/SQL cursor

variable involved in an assignment have incompatible return types. For example, when you pass an open host cursor variable to a stored subprogram, the return types of the actual and formal parameters must be compatible.

STORAGE_ERROR PL/SQL runs out of memory or memory is corrupted.

SUBSCRIPT_BEYOND_COUNT you reference a nested table or varray element using an index number larger than the number of elements in the collection.

SUBSCRIPT_OUTSIDE_LIMIT

you reference a nested table or varray element using an index number that is outside the legal range (-1 for example).

TIMEOUT_ON_RESOURCE a timeout occurs while Oracle is waiting for a resource.

TOO_MANY_ROWS a SELECT INTO statement returns more than one row.

VALUE_ERROR an arithmetic, conversion, truncation, or size-constraint error occurs. For example, when you select a column value into a character variable, if the value is longer than the declared length of the variable, PL/SQL aborts the assignment and raises VALUE_ERROR. In procedural statements, VALUE_ERROR is raised if the conversion of a character string to a number fails. In SQL statements, INVALID_NUMBER is raised.

ZERO_DIVIDE you try to divide a number by zero.

Page 38: Oracle Plsql

Oracle PL/SQL

Jayashree Page 38 of 69

User-Defined Exceptions :

Example :

DECLARE

out_of_stock EXCEPTION;

q_o_h NUMBER(5); …

BEGIN

IF q_o_h < 1 THEN

RAISE out_of_stock;

END IF; …

EXCEPTION

WHEN out_of_stock THEN

/* Exception Handling code */

END;

Example : DECLARE

acct_type INTEGER; ...

BEGIN

...

IF acct_type NOT IN (1, 2, 3) THEN

RAISE INVALID_NUMBER; -- raise predefined exception

END IF;

...

EXCEPTION

WHEN INVALID_NUMBER THEN

ROLLBACK;

END;

Scope Rules

• You cannot declare an exception twice in the same block. You can, however, declare the same exception in two different blocks.

• Exceptions declared in a block are considered local to that block and global to all its sub-blocks. Because a block can reference only local or global exceptions, enclosing blocks cannot reference exceptions declared in a sub-block.

• If you redeclare a global exception in a sub-block, the local declaration prevails. So, the sub-block cannot reference the global exception unless it was declared in a labeled block, in which case the following syntax is valid:

block_label.exception_name

Page 39: Oracle Plsql

Oracle PL/SQL

Jayashree Page 39 of 69

Using EXCEPTION_INIT

• To handle unnamed internal exceptions, you must use the OTHERS handler or the pragma EXCEPTION_INIT. A pragma is a compiler directive, which can be thought of as a parenthetical remark to the compiler. Pragmas (also called pseudoinstructions) are processed at compile time, not at run time.

• In PL/SQL, the pragma EXCEPTION_INIT tells the compiler to associate an exception name with an Oracle error number. That allows you to refer to any internal exception by name and to write a specific handler for it.

• You can code the pragma EXCEPTION_INIT in the declarative part of a PL/SQL block, subprogram, or package using the syntax

PRAGMA EXCEPTION_INIT(exception_name, Oracle_error_number);

where exception_name is the name of a previously declared exception.

Example: DECLARE

deadlock_detected EXCEPTION;

PRAGMA EXCEPTION_INIT(deadlock_detected, -60);

BEGIN

...

EXCEPTION

WHEN deadlock_detected THEN

-- handle the error

...

END;

Propagation of Exception

• When an exception is raised, if PL/SQL cannot find a handler for it in the current block or subprogram, the exception propagates. That is, the exception reproduces itself in successive enclosing blocks until a handler is found or there are no more blocks to search. In the latter case, PL/SQL returns an unhandled exception error to the host environment.

Page 40: Oracle Plsql

Oracle PL/SQL

Jayashree Page 40 of 69

• An exception can propagate beyond its scope, that is, beyond the block in which it was declared.

Example : BEGIN

...

DECLARE ---------- sub-block begins

past_due EXCEPTION;

BEGIN

...

IF ... THEN

RAISE past_due;

END IF;

END; ------------- sub-block ends

EXCEPTION

...

WHEN OTHERS THEN

ROLLBACK;

END;

• Because the block in which it was declared has no handler for the exception named past_due, it propagates to the enclosing block. But, according to the scope rules, enclosing blocks cannot reference exceptions declared in a sub-block. So, only an OTHERS handler can catch the exception.

Re-raising an Exception

• Sometimes, you want to re raise an exception, that is, handle it locally, then pass it to an enclosing block. For example, you might want to roll back a transaction in the current block, then log the error in an enclosing block.

• To re raise an exception, simply place a RAISE statement in the local handler without an exception name.

Page 41: Oracle Plsql

Oracle PL/SQL

Jayashree Page 41 of 69

DECLARE

out_of_balance EXCEPTION;

BEGIN

...

BEGIN ---------- sub-block begins

...

IF ... THEN

RAISE out_of_balance; -- raise the exception

END IF;

EXCEPTION

WHEN out_of_balance THEN

-- handle the error

RAISE; -- reraise the current exception

...

END; ------------ sub-block ends

EXCEPTION

WHEN out_of_balance THEN

-- handle the error differently

...

END;

SQLCODE and SQLERRM

• In an exception handler, you can use the functions SQLCODE and SQLERRM to find out which error occurred and to get the associated error message.

• For internal exceptions, SQLCODE returns the number of the Oracle error. The number that SQLCODE returns is negative unless the Oracle error is no data found, in which case SQLCODE returns +100. SQLERRM returns the corresponding error message. The message begins with the Oracle error code.

• For user-defined exceptions, SQLCODE returns +1 and SQLERRM returns the message

User-Defined Exception

• If no exception has been raised, SQLCODE returns zero and SQLERRM returns the message : ORA-0000: normal, successful completion

Page 42: Oracle Plsql

Oracle PL/SQL

Jayashree Page 42 of 69

• You can pass an error number to SQLERRM, in which case SQLERRM returns the message associated with that error number. Make sure you pass negative error numbers to SQLERRM.

DECLARE

err_msg VARCHAR2(100); ...

BEGIN

...

/* Get all Oracle error messages. */

FOR err_num IN 1..9999 LOOP

err_msg := SQLERRM(-err_num);

INSERT INTO errors VALUES (err_msg);

END LOOP;

END;

• You cannot use SQLCODE or SQLERRM directly in a SQL statement. Instead, you must assign their values to local variables, then use the variables in the SQL statement, as the following example shows:

DECLARE err_num NUMBER; err_msg VARCHAR2(100);

BEGIN

...

EXCEPTION

...

WHEN OTHERS THEN

err_num := SQLCODE;

err_msg := SUBSTR(SQLERRM, 1, 100);

INSERT INTO errors VALUES (err_num,err_msg);

END;

Example: To update the ITEMMAST table using the ITTRAN table DECLARE

CURSOR t1 IS

SELECT itno, trandate, trantype, qty FROM ittran

WHERE upper(updt) = ‘N’ ORDER BY itno;

var_qoh itemmast.qoh%TYPE := 0;

BEGIN

FOR tran IN t1 LOOP

/* inner block */

DECLARE

out_of_stock EXCEPTION;

BEGIN

SELECT qoh INTO var_qoh FROM itemmast

WHERE itno = tran.itno;

Page 43: Oracle Plsql

Oracle PL/SQL

Jayashree Page 43 of 69

IF tran.trantype = ‘I’ THEN

IF tran.qty > var_qoh THEN

RAISE out_of_stock;

ELSE

UPDATE itemmast SET

qoh = qoh - tran.qty

WHERE itno = tran.itno;

END IF;

ELSE

UPDATE itemmast SET

qoh = qoh + tran.qty

WHERE itno = tran.itno;

END IF;

UPDATE ittran SET updt = ‘Y’

WHERE itno = tran.itno;

EXCEPTION

WHEN out_of_stock THEN

INSERT INTO errortab VALUES (tran.itno,

tran.trandate, tran.trantype,

tran.qty, ‘out of stock’ );

WHEN no_data_found THEN

INSERT INTO errortab VALUES (tran.itno,

tran.trandate, tran.trantype,

tran.qty,‘invalid item number’);

END; /* inner block */

END LOOP; /* FOR loop */

END; /* main block */

Page 44: Oracle Plsql

Oracle PL/SQL

Jayashree Page 44 of 69

Review Questions 1. Internal exceptions cannot be raised by the RAISE statement. (T / F) 2. A routine that is used to handle raised exceptions is called ____________________

______________________________________ 3. You can use an explicit GO TO statement in the exception handling part of a PL/SQL

block to go back to the statement following the one which raised the exception.(T / F) 4. The internal exception DUP_VAL_ON_INDEX means ______________________

___________________________________________________________________ 5. The internal exception TOO_MANY_ROWS is raised when __________________

___________________________________________________________________ 6. The exception handler which can catch any kind of exception raised is called

___________________________ 7. To get the error message of an error, you can use the function ___________________

Exercises 1. Consider the following tables :

ITEMMAST ITTRAN ITNO ITEMNO NAME TRANTYPE QOH (Quantity on hand) TRANQTY CLASS (Category) TRANDATE UOM (Unit of measurement) UPDT ROL (Re-order level) ROQ (Re-order quantity) RATE Update the itemmast table using the ittran table. Record all invalid transactions in another table.

Page 45: Oracle Plsql

Oracle PL/SQL

Jayashree Page 45 of 69

2. Suppose there are the two tables :

ACCOUNTS Account_id Balance

1 1000 2 2000 3 1500 4 6500 5 500

ACTION Account_id Oper_type New_value Status Time_tag 3 u 599 12-DEC-97 6 i 20099 12-DEC-97 5 d 12-DEC-97 7 u 1599 12-DEC-97 1 I 399 12-DEC-97 9 d 12-DEC-97 10 x 12-DEC-97 Accounts table is modified according to instructions stored in the action table. Each row in the action table contains an account number, an action to be taken (I, U, or D for insert, update, or delete), an amount by which to update the account, and a time tag used to sequence the transactions. On an insert, if the account already exists, an update is done instead. On an update, if the account does not exist, it is created by an insert. On a delete, if the row does not exist, no action is taken. In each case the status is written into the action

table.

Page 46: Oracle Plsql

Oracle PL/SQL

Jayashree Page 46 of 69

Subprograms and Packages

Topics

• What are Subprograms?

• Procedures

• Functions

• Declaring Subprograms

• Stored Subprograms

• Positional and Named Notation

• Overloading

• Recursion

• Packages

• Package STANDARD

• Product-Specific Packages

• Advantages of Packages

Page 47: Oracle Plsql

Oracle PL/SQL

Jayashree Page 47 of 69

What are Subprograms?

• Subprograms are named PL/SQL blocks that can take parameters and can be invoked.

• PL/SQL has two types of subprograms - procedures

- functions

• Generally, you use a procedure to perform an action and a function to compute a value.

• Subprograms have a declarative part, an executable part, and an optional exception-handling part.

• The declarative part contains declarations of types, cursors, constants, variables, exceptions, and nested subprograms. These objects are local and cease to exist when you exit the subprogram.

• The executable part contains statements that assign values, control execution, and manipulate Oracle data.

• The exception-handling part contains exception handlers, which deal with exceptions raised during execution.

Subprograms : Example PROCEDURE debit_account (acct_id INTEGER, amount REAL) IS

old_balance REAL;

new_balance REAL;

overdrawn EXCEPTION;

BEGIN

SELECT bal INTO old_balance FROM accts

WHERE acctno = acct_id;

new_balance := old_balance - amount;

IF new_balance < 0 THEN

RAISE overdrawn;

ELSE

UPDATE accts SET bal = new_balance

WHERE acctno = acct_id;

END IF;

EXCEPTION

WHEN overdrawn THEN

...

END debit_account;

Page 48: Oracle Plsql

Oracle PL/SQL

Jayashree Page 48 of 69

Procedures Syntax :

PROCEDURE name [(parameter[, parameter, ...])] IS

[local declarations]

BEGIN

executable statements

[EXCEPTION

exception handlers]

END [name];

where parameter stands for the following syntax:

parameter_name [IN|OUT|IN OUT] datatype

[{:=|DEFAULT} expr]

• You cannot specify a constraint on the datatype. Example : Procedure

PROCEDURE raise_salary (emp_id INTEGER, increase REAL) IS

current_salary REAL;

salary_missing EXCEPTION;

BEGIN

SELECT sal INTO current_salary FROM emp

WHERE empno = emp_id;

IF current_salary IS NULL THEN

RAISE salary_missing;

ELSE

UPDATE emp SET sal = sal + increase

WHERE empno = emp_id;

END IF;

EXCEPTION

WHEN NO_DATA_FOUND THEN

INSERT INTO emp_audit VALUES (emp_id, 'No such

number');

WHEN salary_missing THEN

INSERT INTO emp_audit VALUES (emp_id, 'Salary is

null');

END raise_salary;

Page 49: Oracle Plsql

Oracle PL/SQL

Jayashree Page 49 of 69

Functions Syntax :

FUNCTION name [(parameter[, parameter, ...])] RETURN datatype IS

[local declarations]

BEGIN

executable statements

[EXCEPTION

exception handlers]

END [name];

where parameter stands for the following syntax:

parameter_name [IN | OUT | IN OUT] datatype

[{:= | DEFAULT} expr]

Note, you cannot specify a constraint on the data type. Example : Function

The following function determines if an employee salary is out of range: FUNCTION sal_ok (salary REAL, title CHAR) RETURN BOOLEAN IS

min_sal REAL;

max_sal REAL;

BEGIN

SELECT losal, hisal INTO min_sal, max_sal

FROM sals

WHERE job = title;

RETURN (salary >= min_sal) AND (salary <= max_sal);

END sal_ok;

Parameter Modes

• IN Mode : An IN parameter lets you pass values to the subprogram being called. Inside the subprogram, an IN parameter acts like a constant. Therefore, it cannot be assigned a value. IN parameters can be initialized to default values.

• OUT Mode : An OUT parameter lets you return values to the caller of a subprogram. Inside the subprogram, an OUT parameter acts like an uninitialized variable. Therefore, its value cannot be assigned to another variable or reassigned to itself.

• IN OUT Mode : An IN OUT parameter lets you pass initial values to the subprogram being called and return updated values to the caller. Inside the subprogram, an IN OUT parameter acts like an initialized variable. Therefore, it can be assigned a value and its value can be assigned to another variable.

Page 50: Oracle Plsql

Oracle PL/SQL

Jayashree Page 50 of 69

Declaring Subprograms

• You can declare subprograms in any PL/SQL block, subprogram, or package.

However, you must declare subprograms at the end of a declarative section after all other program objects. DECLARE

rating NUMBER;

CURSOR c1 IS SELECT * FROM emp;

PROCEDURE award_bonus (...)

BEGIN

...

END;

• PL/SQL requires that you declare an identifier before using it. Therefore, you must declare a subprogram before calling it.

• Forward Declarations :You can use forward declarations to - define subprograms in logical or alphabetical order - define mutually recursive subprograms - group subprograms in a package

• A forward declaration consists of a subprogram specification terminated by a semicolon. DECLARE

PROCEDURE calc_rating ( ... ); -- forward declaration

...

/* Define subprograms in alphabetical order. */

PROCEDURE award_bonus ( ... ) IS

BEGIN

calc_rating( ... );

...

END;

PROCEDURE calc_rating ( ... ) IS

BEGIN

...

END;

Page 51: Oracle Plsql

Oracle PL/SQL

Jayashree Page 51 of 69

Stored Subprograms

• To create subprograms and store them permanently in an Oracle database, you use the CREATE PROCEDURE and CREATE FUNCTION statements, which you can execute interactively from SQL*Plus.

• Example : CREATE OR REPLACE PROCEDURE issue_qty (

iss_item itemmast.itno%TYPE, iss_qty NUMBER)

AS

BEGIN

UPDATE itemmast SET qoh = qoh - iss_qty

WHERE itno = iss_item;

COMMIT;

END;

The stored subprograms can be either called from a PL/SQL program or other subprogram, or can be executed directly at the SQL*PLUS prompt using the EXECUTE command :

SQL> EXECUTE issue_qty ( 6, 100 )

Actual and Formal Parameters

• Subprograms pass information using the parameters.

• The variables or expressions referenced in the parameter list of a subprogram call are actual parameters.

• The variables declared in a subprogram specification and referenced in the subprogram body are formal parameters.

• Though not necessary, it is good programming practice to use different names for actual and formal parameters.

• When you call procedure raise_salary, the actual parameters are evaluated and the result values are assigned to the corresponding formal parameters.

Page 52: Oracle Plsql

Oracle PL/SQL

Jayashree Page 52 of 69

Positional and Named Notation

• When calling a subprogram, you can indicate the association between an actual and formal parameter by position or name.

• Example : DECLARE acct INTEGER;

amt REAL;

PROCEDURE credit (acctno INTEGER, amount REAL) IS

BEGIN ... END;

you can call the procedure credit in four logically equivalent ways:

- credit(acct, amt); -- positional notation - credit(amount => amt, acctno => acct); -- named notation - credit(acctno => acct, amount => amt); -- named notation - credit(acct, amount => amt); -- mixed notation

Overloading

• PL/SQL lets you overload subprogram names. That is, you can use the same name for several different subprograms as long as their formal parameters differ in number, order, or data type family.

Example Suppose you want to initialize the first n rows in two index-by tables that were declared as follows: DECLARE

TYPE DateTabTyp IS TABLE OF DATE

INDEX BY BINARY_INTEGER;

TYPE RealTabTyp IS TABLE OF REAL

INDEX BY BINARY_INTEGER;

hiredate_tab DateTabTyp;

sal_tab RealTabTyp;

Procedure to initialize the index-by table named hiredate_tab: PROCEDURE initialize (tab OUT DateTabTyp, n INTEGER) IS

BEGIN

FOR i IN 1..n LOOP

tab(i) := SYSDATE;

END LOOP;

END initialize;

Page 53: Oracle Plsql

Oracle PL/SQL

Jayashree Page 53 of 69

Procedure to initialize the index-by table named sal_tab: PROCEDURE initialize (tab OUT RealTabTyp, n INTEGER) IS

BEGIN

FOR i IN 1..n LOOP

tab(i) := 0.0;

END LOOP;

END initialize;

You can place the two overloaded initialize procedures in the same block, subprogram, or package. PL/SQL determines which of the two procedures is being called by checking their formal parameters. DECLARE

TYPE DateTabTyp IS TABLE OF DATE

INDEX BY BINARY_INTEGER;

TYPE RealTabTyp IS TABLE OF REAL

INDEX BY BINARY_INTEGER;

hiredate_tab DateTabTyp;

comm_tab RealTabTyp;

indx BINARY_INTEGER;

...

BEGIN

indx := 50;

initialize(hiredate_tab, indx); -- calls first version

initialize(comm_tab, indx); -- calls second version

...

END;

• Only local or packaged subprograms can be overloaded. Therefore, you cannot overload standalone subprograms. Also, you cannot overload two subprograms if their formal parameters differ only in name or parameter mode.

• You cannot overload two subprograms if their formal parameters differ only in data type and the different data types are in the same family.

• Likewise, you cannot overload two subprograms if their formal parameters differ only in subtype and the different subtypes are based on types in the same family.

• Finally, you cannot overload two functions that differ only in return type (the data type of the result value) even if the types are in different families.

Page 54: Oracle Plsql

Oracle PL/SQL

Jayashree Page 54 of 69

Recursion

• PL/SQL supports recursive subprograms .

Example : FUNCTION fac (n POSITIVE) RETURN INTEGER IS

-- returns n!

BEGIN

IF n = 1 THEN -- terminating condition

RETURN 1;

ELSE

RETURN n * fac(n - 1); -- recursive call

END IF;

END fac;

Packages

• A package is a database object that groups logically related PL/SQL types, objects, and subprograms.

• Packages usually have two parts, a specification and a body, although sometimes the body is unnecessary.

• The specification is the interface to your applications; it declares the types, variables, constants, exceptions, cursors, and subprograms available for use.

• The body fully defines cursors and subprograms, and so implements the specification.

• Unlike subprograms, packages cannot be called, parameterized, or nested.

• To create packages and store them permanently in an Oracle database, you use the CREATE PACKAGE and CREATE PACKAGE BODY statements, which you can execute interactively from SQL*PLUS :

CREATE PACKAGE name AS -- specification (visible part)

-- public type and object declarations

-- subprogram specifications

END [name];

Page 55: Oracle Plsql

Oracle PL/SQL

Jayashree Page 55 of 69

CREATE PACKAGE BODY name AS -- body (hidden part)

-- private type and object declarations

-- subprogram bodies

[BEGIN

-- initialization statements]

END [name];

Package Interface

• The specification holds public declarations, which are visible to your application. The body holds implementation details and private declarations, which are hidden from your application.

• You can debug, enhance, or replace a package body without changing the interface (package specification) to the package body.

Example : Package

CREATE PACKAGE emp_actions AS -- specification

TYPE EmpRecTyp IS RECORD(emp_id INTEGER, salary REAL);

CURSOR desc_salary RETURN EmpRecTyp;

PROCEDURE hire_employee (

ename VARCHAR2,

job VARCHAR2,

mgr NUMBER,

sal NUMBER,

comm NUMBER,

deptno NUMBER);

PROCEDURE fire_employee (emp_id NUMBER);

END emp_actions;

Application Database Package

Specificatio

Body

Page 56: Oracle Plsql

Oracle PL/SQL

Jayashree Page 56 of 69

CREATE PACKAGE BODY emp_actions AS -- body

CURSOR desc_salary RETURN EmpRecTyp IS

SELECT empno, sal FROM emp ORDER BY sal DESC;

PROCEDURE hire_employee (

ename VARCHAR2,

job VARCHAR2,

mgr NUMBER,

sal NUMBER,

comm NUMBER,

deptno NUMBER) IS

BEGIN

INSERT INTO emp VALUES (empno_seq.NEXTVAL, ename,

job, mgr, SYSDATE, sal, comm, deptno);

END hire_employee;

PROCEDURE fire_employee (emp_id NUMBER) IS

BEGIN

DELETE FROM emp WHERE empno = emp_id;

END fire_employee;

END emp_actions;

Referencing Package Contents

• To reference the types, objects, and subprograms declared within a package specification, you use dot notation, as follows: - package_name.type_name

- package_name.object_name

- package_name.subprogram_name

• You can reference package contents from a database trigger, a stored subprogram, or an Oracle tool such as SQL*Plus.

Page 57: Oracle Plsql

Oracle PL/SQL

Jayashree Page 57 of 69

Package STANDARD

A package named STANDARD defines the PL/SQL environment. The package specification globally declares types, exceptions, and subprograms, which are available automatically to every PL/SQL program. For example, package STANDARD declares the following built-in function named ABS, which returns the absolute value of its argument: FUNCTION ABS (n NUMBER) RETURN NUMBER;

If you redeclare ABS in a PL/SQL program, your local declaration overrides the global declaration. However, you can still call the built-in function by using dot notation, as follows: ... STANDARD.ABS(x) ...

Most built-in functions are overloaded. For example, package STANDARD contains the following declarations: FUNCTION TO_CHAR (right DATE) RETURN VARCHAR2;

FUNCTION TO_CHAR (left NUMBER) RETURN VARCHAR2;

FUNCTION TO_CHAR (left DATE, right VARCHAR2)

RETURN VARCHAR2;

FUNCTION TO_CHAR (left NUMBER, right VARCHAR2)

RETURN VARCHAR2;

ORACLE Product-specific Packages

• Package DBMS_STANDARD : provides language facilities that help your application interact with Oracle. For instance, a procedure named raise_application_error lets you issue user-defined error messages. That way, you can report errors to an application and avoid returning unhandled exceptions.

• Package DBMS_SQL : allows PL/SQL to execute SQL data definition and data manipulation statements dynamically at run time.

• Package DBMS_ALERT : lets you use database triggers to alert an application when specific database values change. The alerts are transaction based and asynchronous (that is, they operate independently of any timing mechanism).

• Package DBMS_OUTPUT : enables you to display output from PL/SQL blocks and subprograms, which makes it easier to test and debug them. The put_line procedure outputs information to a buffer in the SGA. You display the information by calling the procedure get_line or by using the command SET SERVEROUTPUT ON in SQL*Plus.

Page 58: Oracle Plsql

Oracle PL/SQL

Jayashree Page 58 of 69

• Package DBMS_PIPE: allows different sessions to communicate over named pipes. (A pipe is an area of memory used by one process to pass information to another.) You can use the procedures pack_message and send_message to pack a message into a pipe, then send it to another session in the same instance. At the other end of the pipe, you can use the procedures receive_message and unpack_message to receive and unpack (read) the message. Named pipes are useful in many ways. For example, you can write routines in C that allow external servers to collect information, then send it through pipes to procedures stored in an Oracle database.

• Package UTL_FILE: allows your PL/SQL programs to read and write operating system (OS) text files. It provides a restricted version of standard OS stream file I/O, including open, put, get, and close operations.

When you want to read or write a text file, you call the function fopen, which returns a file handle for use in subsequent procedure calls. For example, the procedure put_line writes a text string and line terminator to an open file. The procedure get_line reads a line of text from an open file into an output buffer.

• Package UTL_HTTP: allows your PL/SQL programs to make hypertext transfer protocol (HTTP) callouts. You can use it to retrieve data from the internet, or to call Oracle Web Server cartidges. The package has two entry points, each of which accepts a URL (universal resource locator) string, contacts the specified site, and returns the requested data, which is usually in hypertext markup language (HTML) format.

Advantages of Packages Modularity : Packages let you encapsulate logically related types, objects, and subprograms in a named PL/SQL module. Each package is easy to understand, and the interfaces between packages are simple, clear, and well defined. Easier Application Design : When designing an application, you can code and compile a specification without its body. Once the specification has been compiled, stored subprograms that reference the package can be compiled as well. Information Hiding : With packages, you can specify which types, objects, and subprograms are public (visible and accessible) or private (hidden and inaccessible). For example, if a package contains four subprograms, three might be public and one private. The package hides the definition of the private subprogram so that only the package (not your application) is affected if the definition changes. This simplifies maintenance and enhancement. Also, by hiding implementation details from users, you protect the integrity of the package.

Page 59: Oracle Plsql

Oracle PL/SQL

Jayashree Page 59 of 69

Added Functionality : Packaged public variables and cursors persist for the duration of a session. So, they can be shared by all subprograms that execute in the environment. Also, they allow you to maintain data across transactions without having to store it in the database. Better Performance : When you call a packaged subprogram for the first time, the whole package is loaded into memory. Therefore, subsequent calls to related subprograms in the package require no disk I/O.

Exercises 1. Create a function to return an employee’s bonus that is based on his salary and

department to which he belongs. If he belongs to department 10 and is not a clerk or salesman, then he receives 4% bonus on his salary. If he belongs to department 10 and is a clerk or salesman, then he receives 5% bonus on his salary. All others receive 6% of salary as bonus. Test this function at the SQL*PLUS prompt using the command EXECUTE.

2. Create a procedure that accepts an argument n, and determines the top n employees

with respect to salary. The procedure should display the ename and sal of these employees, as well as record the results in a table called TOP_SAL. Call this procedure from a PL/SQL block, or test it at the SQL*PLUS prompt using the command EXECUTE.

3. Create a PL/SQL block that calls a recursive function fact to compute and display the

factorials of !..n numbers. 4. Create procedures for the following (refer to the ITEMMAST table):

a) Item issue updation b) Item receipt updation c) Adding a new item Execute these procedures with the EXECUTE command.

Page 60: Oracle Plsql

Oracle PL/SQL

Jayashree Page 60 of 69

Database Triggers

Topics

• Introduction to Triggers

• Creating a Database Trigger

• Triggers Examples

• INSTEAD OF Triggers

• Trigger Execution

Page 61: Oracle Plsql

Oracle PL/SQL

Jayashree Page 61 of 69

Introduction to Triggers

• A database trigger is a stored PL/SQL procedure that is associated with a table, and that is implicitly executed when an INSERT, UPDATE, or DELETE statement is issued against the associated table.

• Oracle automatically executes a trigger when a specified SQL statement is issued

against the table.

• Triggers can supplement the standard capabilities of Oracle to provide a highly customized database management system. For example, a trigger can restrict DML operations against a table to those issued during regular business hours. A trigger could also restrict DML operations to occur only at certain times during weekdays. Other uses for triggers are to: - automatically generate derived column values - prevent invalid transactions - enforce complex security authorizations - enforce referential integrity across nodes in a distributed database - enforce complex business rules - provide transparent event logging - provide sophisticated auditing - maintain synchronous table replicates - gather statistics on table access

Creating a Database Trigger

CREATE [OR REPLACE] TRIGGER trigger-name

[BEFORE | AFTER]

{DELETE|INSERT|UPDATE [OF column [, column]…}

[OR {DELETE|INSERT|UPDATE [OF column [,column]…}]...

ON table

[REFERENCING {OLD [AS] old | NEW [AS] new}]

[FOR EACH ROW]

[WHEN (condition)]

PL/SQL Block

Page 62: Oracle Plsql

Oracle PL/SQL

Jayashree Page 62 of 69

Parts of a Trigger

• Triggering statement : DELETE, INSERT, UPDATE - The definition of the triggering statement specifies what SQL statements cause Oracle to fire the trigger. You must also specify the table with which the trigger is associated. The triggering statement is one that modifies this table.

• Trigger restriction : The trigger restriction specifies an additional condition that must be satisfied for a row trigger to be fired. You can specify this condition with the WHEN clause.

• Trigger action : The trigger action specifies the PL/SQL block Oracle executes to fire the trigger.

Oracle evaluates the condition of the trigger restriction whenever a triggering statement is issued. If this condition is satisfied, then Oracle fires the trigger using the trigger action.

REFERENCING : specifies correlation names. You can use correlation names in the PL/SQL block and WHEN clause of a row trigger to refer specifically to old and new values of the current row. The default correlation names are OLD and NEW. If your row trigger is associated with a table named OLD or NEW, you can use this clause to specify different correlation names to avoid confusion between the table name and the correlation name. WHEN : specifies the trigger restriction. The trigger restriction contains a SQL condition that must be satisfied for Oracle to fire the trigger. Types of Triggers

Row-Level Triggers execute once for each row in a transaction

Statement-Level Triggers execute once for each transaction

BEFORE and AFTER Triggers executed immediately before or after inserts, updates or deletes

With FOR EACH ROW

option

BEFORE Option ORACLE fires the trigger only once, before executing the triggering statement

ORACLE fires the trigger before modifying each row affected by the triggering statement

AFTER Option ORACLE fires the trigger only once, after executing the triggering statement

ORACLE fires the trigger after modifying each row affected by the triggering statement

Page 63: Oracle Plsql

Oracle PL/SQL

Jayashree Page 63 of 69

Triggers Examples

1. To create a trigger for emp table to check the salary range, while inserting a value for sal column or updating the sal column of an existing employee :

CREATE TRIGGER salary_check

BEFORE

INSERT OR UPDATE OF sal, job ON emp

FOR EACH ROW

WHEN (new.job <> 'PRESIDENT')

DECLARE

minsal NUMBER;

maxsal NUMBER;

BEGIN

/* Get the minimum and maximum salaries for the

employee's job from the SAL_GUIDE table. */

SELECT min_sal, max_sal INTO minsal, maxsal

FROM sal_guide WHERE job = :new.job;

/* If the employee's salary is out of range */

/* then generate an error */

IF(:new.sal < minsal OR :new.sal > maxsal) THEN

raise_application_error( -20601, 'Salary '

|| :new.sal || ' out of range for job '

|| :new.job || ' for employee ' ||

:new.ename );

END IF;

END;

2. Whenever there is a deletion of row(s) from the emp table, details regarding the user, and the empno of the row deleted should be logged into another table del_history.

CREATE OR REPLACE TRIGGER del_check

AFTER DELETE

ON EMP

FOR EACH ROW

BEGIN

INSERT INTO del_history VALUES (USER, :old.empno);

END;

Page 64: Oracle Plsql

Oracle PL/SQL

Jayashree Page 64 of 69

3. Ensure that the names of employees in the emp table are always in upper case.

CREATE OR REPLACE TRIGGER upcase

BEFORE INSERT OR UPDATE OF ename

ON EMP

FOR EACH ROW

BEGIN

:new.ename := UPPER(:new.ename);

END;

4. Record all the types of operations done on the emp table along with the time.

CREATE OR REPLACE TRIGGER opn_check

AFTER INSERT OR DELETE OR UPDATE

ON EMP

FOR EACH ROW

BEGIN

IF INSERTING THEN

INSERT INTO opn_history VALUES

(‘INSERT’, TO_CHAR(SYSDATE, ’HH:MI:SS’));

ELSIF DELETING THEN

INSERT INTO opn_history VALUES

(‘DELETE’, TO_CHAR(SYSDATE, ’HH:MI:SS’));

ELSIF UPDATING THEN

INSERT INTO opn_history VALUES

(‘UPDATE’, TO_CHAR(SYSDATE, ’HH:MI:SS’));

END IF;

END;

5. Suppose you have a table, SAL, and you want to know when the table is being accessed and the types of queries being issued. The example below contains a sample package and trigger that tracks this information by hour and type of action (for example, UPDATE, DELETE, or INSERT) on table SAL. A global session variable, STAT.ROWCNT, is initialized to zero by a BEFORE statement trigger. Then it is increased each time the row trigger is executed. Finally the statistical information is saved in the table STAT_TAB by the AFTER statement trigger.

DROP TABLE stat_tab;

CREATE TABLE stat_tab(utype CHAR(8),

rowcnt INTEGER, uhour INTEGER);

CREATE OR REPLACE PACKAGE stat IS

rowcnt INTEGER;

END;

Page 65: Oracle Plsql

Oracle PL/SQL

Jayashree Page 65 of 69

CREATE TRIGGER bt BEFORE UPDATE OR DELETE OR INSERT ON

sal

BEGIN

stat.rowcnt := 0;

END;

CREATE TRIGGER rt BEFORE UPDATE OR DELETE OR INSERT ON

sal

FOR EACH ROW BEGIN

stat.rowcnt := stat.rowcnt + 1;

END;

CREATE TRIGGER at AFTER UPDATE OR DELETE OR INSERT ON sal

DECLARE

typ CHAR(8);

hour NUMBER;

BEGIN

IF updating THEN typ := 'update'; END IF;

IF deleting THEN typ := 'delete'; END IF;

IF inserting THEN typ := 'insert'; END IF;

hour := TRUNC((SYSDATE - TRUNC(SYSDATE)) * 24);

UPDATE stat_tab

SET rowcnt = rowcnt + stat.rowcnt

WHERE utype = typ

AND uhour = hour;

IF SQL%ROWCOUNT = 0 THEN

INSERT INTO stat_tab VALUES (typ, stat.rowcnt, hour);

END IF;

EXCEPTION

WHEN dup_val_on_index THEN

UPDATE stat_tab

SET rowcnt = rowcnt + stat.rowcnt

WHERE utype = typ

AND uhour = hour;

END;

Page 66: Oracle Plsql

Oracle PL/SQL

Jayashree Page 66 of 69

INSTEAD OF Triggers

• INSTEAD OF triggers provide a transparent way of modifying views that cannot be modified directly through SQL DML statements (INSERT, UPDATE, and DELETE). These triggers are called INSTEAD OF triggers because, unlike other types of triggers, Oracle fires the trigger instead of executing the triggering statement. The trigger performs update, insert, or delete operations directly on the underlying tables.

• Users write normal INSERT, DELETE, and UPDATE statements against the view and the INSTEAD OF trigger works invisibly in the background to make the right actions take place. By default, INSTEAD OF triggers are activated for each row.

Modifying Views Modifying views has inherent problems of ambiguity.

• Deleting a row in a view could either mean deleting it from the base table or updating some column values so that it will no longer be selected by the view.

• Inserting a row in a view could either mean inserting a new row into the base table or updating an existing row so that it will be projected by the view.

• Updating a column in a view that involves joins might change the semantics of other columns that are not projected by the view.

Object views present additional problems. For example, a key use of object views is to represent master/detail relationships. This inevitably involves joins, but modifying joins is inherently ambiguous. As a result of these ambiguities, there are many restrictions on which views are modifiable. An INSTEAD OF trigger can be used on object views as well as relational views that are not otherwise modifiable. Example of an INSTEAD OF Trigger The following example shows an INSTEAD OF trigger for inserting rows into the MANAGER_INFO view. CREATE VIEW manager_info AS

SELECT e.name, e.empno, d.dept_type, d.deptno, p.level,

p.projno

FROM emp e, dept d, project p

WHERE e.empno = d.mgr_no

AND d.deptno = p.resp_dept;

Page 67: Oracle Plsql

Oracle PL/SQL

Jayashree Page 67 of 69

CREATE TRIGGER manager_info_insert

INSTEAD OF INSERT ON manager_info

REFERENCING NEW AS n

-- new manager information

FOR EACH ROW

BEGIN

IF NOT EXISTS SELECT * FROM emp

WHERE emp.empno = :n.empno

THEN

INSERT INTO emp

VALUES(:n.empno, :n.name);

ELSE

UPDATE emp SET emp.name = :n.name

WHERE emp.empno = :n.empno;

END IF;

IF NOT EXISTS SELECT * FROM dept

WHERE dept.deptno = :n.deptno

THEN

INSERT INTO dept

VALUES(:n.deptno, :n.dept_type);

ELSE

UPDATE dept SET dept.dept_type = :n.dept_type

WHERE dept.deptno = :n.deptno;

END IF;

IF NOT EXISTS SELECT * FROM project

WHERE project.projno = :n.projno

THEN

INSERT INTO project

VALUES(:n.projno, :n.project_level);

ELSE

UPDATE project SET project.level = :n.level

WHERE project.projno = :n.projno;

END IF;

END;

Page 68: Oracle Plsql

Oracle PL/SQL

Jayashree Page 68 of 69

Trigger Execution

A trigger can be in either of two distinct modes:

enabled An enabled trigger executes its trigger action if a triggering statement is issued and the trigger restriction (if any) evaluates to TRUE.

disabled A disabled trigger does not execute its trigger action, even if a triggering statement is issued and the trigger restriction (if any) would evaluate to TRUE.

For enabled triggers, Oracle automatically

• executes triggers of each type in a planned firing sequence when more than one trigger is fired by a single SQL statement

• performs integrity constraint checking at a set point in time with respect to the different types of triggers and guarantees that triggers cannot compromise integrity constraints

• provides read-consistent views for queries and constraints

• manages the dependencies among triggers and objects referenced in the code of the trigger action

• uses two-phase commit if a trigger updates remote tables in a distributed database

• fires multiple triggers in an unspecified order, if more than one trigger of the same type exists for a given statement

Page 69: Oracle Plsql

Oracle PL/SQL

Jayashree Page 69 of 69

Exercises 1. Write a database trigger to automatically update the commission of employees in the

EMP table who are salesmen, as newcomm = oldcomm * (newsal / oldsal). 2. Create a trigger to make sure that the increase in salary for employees in the EMP

table is only 10% of the previous salary. 3. Create a trigger to change the deptno in the EMP table whenever changes occur in the

DEPT table. 4. Prevent users from modifying the EMP table at times other than between 8:30 am and

6:00 pm on week days. 5. Create database triggers to (refer to the ITEMMAST table) :

a) Check the QOH column value before any issue is made. b) Store the necessary details in a table called RE_ORD, in case the QOH goes below ROL for that item. c) Check the ROQ value in case of receipt of an item. If the receipt is more than the ROQ value, then the trigger should fire for a confirmation.

6. Consider the two tables: EMP DEPT

EMPNO DEPTNO DEPTNO DNAME 1 10 10 SALES 2 10 20 RESEARCH 3 30 30 OPERATIONS 4 20 40 PRODUCTION 5 20

Create a view emp_dept on these two tables, that selects empno, deptno, and dname

columns. Write an INSTEAD OF trigger for insert, which will allow you to execute the following commands successfully: INSERT INTO emp_dept VALUES (4, 30, ‘SUPPORT’);

INSERT INTO emp_dept VALUES (6, 30, ‘OPERATIONS’);

INSERT INTO emp_dept VALUES (7, 50, ‘SUPPORT’);


Recommended