You are on page 1of 49

INTRODUCTION TO PL/SQL

PL/SQL is a completely portable, high-performance transaction processing


language. PL/SQL provides a built-in interpreted and OS independent
programming environment.

Features of PL/SQL

 PL/SQL is tightly integrated with SQL.


 PL/SQL offers a variety of programming structures.
 PL/SQL offers extensive error checking.
 PL/SQL offers numerous data types.
 PL/SQL supports structured programming through functions and procedures.
 PL/SQL supports object-oriented programming.

Advantages of PL/SQL

 PL/SQL supports both static and dynamic SQL.


 Static SQL is the feature that allows to write SQL statements (DML
operations and transaction control ) directly in PL/SQL block.
 Dynamic PL/SQL refers to entire PL/SQL blocks of code that are
constructed dynamically, then compiled and executed.
 PL/SQL allows sending an entire block of statements to the database at one
time. This reduces network traffic and provides high performance for
applications.
 PL/SQL gives high productivity to programmers as it can query, transform,
and update data in a database.
 PL/SQL saves time on design and debugging by strong features, such as
exception handling, encapsulation, data hiding, and object-oriented data
types.
 Applications written in PL/SQL are fully portable.
 PL/SQL provides high security level.
 PL/SQL provides access to predefined SQL packages.
 PL/SQL provides support for Object-Oriented Programming.
 PL/SQL provides support for Developing Web Applications and Server
Pages.

PL/SQL block

PL/SQL is a block-structured language, meaning that PL/SQL programs are


divided and written in logical blocks of code.
Basic Structure of PL/SQL block

A PL/SQL block consists of four sub-parts as defined below out of which


only one is mandatory.

Header: An optional section .Used only for named blocks. It determines the way
the named block or program must be called.
Declaration section : An optional section. All identifies variables, cursors, and
subblocks that are referenced in the execution and exception sections are declared
here.
Execution section: This is the mandatory section.Statements the PL/SQL runtime
engine will execute at runtime are written here.
Exception section: Optional section.Handles exceptions to normal processing
(warnings and error conditions).

PL/SQL BLOCK Types:

PL/SQL blocks are of two types.

 Unnamed Blocks or Anonymous block


 Named Blocks or sub programs - Function,Procedure,Package,Trigger

Structure of Unnamed Block:

DECLARE

< declarations section> (optional )

BEGIN

execute at runtime>

EXCEPTION

< exception handling> (optional )

END;

Example:

DECLARE
str varchar2(20):= 'Hello, World!';

BEGIN

dbms_output.put_line(str);

END;

Data Types

Programmer has to declare every constant, variable, and parameter used in a


PL/SQL block with a data type.

Categories of data types in PL/SQL

 Predefined data types and subtypes


 User defined subtypes

Predefined PL/SQL data types are categorised into following categories:

 Scalar : Single values with no internal components


 Composite : Data items having internal components that are either scalar or
composite
 Reference : Pointers to other data items such as REF CURSORs

Commonly used predefined PL/SQL scalar Data Types are:

 Numeric : NUMBER etc.


 Characters : CHAR,VARCHAR2 etc.
 Boolean : BOOLEAN
 DateTime: DATE,TIMESTAMP etc.
 LOB : BLOB(binary LOB),CLOB(character LOB) etc.

Composite data types:

These are data items that have internal components. We can access and
manipulate each of these internal components individually.

For example, records in a table. Records have fields with different data types.
We can pass records to subprograms as a single parameter.

 %TYPE attribute is used to declare a scalar PL/SQL variables. Use of this


attribute ensures the type compatibility between table columns and PL/SQL
variables.
 %ROWTYPE attribute is used to declare a record that represents a row in a
table or a row from a query result set, without specifying the names and
types for the fields.

Syntax :

< Table_Name> . % TYPE;

< Table_Name> % ROWTYPE;

Variables

A variable is nothing but a name given to a storage area that programs can
manipulate.

 The name of a variable can be a single letter or a combination of letters ,


numerals, dollar signs, underscores.
 Length pf a variable name should not exceed 30 characters.
 Variable names are not case-sensitive.
 Cannot use a reserved PL/SQL keyword as a variable name.

Syntax :

variable_name [CONSTANT] datatype [NOT NULL] [:= |


DEFAULT initial_value]

Example:

sales number(10, 2);

emp_name varchar2(25);

address1 varchar2(100);

Initializing Variables in PL/SQL


When a variable is declared PL/SQL assigns a default value of NULL to the
variable.

Programmer can provide an initial value other than NULL to a variable using
assignment operator during declaration.

Example1:

My_counter number := 0;

My_greetings varchar2(20) := 'Have a Good Day';

Using INTO clause in a SELECT statement programmer can assign values to


variables from tables.

For each item in the SELECT list, there must be a corresponding, type- compatible
variable in the INTO list.

Example2:

SELECT ename,deptno INTO v_name,v_no FROM Employee.

Where v_name and v_no are variables declared with the data type same as the data
type ename and deptno columns of employee table respectively.

Example1:

A complete PL/SQL clock to print the name and salary of employees from
employee table.

DECLARE

empno NUMBER(3); emp_name employee.name%TYPE;

-- declares a variable emp_nam of type name attribute of employee table.

sal employee.salary%TYPE; -- declares a variable sal of type salary


attribute of employee table.

BEGIN

eno := &eno;
SELECT name, salary INTO emp_name, sal FROM employee

WHERE eno=empno;

DBMS_OUTPUT.PUT_LINE(emp_name);

DBMS_OUTPUT.PUT_LINE(salary);

END;

Example2:

PL/SQL clock to print the details of employees from employee table.

DECLARE

rs employee%ROWTYPE; -- rs is the variable declared to hold the entire


record of Employee table.

BEGIN

SELECT * INTO rs FROM employee WHERE eno=&eno;

DBMS_OUTPUT.PUT_LINE(rs)

END;

Operators

An operator is a symbol that tells the compiler to perform specific mathematical or


logical manipulation.

In PL/SQL , expressions are constructed using operands and operators.


An operand is a variable, constant, literal, or function call that contributes a value
to an expression.

An example of a simple arithmetic expression is as below:


A:=X+Y;

Here, A,X,Y are variables and := and + are operators.

Note: Variables must be declared before use.

The following types of operators are supported in PL/SQL.

 Arithmetic operators : +,,*,/,**


 Relational operators : =,<>,>,<,<=,>=,
 Comparison operators : LIKE,BETWEEN,NULL,IN Logical operators :
AND,OR,NOT
 Iterative control statements

There may be a situation a block of code need to be executed several number
of times. In general, statements are executed sequentially: The first
statement in a function is executed first, followed by the second, and so on.
 Iterative Control structures are of three types
a. Simple LOOP
b. WHILE Loop
b. FOR Loop

a. The Loop control statements
Loop control statements change execution from its normal sequence. When
execution leaves a scope, all automatic objects that were created in that
scope are destroyed. PL/SQL supports the following control statements.
Labelling loops also helps in taking the control outside a loop.

EXIT statement :- The Exit statement completes the loop and control
passes to the statement immediately after END LOOP. When the EXIT
statement is encountered inside a loop, the loop is immediately terminated
and program control moves to the next statement following the loop. If
nested loops are used the EXIT statement will stop the execution of the inner
loop and starts executing
the next line of program after the block.
 Syntax:
EXIT;
 EXIT-WHEN statement :- It allows the condition in the WHEN clause to
be evaluated. If the condition is true, the loop completes and the control
moves to the statement immediately after END LOOP. Until the condition is
true, the EXIT WHEN statement acts like a NULL statement, except for
evaluating the
condition, and does not terminate the loop.
Syntax:
EXIT WHEN condition;
 CONTINUE statement :- Causes the loop to skip the remainder of its body
and
immediately retests its condition prior to reiterating.
 b. FOR Loop
 The FOR Loop executes for a specified number of times, defined in the loop
definition. Simple FOR loops iterate over a specified range of integers. The
number of iterations is known before the loop is entered.
 Syntax:
FOR counter IN lower_bound .. upper_bound
LOOP
Statements;
END LOOP;

A double dot (..) serves as the range operator. The range is evaluated when
the FOR loop is first entered and is never re-evaluated. After each iteration,
the loop counter is incremented.
 The initial step is executed first, and only once. This step allows you to
declare and initialize any loop control variables. Next, the condition, i.e.,
lower_bound .. upper_bound is evaluated. If it is TRUE, the body of the loop
is executed. If it is FALSE, the body of the loop does not execute and flow
of control jumps to the next statement just after the FOR loop. After the
body of the FOR loop executes, the value of the counter variable isincreased
or decreased. The condition is now evaluated again. If it is TRUE, the loop
executes and the process repeats itself . After the condition becomes FALSE,
the FORLOOP terminates.
 Example:
BEGIN
FOR i IN 1..10
LOOP
DBMS_OUTPUT.PUT_LINE(i);
END LOOP;
END;
 Reverse FOR loop
 By default, iteration proceeds from the lower_bound to the upper_bound.
This order can be reversed by using the REVERSE keyword. In such case,
iteration proceeds the other way. After each iteration, the loop counter is
decremented.
 Syntax:
FOR counter REVERSE IN lower_bound .. upper_bound
LOOP
Statements;
END LOOP;

Example:
 DECLARE
str VARCHAR2(200);
BEGIN
FOR i IN REVERSE 1..50
LOOP
str:=str||' '||i;
END LOOP;
DBMS_OUTPUT.PUT_LINE(str);
END;
 c. WHILE Loop
 The WHILE-LOOP statement executes the statements in the loop body as
long as condition is true.
 Syntax:
WHILE (conditional statement)
LOOP
Statements;
END LOOP;
Before each iteration of the LOOP, the condition is evaluated.
If it is TRUE , statements are executed , then control resumes at the top of
the
loop.
If it is FALSE , the loop is skipped and control passes to the next statement.

 Example:
DECLARE
num1 NUMBER(4):=&num1;
num2 NUMBER(4):=1;
BEGIN
WHILE (num2<=num1)
LOOP
DBMS_OUTPUT.PUT_LINE(num2);
num2:=num2+1;
END LOOP;
END;

Conditional control structures

Conditional control structures allows to control the flow of the execution of the
program based on a condition. In programming terms, it means that the statements
in the program are not executed sequentially, rather, one group of statements, or
another will be executed, depending on how the condition is evaluated.

Pl/Sql supports following conditional constructs:

 IF-THEN
 IF-THEN –ELSE
 IF-THEN-ELIF
 CASE

IF - THEN:

Syntax:

IF (condition) THAN

statements;
END IF;

Example:

DECLARE

a number(2) := 0;

BEGIN

a:= 10; -- check the boolean condition using if statement

IF( a < 20 ) THEN

-- if condition is true then print the following

dbms_output.put_line('a is less than 20 ' );

END IF;

dbms_output.put_line('value of a is : ' || a);

END;

IF - THEN - ELSE:

Syntax:

IF (condition) THAN

statements;

ELSE

Statements;

END IF;

Example:
DECLARE

a number(3) := 0;

BEGIN

a:=&a;

-- check the boolean condition using if statement

IF( a < 20 ) THEN

-- if condition is true then print the following

dbms_output.put_line('a is less than 20 ' );

ELSE

dbms_output.put_line('a is not less than 20 ' );

END IF;

dbms_output.put_line('value of a is : ' || a);

END;

IF-THEN- ELIF:

Syntax:

IF (condition) THAN

statements;

ELSIF (condition) THEN

Statements;

ELSE
Statements;

END IF;

Example:

DECLARE

a number(3) := 0;

BEGIN

a:=&a;

IF ( a = 10 ) THEN

dbms_output.put_line('Value of a is 10' );

ELSIF ( a = 20 ) THEN

dbms_output.put_line('Value of a is 20' );

ELSIF ( a = 30 ) THEN

dbms_output.put_line('Value of a is 30' );

ELSE

dbms_output.put_line('None of the values is matching');

END IF;

dbms_output.put_line('Exact value of a is: '|| a );

END;

CASE statement:
The CASE statement selects one sequence of statement to execute similar to IF.
The expression is evaluated once and its value is matched with several blocks
whichever block matches first , that is evaluated.
Syntax:

CASE selector
WHEN expression1 THEN

Statement 1;
WHEN expression2 THEN
Statement 2;
ELSE

Statement n;

END CASE;

The reserved word CASE marks the beginning of the CASE statement.
The 'selector' is a value that determines , which WHEN clause should be executed.
It is evaluated only once for the whole selection process.
Each WHEN clause contains an expression and one or more executable statements
associated with it.

The ELSE clause is an optional statement.

Example:

DECLARE
grade varchar2(1):='A';
BEGIN
grade:=&grade;
CASE grade
WHEN 'A' THEN

dbms_output.put_line('Excellent');
WHEN 'B' THEN

dbms_output.put_line('Very Good');
WHEN 'C' THEN

dbms_output.put_line('Good');
WHEN 'D' THEN
dbms_output.put_line('Fair');
WHEN 'F' THEN

dbms_output.put_line('Poor');
ELSE

dbms_output.put_line('No such grade');


END CASE;
END;
/

GOTO statement:

GOTO provides the ability to jump through a program from one place to another. It
is better to have a limited usage of GOTO in program code. When a jump is
proposed using GOTO , it is associated with an appropriate
label.

The GOTO statement branches to a label unconditionally.

The label must be unique within its scope and must precede an executable
statement.

When executed, the GOTO statement transfers the control to the labelled
statements or block.

The labelled statement or block can be down or up in the sequence of statements.

The labels are enclosed between angular brackets << and >>

Syntax:

GOTO label_name;

Example:
DECLARE
num NUMBER(2) := 1;
BEGIN

LOOP
num := num+1;
IF num > 5 THEN
GOTO 1_ENDOFLOOP; -- print num 5 times
END IF;
DBMS_OUTPUT.PUT_LINE('value = ' || );
END LOOP;

END;

PL/SQL enforces some restrictions while using GOTO.

It is illegal to use GOTO to branch into:

 an inner block
 a loop
 an IF statement
 an exception
 Practice Assignments on Looping Structures

1. Write a PL/SQL block to print the even numbers from 1 to a given
number using while loop.

2. Write an Anonymous Block to accept two different number and find
addition, subtraction, multiplication and division of given two numbers
using CASE.

3. Write a PL/SQL block to print the multiplication table up to 10 multiples
for a given number in the below format:
5*1=5
5 * 2 = 10
5 * 3 = 15
…...
5 * 10 = 50

4. Write a PL/SQL block to check whether the given number is a palindrome
or not.

5. Write a PL/SQL to find the sum of first hundred odd numbers.

6. Write an anonymous block to print the following series using for loop.
1
12
123
1234
12345

7. Write an anonymous block to print the following series using for loop. 5 5
555
4444
333
12
1
 8. Write a PL/SQL to print the number of times a specified character is
appearing in a given string.
 Note: Use the below tables to perform the queries for below two
assignments.
FACULTY – fid , name , qualification
BATCH – bid , start_date , end_date , fid , cid , timing
COURSE – cid , cname , duration , fee
STUDENT – sid , sname , gender , doj , bid , cid
 9. Write a PL/SQL block to display the student details for a specified student
id.
 10.Write a PL/SQL block to print the batch id , start date , end date and
number of days the batch batch will be staying.

Introduction to Cursors

For processing an SQL statement, oracle needs to allocate memory called context
area. A cursor is a pointer to this context area. PL/SQL controls the context area
through a cursor.

Cursor contains information on a select statement and the rows accessed by it. This
temporary work area is used to store the data retrieved from the database and
manipulate this data.

The set of rows the cursor holds is referred to as the active set.

Types of Cursors:

There are two types of cursors.

a) Implicit Cursors
 Oracle automatically creates an implicit cursor for all DML (INSERT,
UPDATE and DELETE) and Select statements
 Programmers cannot control the implicit cursors and the information in it.
 For INSERT operations, the cursor holds the data that to be inserted.
 For UPDATE and DELETE operations, the cursor identify the rows that are
affected.

PL/SQL implicit cursor is SQL.

Attributes of the SQL cursor are:

%FOUND: 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.

%ISOPEN: 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.

%NOTFOUND: Returns FALSE for implicit cursors, because Oracle closes the
SQL cursor automatically after executing its associated SQL statement. It returns
TRUE for explicit cursor if the cursor is open, otherwise returns FALSE.

%ROWCOUNT: Returns the number of rows affected by an INSERT, UPDATE,


or DELETE statement, or returned by a SELECT INTO statement.

Example: To update the salary of all employees in the Employee table and print
the count of rows updated or if the table is empty print ‘no employees selected’.

Employee table has the following structure.

Employee(eno number(3),ename varchar2(20),salary number(6));

DECLARE

total_rows number(2);

BEGIN

UPDATE employee SET salary = salary + 500;

IF sql%notfound THEN
dbms_output.put_line('no employee selected');

ELSIF sql%found THEN

total_rows := sql%rowcount ;

dbms_output.put_line( total_rows || ' employees selected ');

END IF;

END;

/NT

b) Explicit Cursors:

 Cursors declared by the programmer for Queries that return more than one
row.
 Declared and managed by the programmer and manipulated through specific
statements in the blocks.

 Defined in the declaration section of the PL/SQL Block.

 Used in PL/SQL where we have a Select statement that returns multiple


rows called the Active Set.

 The size of the active set meets the search criteria in the select statement.

All the cursor attributes available for implicit cursors will work on explicit cursors
in the same manner.

Following are the steps to be followed to use an explicit cursor.

Step 1. Declare a Cursor

In the declarative section of PL/SQL block, declare the cursor by naming it and
defining the structure of Query to be associated with it.

Syntax:

CURSOR IS SELECT statement;


Example:

CURSOR cur_emp IS SELECT emp_ID,emp_name,emp_salary from employees;

Step 2. Open the Cursor

Open statement allocates the memory for the cursor and makes it ready for fetching
the rows returned by the SQL statement into it.

Syntax :

OPEN cursor_name ;

Example: To open declared in the previous step.

OPEN cur_emp;

Step 3. Fetch data from the Cursor

The Fetch statement retrieves the rows from the cursor one at a time.

Advances the pointer to the next row in the active set.

Syntax:

FETCH INTO list of variables ;

Include the same number of variables in the variable list as the number of columns
selected in cursor definition.

Example: To fetch the Rows from the cursor cur_emp opened in the previous
statement.

FETCH cur_emp INTO v_id,v_name,v_salary;

V_id,v_name,v_salary are declared in DECLARATION section.

Step 4. Close the Cursor


Close statement disables the cursor, releases the context area and undefined the
active set.

Syntax :

CLOSE cursore_Name;

Example: To close the cursor used in previous steps.

CLOSE cur_emp;

Following are examples to illustrate the concepts of explicit cursors

Example1: To declare cursor to select all records from employee table and print
the values . Employee table has following structure:

Employee(eno number(3),ename varchar2(20),salary number(6));

DECLARE

CURSOR c1 IS select * from employee;

c employee%rowtype;

BEGIN

OPEN c1;

Loop

FETCH c1 into c;

Exit when c1%notfound;

dbms_output.put_line('Employee Number: '||c.eno);

dbms_output.put_line('Employee Name: '||c.ename);

dbms_output.put_line('Employee Salary: ‘||c.salary);

End Loop;
CLOSE c1;

END;

Example2 : To print the employee number and name of those employee who gets
salary more than 20000.

DECLARE

CURSOR c1 IS select eno,ename from employee where salary>20000;

c employee%rowtype;

BEGIN

OPEN c1;

Loop

FETCH c1 into c;

Exit when c1%notfound;

dbms_output.put_line('Employee Number: '||c.eno);

dbms_output.put_line('Employee Name: '||c.ename);

dbms_output.put_line('Employee Salary: ‘||c.salary);

End Loop;

CLOSE c1;

END;

Parameterized Cursor
We can send any number of parameters to cursors. Supplying a value
to the query dynamically in the where condition is cursor Parameter.
Declaring a Parameterized Cursor:
CURSOR cursor_name(parameter_list) IS

Opening a Parameterized Cursor:


OPEN (Value/Variable/Expression);

Example:

DECLARE
CURSOR c1 (p_dept_id) IS select * from employee where deptno =
p_deptid;
c employee%rowtype;
v_dept_id number;
BEGIN
v_dept_id :=20;
OPEN c1(v_dept_id);
Loop
FETCH c1 into c;
Exit when c1%notfound;
dbms_output.put_line('Employee Number: '||c.eno);
dbms_output.put_line('Employee Name: '||c.ename);
End Loop;
CLOSE c1;
END;

Cursor FOR Loops

 The Cursor FOR Loop is a shortcut to process explicit cursors.


 Implicit Open,Fetch,Exit and Close Occurs.
 Record is implicitly declared.

Syntax:

For record_name IN cursor_name Loop


Statement 1;
Statement 2;
…..
End Loop;
Where ,
record_name - is the name of the index that the cursor FOR LOOP statement
declares implicitly as a %ROWTYPE record variable of the type of the cursor.
cursor_name – is a PL/SQL identifier for the previously declared cursor.

Example:

The product table has the following structure:

Product(product_name varchar2(20) primary key , unit_price number(5))

PL/SQL block to print the product name and the unit price of all products in the
table.

DECLARE
CURSOR cur_product IS
SELECT product_name, unit_price FROM products;
BEGIN
FOR product IN cur_product
LOOP
DBMS_OUTPUT.PUT_LINE( product.product_name || ': $'
|| product.unit_price );
END LOOP;
END;

Problem Statements on CURSORS

1. Employee table has the following fields: EmployeeId,EmployeeName and


Basic Salary.

Write a PL/SQL block to update the basic salary of each employee by 2000 The
code should print a message as “None of the salaries where updated” in case there
is no record in the table. Should print a message as below “Salaries for 1000
employees are updated' if there are 1000 rows in the table.
Use cursor attributes to print appropriate messages.

2. Considering the same Employee table of question 1, write a PL/SQL block to


print the following report.

Employee Id Basic Salary Total Salary.

Total salary needs to be calculated as Total salary = basic Salary + 50% of Basic
Salary .

Declare a cursor to fetch the data .

EXCEPTION HANDLING

Introduction

An error condition during an execution is called exception An exception can be


any of the following

 An error generated by the system


 An error caused by the user action
 A warning issued by the application to the user

PL/SQL traps and responds to errors using an architecture of exception handlers.


The exception handler mechanism allows to clearly separate error processing code
from executable statements
Using Exception Handling testing can be done on the code in order to avoid it from
exiting abruptly

When an exception occurs, a message which explains its cause is received PL/SQL
exception consists of three parts

 Type of exception
 Error Code
 Error Message

Types Of Exceptions

There are two types of exception

 System defined / Predefined exceptions - Named Exception, Unnamed


Exceptions
 User defined exceptions

Basic Exception Block:

BEGIN
Execution block statements.
EXCEPTION
WHEN exception_name THEN
statements to be executed
WHEN OTHERS THEN ---- optional
statements to be executed
END;

Example:

To print the id of the employee from employee table for the employee named
Deepak. If the employee with name Deepak not found the message "Employee not
found " should be displayed.

DECLARE

v_id Number(4);

BEGIN

SELECT emp_Id into v_Id from employee where emp_name='Deepak';

dbms_output.put_line('Employee id is '||v_Id);

EXCEPTION

WHEN no_data_found THEN

dbms_output.put_line('Employee not found ');

END;

System Defined Exceptions


System exceptions are automatically raised by Oracle, when a program violates a
RDBMS rule.
There are some system exceptions which are raised frequently, so they are
predefined and given a name in Oracle which are known as Named System
Exceptions.

For example: NO_DATA_FOUND and ZERO_DIVIDE are called Named


System exceptions.
Named system exceptions are:

 No need to declare explicitly.


 Raised implicitly when a predefined Oracle error occurs.
 caught by referencing the standard name within an exception-handling
routine

The functions SQLCODE and SQLERRM are useful in the OTHERS handler as
they return the Oracle error code and message text.

Examples:

Example:

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 Due To -->'||
SQLCODE||SQLERRM);
END;

Unnamed System Exceptions

Those system exception for which oracle does not provide a name is known as
unnamed system exception.
These exception do not occur frequently. These Exceptions have a code and an
associated message.

There are two ways to handle unnamed system exceptions:

 By using the WHEN OTHERS exception handler.


 By associating the exception code to a name and using it as a named
exception.

We can assign a name to unnamed system exceptions using a PRAGMA (compiler


directive) called EXCEPTION_INIT.
EXCEPTION_INIT will associate a predefined Oracle error number to a
programmer_defined exception name.
Steps to be followed to use unnamed system exceptions are

• They are raised implicitly.


• If they are not handled in WHEN OTHERS they must be handled explicitly.
• To handle the exception explicitly, they must be declared using Pragma.

EXCEPTION_INIT as given above and handled referencing the user-defined


exception name in the exception section.
The general syntax to declare unnamed system exception using
EXCEPTION_INIT is:
DECLARE
exception_name EXCEPTION;
PRAGMA
EXCEPTION_INIT (exception_name, Err_code);
BEGIN
Execution section
EXCEPTION

WHEN exception_name THEN


handle the exception
END;

Example:
Lets consider the product table and order_items table . Here product_id is a
primary key in product table and a foreign key in order_items table. If we try to
delete a product_id from the product table when it has child records in order_id
table an exception will be thrown with oracle code number -2292. We can provide
a name to this exception and handle it in the exception section as given below.

DECLARE
Child_rec_exception EXCEPTION;
PRAGMA
EXCEPTION_INIT (Child_rec_exception, -2292);
BEGIN
Delete FROM product where product_id= 104;
EXCEPTION
WHEN Child_rec_exception THEN

DBMS_OUTPUT.put_line('Child records are present for this product_id.');


END;
/

User-defined Exceptions

Apart from system exceptions we can explicitly define exceptions based on


business rules. These are known as user-defined exceptions.

Steps to be followed to use user-defined exceptions:


• They should be explicitly declared in the declaration section.
• They should be explicitly raised in the Execution Section.
• They should be handled by referencing the user-defined exception name in the
exception section.

Example:
Lets consider the product table and order_items tables.
Lets create a business rule that if the total no of units of any particular product sold
is more than 20, then it is a huge quantity and a special discount should be
provided.

DECLARE
huge_quantity EXCEPTION;
CURSOR product_quantity IS
SELECT p.product_name as name, sum(o.total_units) as units
FROM order_tems o, product p
WHERE o.product_id = p.product_id;
quantity order_tems.total_units%type;
up_limit CONSTANT order_tems.total_units%type := 20;
message VARCHAR2(50);
BEGIN
FOR product_rec in product_quantity

LOOP
quantity := product_rec.units;
IF quantity > up_limit THEN
message := 'The number of units of product ' || product_rec.name ||' is
more than 20. Special discounts should be provided.Rest of
the records are skipped. '
RAISE huge_quantity;
ELSIF quantity < up_limit THEN

v_message:= 'The number of unit is below the discount limit.';


END IF;
DBMS_OUTPUT.put_line (message);
END LOOP;
EXCEPTION
WHEN huge_quantity THEN
DBMS_OUTPUT.put_line (message);
END;
/
RAISE_APPLICATION_ERROR ( )

RAISE_APPLICATION_ERROR is a built-in procedure in oracle which is used to


display the user-defined error messages along with the error number whose range
is in between -20000 and -20999. Whenever a message is displayed using
RAISE_APPLICATION_ERROR, all
previous transactions which are not committed within the PL/SQL Block are rolled
back automatically (i.e. change due to INSERT, UPDATE, or DELETE
statements).
RAISE_APPLICATION_ERROR raises an exception but does not handle it.

RAISE_APPLICATION_ERROR is used for the following reasons.

 To create a unique id for an user-defined exception.


 To make the user-defined exception look like an Oracle error.

The General Syntax to use this procedure is:


RAISE_APPLICATION_ERROR (error_number, error_message);

Example:
DECLARE
huge_quantity EXCEPTION;
CURSOR product_quantity IS
SELECT p.product_name as name, sum(o.total_units) as units
FROM order_tems o, product p
WHERE o.product_id = p.product_id;

quantity order_tems.total_units%type;
up_limit CONSTANT order_tems.total_units%type := 20;
message VARCHAR2(50);
BEGIN
FOR product_rec in product_quantity LOOP
quantity := product_rec.units;
IF quantity > up_limit THEN
RAISE huge_quantity;
ELSIF quantity < up_limit THEN
v_message:= 'The number of unit is below the discount limit.';
END IF;
DBMS_OUTPUT.put_line (message);
END LOOP;
EXCEPTION
WHEN huge_quantity THEN
raise_application_error(-2100, 'The number of unit is above
the discount limit.');
END;

Sub Programs - Stored Procedure and Functions

Sub Program:

 A named PL/SQL block is called a sub program.

 We can invoke a sub program with a set of parameters.

 We can create a subprogram either at schema level or inside a package, or


inside a PL/SQL block

Schema Level Sub Program:

 A standalone stored subprogram.

 Created using CREATE statement.

 Are stored in the database until dropped.

 Are dropped using DROP statement.

Packaged subprogram:

 A packaged sub program is created inside a package .

 It is stored in the database until the package is dropped with


the DROP PACKAGE statement.

Nested subprogram:

These are sub programs defined inside another sub

 Created inside a PL/SQL block.


 We can either declare and define it defined at the same time, or can declare
it first and define it later in the same block.
 It is stored in the database only if it is nested within a standalone or
packaged subprogram.

Parts of Subprogram:

Name: Since a subprogram is a named block, must have a name.

Parameters: an optional parameter list.

Declarative Part:

 Optional part.
 Does not start with DECLARE keyword.
 Contains declarations of cursors , constants, variables, exceptions and nested
sub programs.

Executable Part

 Contains statements to assigns values to variables , control execution and


manipulate data.

Exception Handling Part

 Contains code that handles run time errors.

Types of sub Programs:

PL/SQL provides two types of sub programs:

 Procedure
 Function

Procedures

 Procedures are Named PL/SQL blocks designed for a specific task.


 Procedure allow programmers to encapsulate complex business logic and
reuse it in both database layer and application layer.
 Procedures can have parameters but does not return value.
Basic Syntax :

The basic syntax for writing a Procedure is:

CREATE OR REPLACE PROCEDURE procedure_name (parameter_name [


[ MODE] [data type] ]
IS | AS
[ local variable declaration ]
BEGIN
PL/SQL Executable statements
[ EXCEPTION
Exception handlers ]
END[ procedure_name ];

Procedure Header:

Section before IS keyword is called procedure header or procedure signature.

Components:

Procedure name : The name of the procedure.

Parameter list: The optional parameter list contains name, mode and types
of the parameters.

Parameter mode can be IN, OUT or IN OUNT.

 IN represents a read-only parameter. If the function tries to change the value


of the parameters with IM mode, the compiler will issue an error message.
This mode is used to pass a constant, literal, initialized variable, or
expression to the function as the.
 OUT represents a write-only parameter. Used to return values back to the
calling program.
 IN OUT is used to make a parameter read and write. Procedure can read the
value from this type of parameter can change the value and return it back to
the calling program.

Procedure Body:
Statements after the IS keyword is the procedure body. The procedure body has
similar syntax like an anonymous block and consists of the declaration, execution
and exception sections.

Example1:

To print the summation and average of three numbers.

CREATE or REPLACE PROCEDURE find_Total_Average (m1 NUMBER,m2


NUMBER,m3 NUMBER) AS

total1 number;

average1 number;

BEGIN

total1:=(m1+m2+m3);

average1:=(total1/3);

dbms_output.put_line('The total of three subject marks is '||total1) ;

dbms_output.put_line('The Avg of three subject marks is '||average1) ;

END;

How to call a Procedure:

We can call a procedure in two ways.

1. Using the EXECUTE keyword.

EXECUTE find_Total_Average(20,30,40);

2. From another Procedure / Function PL/SQL block

For example,
DECLARE

a number;

b number;

c number;

BEGIN

a:=&a;

b:=&b;

c:=&c;

find_Total_Average (a,b,c);

END;

Example 2: (Use of IN and OUT mode for parameters)

CREATE OR REPLACE PROCEDURE findMin(num1 IN number, num2 IN


number, result OUT number) IS

BEGIN

IF num1 < num2 THEN

result:= num1;

ELSE

result:= num2;

END IF;

END;

/
Anonymous block to call the procedure:

DECLARE

a NUMBER :=100;

b NUMBER :=200;

c NUMBER;

BEGIN

findMin(a, b, c);

dbms_output.put_line(' Minimum of (100, 200) : ' || c);

END;

Example 3: (Use of INOUT mode of parameter)

PROCEDURE findSquareNum(num IN OUT NUMBER) IS

BEGIN

num := num * num;

END;

Anonymous block to call the procedure:

DECLARE

V_num NUMBER :=20;

BEGIN

a:= 20;
squareNum(a);

dbms_output.put_line(' Square of (20): ' || a);

END;

Note:

Procedure and Function Differences

 Function returns a value based on some calculation or search result.


However, a procedure may, may not return a value, or may return more than
one values using the OUT parameter.
 Function can be called from SQL statements whereas procedure cannot be
called from SQL statements.
 You can have DML (insert, update, delete) statements in a function

Functions

 Functions are Sub program that always return a value.


 Use of a function is to compute and return a single value.
 The returned value may be a single scalar value (e.g a number, date or
character string) or a single collection (e.g a nested table or varray).
 We have to declare and define a function before use.
 Function can accept one , many or no parameters
 Function must have a RETURN value of the data type declared in the
header.
 Function-body contains the executable part written in the BEGIN block.
 Can implement Exception handling by using EXCEPTION block in
functions.

Basic Structure

The basic syntax for writing a function is


CREATE OR REPLACE FUNCTION function_name( [ [ MODE ] ]) RETURN
return_data type
IS | AS
[ local variable declaration ]
BEGIN
PL/SQL executable statements
RETURN value/variable
[ EXCEPTION
Exception handlers]
END [ function_name] ;

 CREATE OR REPLACE option is used to create a new function or modify


an existing function.
 function-name specifies the name of the function.
 The optional parameter list contains name, mode and types of the
parameters.
 The IS/AS keyword is used declare the body of the function .
 Function-body contains the executable part and at the end, it contains return
statement returning the value.
 RETURN clause specifies that data type of the value you are going to return
from the function
 EXCEPTION block is to handle exceptions occurred in the function-body
part.

Return Type:

 The header section defines the return type of the function.


 The return data type can be any of the oracle data type like VARCHAR,
NUMBER etc.
 The function-body and exception section both should return a value which
is of the data type defined in the return clause of the header section.

Example1: (standalone function)

To write a function to add a number given as argument to a number read as input


while executing the function.

CREATE or REPLACE FUNCTION find_sum(num_in number)


RETURN number
AS
num_read number;
sum number :=0;

BEGIN

num_read:=&num_read;
sum:=num_in +num_read;

RETURN sum;
END;

In the above example , name of the function is find_sum.

It has one parameter called name_in of type number and it returns a number.

Example2: (using a table in the function)

To write a function to find the first name of the employee for a given id from the
table

Employees(emp_id,first_name,last_name,designation);

CREATE OR REPLACE FUNCTION find_employee_name (e_id number)


RETURN VARCHAR IS
emp_name VARCHAR(20);

BEGIN

SELECT first_name INTO emp_name FROM employee WHERE empid =


e_id;

RETURN emp_name;

EXCEPTION

WHEN no_data_found THEN

RETURN ‘ No such Employee !’;

END;

In the above function “find_emplyee_name”,

 The argument e_id of type number is used to pass the id value of the
employee to be searched in the employee table.
 Variable emp_name is declared as VARCHAR(20) to hold the value to be
fetched from the table.
 Function returns the first_name value from the employee table if table has a
record with emp_id value equal to the e_id value given as argument.
 If no matching record found in the table, function raises no_data_found
exception and from the EXCEPTION block returns “No such Employee !”.

How to execute a Function:

We can execute a function in the following ways:

1) By invoking from an anonymous block:

Define an anonymous block with a variable declared to catch the return value in
the block.

DECLARE
employee_name varchr2(30);
v_dept_id number
BEGIN
v_dept_id := 20;
employee_name := find_employee_name(v_dept_id);
dbms_output.put_line('employee name is -->'||employee_name);

END;

2) As a part of a SELECT statement:

SELECT find_employee_name (103) FROM dual;

3) In PL/SQL Statements:

dbms_output.put_line(find_employee_name(20));

This line displays the value returned by the function.


Introduction to Trigger

 A trigger is a named program unit stored in database and fired (executed) in


response to a specified event like Insert, Delete, Update on a database table.
 A triggers specified event is associated with either a Table / View / Schema /
Database

 There are two types of triggers

Record based triggers- DML / DDL statements

System based triggers- Database operations

 A trigger is stored as text and compiled at execution time.


 A trigger contains SQL and PL/SQL statements which are executed as a unit
and can call other procedures and triggers.

Importance of Triggers

Triggers can be used to :

 Automatically generate derived column values.


 Prevent invalid transactions.
 Enforce complex business rules.
 Provide transparent event logging.
 Provide auditing.
 Gather statistics on table access.
 Modify table data when DML statements are issued against views.
 Publishes information about database events, user events, and SQL
statements to subscribing applications.

Trigger Restrictions

 A trigger may not issue a TCL statement.


 Any function or procedure called by a trigger cannot issue a TCL statement.
 It is not permitted to declare a LONG or LONG RAW variables in the body
of a trigger.
Types of Triggers
Triggers are basically divided into following types.

 Row level triggers & Statement level triggers


 Before triggers & After triggers

The above two levels can be used as a combination of following

A) BEFORE row level

B) BEFORE statement level

C) AFTER row level

D) AFTER statement level

 Instead of triggers
 Triggers on system events and user events.

Row level trigger :

Row level trigger fires for each and every record which are performing INSERT,
UPDATE and DELETE from the database table.

Row level trigger is

 Fired each time the table is affected by the triggering statement.


 If an UPDATE statement updates multiple rows of a table , a row trigger
fires once for each row affected by the UPDATE statement
 If a triggering statement affects no rows , a row trigger will not run.
 Useful if the code in the trigger action depends on the data provided by the
trigger statements or rows that are affected.

Statement level trigger :

Statement trigger fires only once for a DML statement.

Statement level trigger is

 Fired once on behalf of the triggering statement regardless of number of


rows affected by the triggering statement.
 Useful to make a complex check on the current time on user or generate
single audit record.

BEFORE trigger :

BEFORE trigger executes before the triggering DML statement (INSERT,


UPDATE, DELETE) is executed.

BEFORE trigger can be used only on tables not on views .

Triggering SQL statements may or may not execute, depending on the BEFORE
trigger conditions block.

Commonly used when

 The triggering action determines whether the triggering statement should be


allowed to complete.
 We can eliminate unnecessary processing of the triggering statement and its
eventual rollback in cases where an exception is raised in the trigger action.
 To derive specific values before completing a triggering INSERT /
UPDATE statement.

AFTER trigger :

AFTER trigger execute after the triggering DML statement (INSERT, UPDATE,
DELETE) is executed.

Syntax to Create Trigger :

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 a new


trigger or if a trigger by that name already exists replaces it.
 {BEFORE | AFTER | INSTEAD OF} :- This specifies when the trigger
would 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 would 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 to refer to
the new and old values for various DML statements, like INSERT,
UPDATE, and DELETE. Not available for row_level triggers.
 [FOR EACH ROW] :- This specifies a row level trigger, i.e., the trigger
would be executed for each row being affected. Otherwise the trigger
will be executed 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 be fired. This clause is valid only for row level triggers.

Dropping trigger:
Triggers created can be removed by using Drop command.

Syntax:

DROP TRIGGER trigger_name;

Example 1:

Let us consider the following Employee table:

ID Name Age Address Salary

1 Shital 32 Jaipur 20000.00


2 Ramesh 25 Mumbai 15000.00
3 Bedanta 24 Delhi 20000.00

4 Chaitali 25 Guwahati 30000.00


5 Komal 24 Delhi 20000.00

6 Radhika 22 Kochi 15000.00

To create a row-level trigger for the Employee table that would fire for INSERT or
UPDATE or DELETE operations performed on the table and display the salary
difference between the old salary value and the new salary value .

CREATE OR REPLACE TRIGGER display_salary_changes

BEFORE DELETE OR INSERT OR UPDATE ON Employees

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.

Now if we perform any DELETE, INSERT, or UPDATE operation on the table,


trigger will be fired.

For example, if the following DML statement is executed ,

INSERT INTO Employee (ID,NAME,AGE,ADDRESS,SALARY) VALUES


(7,’Roshan’,24,’UP’,12000.000);

The trigger created above, display_salary_changes will be fired and it will display
the following result –

Old salary :

New salary: 12000.00

Salary difference:

Since this is a new record , the old salary is not available and the result comes as
null.

Now , if the following statement is executed,

UPDATE Employee set salary=salary+2000 where id = 4;


Trigger , display_salary_changes will be fired and it will display the following
result –

Old salary : 30000.00

New salary: 32000.00

Salary difference:2000.00

To drop the trigger display_salary_changes following command is to be used.

DROP TRIGGER display_salary_changes ;

Practice Assignments on Functions

1. Write a simple function to accept two numbers and return the summation of
the numbers . Create an anonymous block and call the function .
2. Write a function to find a factorial of a given number.
3. Write a function to return the day of week( like monday or tueseday ) for
given date.
4. Write a function to check whether the given number is a prime number or
not.
5. Write a function to accept a string and a character and return the number of
times the given character exists in given string.
6. Write a function to reverse a given string.
7. Write a stored function to accept a number from user and display its cube
value (i.e., num^3).

Consider the following table to answer the following assignments .

Employee ( eid , name , qualification,departmentid,basic_salary)

8.Write a function to return the number of employees in the department whose


id is given as argument.
9.Write a function to return the total salary of an employee on the basis of the
data present in the employee table. The employee id will be passed as an argument
for the employee whose salary is to be calculated.

Total salary of employee is calculated as basic_salary+50% of basic as


HRA+20% of basic as DA + Rs 1500 as medical allowance.

Handle exception if required.

10. Write a function to find the number of employees who gets basic pay more
than a given amount. The amount to be compared will be passed as argument to
the stored function.

Handle exception if required.

You might also like