UNIT 4 PL SQL
UNIT 4 PL SQL
of SQL with procedural statements. All the statements of a block are passed to
oracle engine all at once which increases processing speed and decreases the traffic.
Disadvantages of SQL:
SQL doesn’t provide the programmers with a technique of condition checking,
looping and branching.
SQL statements are passed to Oracle engine one at a time which increases traffic
and decreases speed.
SQL has no facility of error checking during manipulation of data.
Features of PL/SQL:
1. PL/SQL is basically a procedural language, which provides the functionality of
decision making, iteration and many more features of procedural programming
languages.
2. PL/SQL can execute a number of queries in one block using single command.
3. One can create a PL/SQL unit such as procedures, functions, packages, triggers,
and types, which are stored in the database for reuse by applications.
4. PL/SQL provides a feature to handle the exception which occurs in PL/SQL
block known as exception handling block.
5. Applications written in PL/SQL are portable to computer hardware or operating
system where Oracle is operational.
6. PL/SQL Offers extensive error checking.
Differences between SQL and PL/SQL:
SQL PL/SQL
Typically, each block performs a logical action in the program. A block has the
following structure:
DECLARE
declaration statements;
BEGIN
executable statements
EXCEPTIONS
exception handling statements
END;
Declare section starts with DECLARE keyword in which variables, constants,
records as cursors can be declared which stores data temporarily. It basically
consists definition of PL/SQL identifiers. This part of the code is optional.
Execution section starts with BEGIN and ends with END keyword.This is a
mandatory section and here the program logic is written to perform any task like
loops and conditional statements. It supports all DML commands, DDL commands
and SQL*PLUS built-in functions as well.
Exception section starts with EXCEPTION keyword.This section is optional
which contains statements that are executed when a run-time error occurs. Any
exceptions can be handled in this section.
PL/SQL identifiers
There are several PL/SQL identifiers such as variables, constants, procedures, cursors,
triggers etc.
1. Variables:
Like several other programming languages, variables in PL/SQL must be
declared prior to its use. They should have a valid name and data type as well.
Syntax for declaration of variables:
variable_name datatype [NOT NULL := value ];
Example to show how to declare variables in PL/SQL :
SQL> DECLARE
var1 INTEGER;
var2 REAL;
var3 varchar2(20) ;
BEGIN
null;
END;
/
Every PL/SQL statement ends with a semicolon (;). PL/SQL blocks can be nested
within other PL/SQL blocks using BEGIN and END. Following is the basic structure of
a PL/SQL block −
DECLARE
<declarations section>
BEGIN
<executable command(s)>
EXCEPTION
<exception handling>
END;
Delimiter Description
+, -, *, / Addition, subtraction/negation, multiplication, division
% Attribute indicator
. Component selector
, Item separator
= Relational operator
; Statement terminator
:= Assignment operator
|| Concatenation operator
** Exponentiation operator
<<, >> Label delimiter (begin and end)
.. Range operator
1 Numeric
Numeric values on which arithmetic operations are performed.
2 Character
Alphanumeric values that represent single characters or strings of characters.
3 Boolean
Logical values on which logical operations are performed.
4 Datetime
Dates and times.
PL/SQL provides subtypes of data types. For example, the data type NUMBER has a
subtype called INTEGER. You can use the subtypes in your PL/SQL program to make
the data types compatible with data types in other programs while embedding the
PL/SQL code in another program, such as a Java program.
NUMBER(prec, scale)
1
Fixed-point or floating-point number with absolute value in range 1E-130 to (but not
including) 1.0E126. A NUMBER variable can also represent 0
2 DEC(prec, scale)
ANSI specific fixed-point type with maximum precision of 38 decimal digits
3 DECIMAL(prec, scale)
IBM specific fixed-point type with maximum precision of 38 decimal digits
4 NUMERIC(pre, scale)
Floating type with maximum precision of 38 decimal digits
FLOAT
5
ANSI and IBM specific floating-point type with maximum precision of 126 binary
digits (approximately 38 decimal digits)
6 INT
ANSI specific integer type with maximum precision of 38 decimal digits
7 INTEGER
ANSI and IBM specific integer type with maximum precision of 38 decimal digits
8 SMALLINT
ANSI and IBM specific integer type with maximum precision of 38 decimal digits
REAL
9
Floating-point type with maximum precision of 63 binary digits (approximately 18
decimal digits)
DECLARE
num1 INTEGER;
num2 REAL;
num3 DOUBLE PRECISION;
BEGIN
null;
END;
When the above code is compiled and executed, it produces the following result −
PL/SQL procedure successfully completed
1 CHAR
Fixed-length character string with maximum size of 32,767 bytes
2 VARCHAR2
Variable-length character string with maximum size of 32,767 bytes
RAW
3
Variable-length binary or byte string with maximum size of 32,767 bytes, not
interpreted by PL/SQL
4 NCHAR
Fixed-length national character string with maximum size of 32,767 bytes
5 NVARCHAR2
Variable-length national character string with maximum size of 32,767 bytes
6 LONG
Variable-length character string with maximum size of 32,760 bytes
LONG RAW
7
Variable-length binary or byte string with maximum size of 32,760 bytes, not
interpreted by PL/SQL
8 ROWID
Physical row identifier, the address of a row in an ordinary table
MONTH 01 to 12 0 to 11
HOUR 00 to 23 0 to 23
MINUTE 00 to 59 0 to 59
NULLs in PL/SQL
PL/SQL NULL values represent missing or unknown data and they are not an
integer, a character, or any other specific data type. Note that NULL is not the same as
an empty data string or the null character value '\0'. A null can be assigned but it
cannot be equated with anything, including itself.
PL/SQL programming language allows to define various types of variables, such as
date time data types, records, collections, etc. which we will cover in subsequent
chapters. For this chapter, let us study only basic variable types.
Table Created
Let us now insert some values in the table −
INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY)
VALUES (1, 'Ramesh', 32, 'Ahmedabad', 2000.00 );
Declaring a Constant
A constant is declared using the CONSTANT keyword. It requires an initial value and
does not allow that value to be changed. For example −
PI CONSTANT NUMBER: = 3.141592654;
DECLARE
-- constant declaration
pi constant number := 3.141592654;
-- other declarations
radius number(5,2);
dia number(5,2);
circumference number(7, 2);
area number (10, 2);
BEGIN
-- processing
radius := 9.5;
dia := radius * 2;
circumference := 2.0 * pi * radius;
area := pi * radius * radius;
-- output
dbms_output.put_line('Radius: ' || radius);
dbms_output.put_line('Diameter: ' || dia);
dbms_output.put_line('Circumference: ' || circumference);
dbms_output.put_line('Area: ' || area);
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
Radius: 9.5
Diameter: 19
Circumference: 59.69
Area: 283.53
IF - THEN statement
1
The IF statement associates a condition with a sequence of statements enclosed
by the keywords THEN and END IF. If the condition is true, the statements get
executed and if the condition is false or NULL then the IF statement does nothing.
IF-THEN-ELSE statement
2
IF statement adds the keyword ELSE followed by an alternative sequence of
statement. If the condition is false or NULL, then only the alternative sequence of
statements get executed. It ensures that either of the sequence of statements is
executed.
IF-THEN-ELSIF statement
3
It allows you to choose between several alternatives.
Case statement
Like the IF statement, the CASE statement selects one sequence of statements to
4 execute.
However, to select the sequence, the CASE statement uses a selector rather than
multiple Boolean expressions. A selector is an expression whose value is used to
select one of several alternatives.
nested IF-THEN-ELSE
5
You can use one IF-THEN or IF-THEN-ELSIF statement inside another IF-
THEN or IF-THEN-ELSIF statement(s).
PL/SQL - Loops
PL/SQL provides the following types of loop to handle the looping requirements. Click
the following links to check their detail.
1
In this loop structure, sequence of statements is enclosed between the LOOP and
the END LOOP statements. At each iteration, the sequence of statements is
executed and then control resumes at the top of the loop.
EXIT statement
1
The Exit statement completes the loop and control passes to the statement
immediately after the END LOOP.
CONTINUE statement
2
Causes the loop to skip the remainder of its body and immediately retest its
condition prior to reiterating.
GOTO statement
3
Transfers control to the labeled statement. Though it is not advised to use the
GOTO statement in your program.
PL/SQL - Arrays
In this chapter, we will discuss arrays in PL/SQL. The PL/SQL programming language
provides a data structure called the VARRAY, which can store a fixed-size sequential
collection of elements of the same type. A varray is used to store an ordered collection
of data, however it is often better to think of an array as a collection of variables of the
same type.
All varrays consist of contiguous memory locations. The lowest address corresponds to
the first element and the highest address to the last element.
An array is a part of collection type data and it stands for variable-size arrays. We will
study other collection types in a later chapter 'PL/SQL Collections'.
Each element in a varray has an index associated with it. It also has a maximum size
that can be changed dynamically.
Type created.
The basic syntax for creating a VARRAY type within a PL/SQL block is −
TYPE varray_type_name IS VARRAY(n) of <element_type>
For example −
TYPE namearray IS VARRAY(5) OF VARCHAR2(10);
Type grades IS VARRAY(5) OF INTEGER;
Let us now work out on a few examples to understand the concept −
Example 1
PL/SQL - Procedures
A subprogram is a program unit/module that performs a particular task. These
subprograms are combined to form larger programs. This is basically called the
'Modular design'. A subprogram can be invoked by another subprogram or program
which is called the calling program.
A subprogram can be created −
Declarative Part
1 It is an optional part. However, the declarative part for a subprogram does not start
with the DECLARE keyword. It contains declarations of types, cursors, constants,
variables, exceptions, and nested subprograms. These items are local to the
subprogram and cease to exist when the subprogram completes execution.
Executable Part
2
This is a mandatory part and contains statements that perform the designated
action.
3 Exception-handling
This is again an optional part. It contains the code that handles run-time errors.
Creating a Procedure
A procedure is created with the CREATE OR REPLACE PROCEDURE statement.
The simplified syntax for the CREATE OR REPLACE PROCEDURE statement is as
follows −
CREATE [OR REPLACE] PROCEDURE procedure_name
[(parameter_name [IN | OUT | IN OUT] type [, ...])]
{IS | AS}
BEGIN
< procedure_body >
END procedure_name;
Where,
procedure-name specifies the name of the procedure.
[OR REPLACE] option allows the modification of an existing procedure.
The optional parameter list contains name, mode and types of the
parameters. IN represents the value that will be passed from outside and OUT
represents the parameter that will be used to return a value outside of the
procedure.
procedure-body contains the executable part.
The AS keyword is used instead of the IS keyword for creating a standalone
procedure.
Example
The following example creates a simple procedure that displays the string 'Hello
World!' on the screen when executed.
CREATE OR REPLACE PROCEDURE greetings
AS
BEGIN
dbms_output.put_line('Hello World!');
END;
/
When the above code is executed using the SQL prompt, it will produce the following
result −
Procedure created.
IN
An IN parameter lets you pass a value to the subprogram. It is a read-only
1 parameter. Inside the subprogram, an IN parameter acts like a constant. It cannot
be assigned a value. You can pass a constant, literal, initialized variable, or
expression as an IN parameter. You can also initialize it to a default value;
however, in that case, it is omitted from the subprogram call. It is the default
mode of parameter passing. Parameters are passed by reference.
OUT
2 An OUT parameter returns a value to the calling program. Inside the subprogram,
an OUT parameter acts like a variable. You can change its value and reference the
value after assigning it. The actual parameter must be variable and it is passed
by value.
IN OUT
3 An IN OUT parameter passes an initial value to a subprogram and returns an
updated value to the caller. It can be assigned a value and the value can be read.
The actual parameter corresponding to an IN OUT formal parameter must be a
variable, not a constant or an expression. Formal parameter must be assigned a
value. Actual parameter is passed by value.
This program finds the minimum of two values. Here, the procedure takes two numbers
using the IN mode and returns their minimum using the OUT parameters.
DECLARE
a number;
b number;
c number;
PROCEDURE findMin(x IN number, y IN number, z OUT number) IS
BEGIN
IF x < y THEN
z:= x;
ELSE
z:= y;
END IF;
END;
BEGIN
a:= 23;
b:= 45;
findMin(a, b, c);
dbms_output.put_line(' Minimum of (23, 45) : ' || c);
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
Minimum of (23, 45) : 23
This procedure computes the square of value of a passed value. This example shows
how we can use the same parameter to accept a value and then return another result.
DECLARE
a number;
PROCEDURE squareNum(x IN OUT number) IS
BEGIN
x := x * x;
END;
BEGIN
a:= 23;
squareNum(a);
dbms_output.put_line(' Square of (23): ' || a);
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
Square of (23): 529
Example
The following example illustrates how to create and call a standalone function. This
function returns the total number of CUSTOMERS in the customers table.
We will use the CUSTOMERS table, which we had created in the PL/SQL
Variables chapter −
Select * from customers;
+----+----------+-----+-----------+----------+
| ID | NAME | AGE | ADDRESS | SALARY |
+----+----------+-----+-----------+----------+
| 1 | Ramesh | 32 | Ahmedabad | 2000.00 |
| 2 | Khilan | 25 | Delhi | 1500.00 |
| 3 | kaushik | 23 | Kota | 2000.00 |
| 4 | Chaitali | 25 | Mumbai | 6500.00 |
| 5 | Hardik | 27 | Bhopal | 8500.00 |
| 6 | Komal | 22 | MP | 4500.00 |
+----+----------+-----+-----------+----------+
CREATE OR REPLACE FUNCTION totalCustomers
RETURN number IS
total number(2) := 0;
BEGIN
SELECT count(*) into total
FROM customers;
RETURN total;
END;
/
When the above code is executed using the SQL prompt, it will produce the following
result −
Function created.
Calling a Function
While creating a function, you give a definition of what the function has to do. To use a
function, you will have to call that function to perform the defined task. When a program
calls a function, the program control is transferred to the called function.
A called function performs the defined task and when its return statement is executed
or when the last end statement is reached, it returns the program control back to the
main program.
To call a function, you simply need to pass the required parameters along with the
function name and if the function returns a value, then you can store the returned
value. Following program calls the function totalCustomers from an anonymous block
−
DECLARE
c number(2);
BEGIN
c := totalCustomers();
dbms_output.put_line('Total no. of Customers: ' || c);
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
Total no. of Customers: 6
Example
BEGIN
num:= 6;
factorial := fact(num);
dbms_output.put_line(' Factorial '|| num || ' is ' ||
factorial);
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
Factorial 6 is 720
Implicit Cursors
Implicit cursors are automatically created by Oracle whenever an SQL statement is
executed, when there is no explicit cursor for the statement. Programmers cannot
control the implicit cursors and the information in it.
Whenever a DML statement (INSERT, UPDATE and DELETE) is issued, an implicit
cursor is associated with this statement. For INSERT operations, the cursor holds the
data that needs to be inserted. For UPDATE and DELETE operations, the cursor
identifies the rows that would be affected.
In PL/SQL, you can refer to the most recent implicit cursor as the SQL cursor, which
always has attributes such as %FOUND, %ISOPEN, %NOTFOUND,
and %ROWCOUNT. The SQL cursor has additional
attributes, %BULK_ROWCOUNT and %BULK_EXCEPTIONS, designed for use with
the FORALL statement. The following table provides the description of the most used
attributes −
%FOUND
1 Returns TRUE if an INSERT, UPDATE, or DELETE statement affected one or
more rows or a SELECT INTO statement returned one or more rows. Otherwise, it
returns FALSE.
%NOTFOUND
2 The logical opposite of %FOUND. It returns TRUE if an INSERT, UPDATE, or
DELETE statement affected no rows, or a SELECT INTO statement returned no
rows. Otherwise, it returns FALSE.
%ISOPEN
3
Always returns FALSE for implicit cursors, because Oracle closes the SQL cursor
automatically after executing its associated SQL statement.
%ROWCOUNT
4
Returns the number of rows affected by an INSERT, UPDATE, or DELETE
statement, or returned by a SELECT INTO statement.
Any SQL cursor attribute will be accessed as sql%attribute_name as shown below in
the example.
Example
We will be using the CUSTOMERS table we had created and used in the previous
chapters.
Select * from customers;
+----+----------+-----+-----------+----------+
| ID | NAME | AGE | ADDRESS | SALARY |
+----+----------+-----+-----------+----------+
| 1 | Ramesh | 32 | Ahmedabad | 2000.00 |
| 2 | Khilan | 25 | Delhi | 1500.00 |
| 3 | kaushik | 23 | Kota | 2000.00 |
| 4 | Chaitali | 25 | Mumbai | 6500.00 |
| 5 | Hardik | 27 | Bhopal | 8500.00 |
| 6 | Komal | 22 | MP | 4500.00 |
+----+----------+-----+-----------+----------+
The following program will update the table and increase the salary of each customer
by 500 and use the SQL%ROWCOUNT attribute to determine the number of rows
affected −
DECLARE
total_rows number(2);
BEGIN
UPDATE customers
SET salary = salary + 500;
IF sql%notfound THEN
dbms_output.put_line('no customers selected');
ELSIF sql%found THEN
total_rows := sql%rowcount;
dbms_output.put_line( total_rows || ' customers selected ');
END IF;
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
6 customers selected
+----+----------+-----+-----------+----------+
| ID | NAME | AGE | ADDRESS | SALARY |
+----+----------+-----+-----------+----------+
| 1 | Ramesh | 32 | Ahmedabad | 2500.00 |
| 2 | Khilan | 25 | Delhi | 2000.00 |
| 3 | kaushik | 23 | Kota | 2500.00 |
| 4 | Chaitali | 25 | Mumbai | 7000.00 |
| 5 | Hardik | 27 | Bhopal | 9000.00 |
| 6 | Komal | 22 | MP | 5000.00 |
+----+----------+-----+-----------+----------+
Explicit Cursors
Explicit cursors are programmer-defined cursors for gaining more control over
the context area. An explicit cursor should be defined in the declaration section of the
PL/SQL Block. It is created on a SELECT Statement which returns more than one row.
The syntax for creating an explicit cursor is −
CURSOR cursor_name IS select_statement;
Working with an explicit cursor includes the following steps −
Example
Table-based
Cursor-based records
User-defined records
Table-Based Records
The %ROWTYPE attribute enables a programmer to create table-
based and cursorbased records.
The following example illustrates the concept of table-based records. We will be using
the CUSTOMERS table we had created and used in the previous chapters −
DECLARE
customer_rec customers%rowtype;
BEGIN
SELECT * into customer_rec
FROM customers
WHERE id = 5;
dbms_output.put_line('Customer ID: ' || customer_rec.id);
dbms_output.put_line('Customer Name: ' || customer_rec.name);
dbms_output.put_line('Customer Address: ' ||
customer_rec.address);
dbms_output.put_line('Customer Salary: ' ||
customer_rec.salary);
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
Customer ID: 5
Customer Name: Hardik
Customer Address: Bhopal
Customer Salary: 9000
Cursor-Based Records
The following example illustrates the concept of cursor-based records. We will be
using the CUSTOMERS table we had created and used in the previous chapters −
DECLARE
CURSOR customer_cur is
SELECT id, name, address
FROM customers;
customer_rec customer_cur%rowtype;
BEGIN
OPEN customer_cur;
LOOP
FETCH customer_cur into customer_rec;
EXIT WHEN customer_cur%notfound;
DBMS_OUTPUT.put_line(customer_rec.id || ' ' ||
customer_rec.name);
END LOOP;
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
1 Ramesh
2 Khilan
3 kaushik
4 Chaitali
5 Hardik
6 Komal
User-Defined Records
PL/SQL provides a user-defined record type that allows you to define the different
record structures. These records consist of different fields. Suppose you want to keep
track of your books in a library. You might want to track the following attributes about
each book −
Title
Author
Subject
Book ID
Defining a Record
Accessing Fields
To access any field of a record, we use the dot (.) operator. The member access
operator is coded as a period between the record variable name and the field that we
wish to access. Following is an example to explain the usage of record −
DECLARE
type books is record
(title varchar(50),
author varchar(50),
subject varchar(100),
book_id number);
book1 books;
book2 books;
BEGIN
-- Book 1 specification
book1.title := 'C Programming';
book1.author := 'Nuha Ali ';
book1.subject := 'C Programming Tutorial';
book1.book_id := 6495407;
-- Book 2 specification
book2.title := 'Telecom Billing';
book2.author := 'Zara Ali';
book2.subject := 'Telecom Billing Tutorial';
book2.book_id := 6495700;
You can pass a record as a subprogram parameter just as you pass any other variable.
You can also access the record fields in the same way as you accessed in the above
example −
DECLARE
type books is record
(title varchar(50),
author varchar(50),
subject varchar(100),
book_id number);
book1 books;
book2 books;
PROCEDURE printbook (book books) IS
BEGIN
dbms_output.put_line ('Book title : ' || book.title);
dbms_output.put_line('Book author : ' || book.author);
dbms_output.put_line( 'Book subject : ' || book.subject);
dbms_output.put_line( 'Book book_id : ' || book.book_id);
END;
BEGIN
-- Book 1 specification
book1.title := 'C Programming';
book1.author := 'Nuha Ali ';
book1.subject := 'C Programming Tutorial';
book1.book_id := 6495407;
-- Book 2 specification
book2.title := 'Telecom Billing';
book2.author := 'Zara Ali';
book2.subject := 'Telecom Billing Tutorial';
book2.book_id := 6495700;
PL/SQL - Exceptions
An exception is an error condition during a program execution. PL/SQL supports
programmers to catch such conditions using EXCEPTION block in the program and an
appropriate action is taken against the error condition. There are two types of
exceptions −
System-defined exceptions
User-defined exceptions
Example
Let us write a code to illustrate the concept. We will be using the CUSTOMERS table
we had created and used in the previous chapters −
DECLARE
c_id customers.id%type := 8;
c_name customerS.Name%type;
c_addr customers.address%type;
BEGIN
SELECT name, address INTO c_name, c_addr
FROM customers
WHERE id = c_id;
DBMS_OUTPUT.PUT_LINE ('Name: '|| c_name);
DBMS_OUTPUT.PUT_LINE ('Address: ' || c_addr);
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line('No such customer!');
WHEN others THEN
dbms_output.put_line('Error!');
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
No such customer!
Raising Exceptions
Exceptions are raised by the database server automatically whenever there is any
internal database error, but exceptions can be raised explicitly by the programmer by
using the command RAISE. Following is the simple syntax for raising an exception −
DECLARE
exception_name EXCEPTION;
BEGIN
IF condition THEN
RAISE exception_name;
END IF;
EXCEPTION
WHEN exception_name THEN
statement;
END;
You can use the above syntax in raising the Oracle standard exception or any user-
defined exception. In the next section, we will give you an example on raising a user-
defined exception. You can raise the Oracle standard exceptions in a similar way.
User-defined Exceptions
PL/SQL allows you to define your own exceptions according to the need of your
program. A user-defined exception must be declared and then raised explicitly, using
either a RAISE statement or the
procedure DBMS_STANDARD.RAISE_APPLICATION_ERROR.
The syntax for declaring an exception is −
DECLARE
my-exception EXCEPTION;
Example
The following example illustrates the concept. This program asks for a customer ID,
when the user enters an invalid ID, the exception invalid_id is raised.
DECLARE
c_id customers.id%type := &cc_id;
c_name customerS.Name%type;
c_addr customers.address%type;
-- user defined exception
ex_invalid_id EXCEPTION;
BEGIN
IF c_id <= 0 THEN
RAISE ex_invalid_id;
ELSE
SELECT name, address INTO c_name, c_addr
FROM customers
WHERE id = c_id;
DBMS_OUTPUT.PUT_LINE ('Name: '|| c_name);
DBMS_OUTPUT.PUT_LINE ('Address: ' || c_addr);
END IF;
EXCEPTION
WHEN ex_invalid_id THEN
dbms_output.put_line('ID must be greater than zero!');
WHEN no_data_found THEN
dbms_output.put_line('No such customer!');
WHEN others THEN
dbms_output.put_line('Error!');
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
Enter value for cc_id: -6 (let's enter a value -6)
old 2: c_id customers.id%type := &cc_id;
new 2: c_id customers.id%type := -6;
ID must be greater than zero!
Pre-defined Exceptions
PL/SQL provides many pre-defined exceptions, which are executed when any
database rule is violated by a program. For example, the predefined exception
NO_DATA_FOUND is raised when a SELECT INTO statement returns no rows. The
following table lists few of the important pre-defined exceptions −
Oracle
Exception SQLCODE Description
Error
Triggers are stored programs, which are automatically executed or fired when some
events occur. Triggers are, in fact, written to be executed in response to any of the
following events −
A database manipulation (DML) statement (DELETE, INSERT, or UPDATE)
A database definition (DDL) statement (CREATE, ALTER, or DROP).
A database operation (SERVERERROR, LOGON, LOGOFF, STARTUP, or
SHUTDOWN).
Triggers can be defined on the table, view, schema, or database with which the event
is associated.
Benefits of Triggers
Creating Triggers
The syntax for creating a trigger is −
CREATE [OR REPLACE ] TRIGGER trigger_name
{BEFORE | AFTER | INSTEAD OF }
{INSERT [OR] | UPDATE [OR] | DELETE}
[OF col_name]
ON table_name
[REFERENCING OLD AS o NEW AS n]
[FOR EACH ROW]
WHEN (condition)
DECLARE
Declaration-statements
BEGIN
Executable-statements
EXCEPTION
Exception-handling-statements
END;
Where,
CREATE [OR REPLACE] TRIGGER trigger_name − Creates or replaces an
existing trigger with the trigger_name.
{BEFORE | AFTER | INSTEAD OF} − This specifies when the trigger will be
executed. The INSTEAD OF clause is used for creating trigger on a view.
{INSERT [OR] | UPDATE [OR] | DELETE} − This specifies the DML operation.
[OF col_name] − This specifies the column name that will be updated.
[ON table_name] − This specifies the name of the table associated with the
trigger.
[REFERENCING OLD AS o NEW AS n] − This allows you to refer new and old
values for various DML statements, such as INSERT, UPDATE, and DELETE.
[FOR EACH ROW] − This specifies a row-level trigger, i.e., the trigger will be
executed for each row being affected. Otherwise the trigger will execute just
once when the SQL statement is executed, which is called a table level trigger.
WHEN (condition) − This provides a condition for rows for which the trigger
would fire. This clause is valid only for row-level triggers.
Example
To start with, we will be using the CUSTOMERS table we had created and used in the
previous chapters −
Select * from customers;
+----+----------+-----+-----------+----------+
| ID | NAME | AGE | ADDRESS | SALARY |
+----+----------+-----+-----------+----------+
| 1 | Ramesh | 32 | Ahmedabad | 2000.00 |
| 2 | Khilan | 25 | Delhi | 1500.00 |
| 3 | kaushik | 23 | Kota | 2000.00 |
| 4 | Chaitali | 25 | Mumbai | 6500.00 |
| 5 | Hardik | 27 | Bhopal | 8500.00 |
| 6 | Komal | 22 | MP | 4500.00 |
+----+----------+-----+-----------+----------+
The following program creates a row-level trigger for the customers table that would
fire for INSERT or UPDATE or DELETE operations performed on the CUSTOMERS
table. This trigger will display the salary difference between the old values and new
values −
CREATE OR REPLACE TRIGGER display_salary_changes
BEFORE DELETE OR INSERT OR UPDATE ON customers
FOR EACH ROW
WHEN (NEW.ID > 0)
DECLARE
sal_diff number;
BEGIN
sal_diff := :NEW.salary - :OLD.salary;
dbms_output.put_line('Old salary: ' || :OLD.salary);
dbms_output.put_line('New salary: ' || :NEW.salary);
dbms_output.put_line('Salary difference: ' || sal_diff);
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
Trigger created.
The following points need to be considered here −
OLD and NEW references are not available for table-level triggers, rather you
can use them for record-level triggers.
If you want to query the table in the same trigger, then you should use the
AFTER keyword, because triggers can query the table or change it again only
after the initial changes are applied and the table is back in a consistent state.
The above trigger has been written in such a way that it will fire before any
DELETE or INSERT or UPDATE operation on the table, but you can write your
trigger on a single or multiple operations, for example BEFORE DELETE, which
will fire whenever a record will be deleted using the DELETE operation on the
table.
Triggering a Trigger
Let us perform some DML operations on the CUSTOMERS table. Here is one INSERT
statement, which will create a new record in the table −
INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY)
VALUES (7, 'Kriti', 22, 'HP', 7500.00 );
When a record is created in the CUSTOMERS table, the above create
trigger, display_salary_changes will be fired and it will display the following result −
Old salary:
New salary: 7500
Salary difference:
Because this is a new record, old salary is not available and the above result comes as
null. Let us now perform one more DML operation on the CUSTOMERS table. The
UPDATE statement will update an existing record in the table −
UPDATE customers
SET salary = salary + 500
WHERE id = 2;
When a record is updated in the CUSTOMERS table, the above create
trigger, display_salary_changes will be fired and it will display the following result −
Old salary: 1500
New salary: 2000
Salary difference: 500