0% found this document useful (0 votes)
2 views

Oracle PLSQL

The document provides a comprehensive guide on Oracle PL/SQL programming, covering essential topics such as block structure, data types, operators, variables, conditional statements, loops, and SQL integration. It includes practical examples and syntax for writing PL/SQL programs, demonstrating how to implement business logic within database applications. Additionally, it discusses advanced concepts like cursors, exceptions, procedures, functions, packages, and triggers.

Uploaded by

sudip kumar
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views

Oracle PLSQL

The document provides a comprehensive guide on Oracle PL/SQL programming, covering essential topics such as block structure, data types, operators, variables, conditional statements, loops, and SQL integration. It includes practical examples and syntax for writing PL/SQL programs, demonstrating how to implement business logic within database applications. Additionally, it discusses advanced concepts like cursors, exceptions, procedures, functions, packages, and triggers.

Uploaded by

sudip kumar
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 42

ORACLE PL/SQL PROGRAMMING

Table of Contents
1. Revision History ............................................................................................. 3
2. PL/SQL Engine ............................................................................................... 3
3. Block Structure: ............................................................................................. 4
4. Important PL/SQL Data types: ...................................................................... 5
5. Operators: ....................................................................................................... 5
6. Variables: ........................................................................................................ 5
7. Conditional Statements: ................................................................................ 6
8. Loops: ............................................................................................................. 9
1.1. Simple Loops .............................................................................................................................. 9
1.2. While Loops .............................................................................................................................. 10
1.3. For Loops .................................................................................................................................. 11

9. Using SQL statements in PL/SQL: .............................................................. 11


10. Cursors: ........................................................................................................ 13
1.4. Implicit Cursors: ........................................................................................................................ 14
1.5. Explicit Cursors: ........................................................................................................................ 15
1.6. OPEN-FOR statements [OR] REF CURSORS: ....................................................................... 17

2. Collections or composite data types:......................................................... 18


2.1. Associate arrays: ...................................................................................................................... 18
2.2. Varrays: ..................................................................................................................................... 20
2.3. Nested tables: ........................................................................................................................... 21

1. Exceptions: ................................................................................................... 22
1.1. Predefined exceptions: ............................................................................................................. 22
1.2. User defined exceptions: .......................................................................................................... 25
1.3. Pragma Exception: .................................................................................................................... 26
1.4. Raise Application Errors: .......................................................................................................... 26

2. Procedures: .................................................................................................. 27
2.1. Creating a procedure. ............................................................................................................... 27
2.2. Calling a procedure: .................................................................................................................. 28
2.3. Getting information on procedures: .......................................................................................... 29
2.4. Dropping a procedure: .............................................................................................................. 29
2.5. Viewing Errors of a Procedure: ................................................................................................. 29

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 1
3. Functions: ..................................................................................................... 31
3.1. Creating a Function ................................................................................................................... 31
3.2. Calling a function ...................................................................................................................... 33
3.3. Getting information on Functions. ............................................................................................. 33
3.4. Dropping Functions. .................................................................................................................. 34

4. Packages: ..................................................................................................... 34
4.1. Creating a Package Specification ............................................................................................. 34
4.2. Creating a Package Body ......................................................................................................... 35
4.3. Calling functions and procedures in a Package. ...................................................................... 36
4.4. Getting information on functions and procedures in a package: .............................................. 37
4.5. Dropping a Package: ................................................................................................................ 37

5. Triggers:........................................................................................................ 37
5.1. When a trigger fires:.................................................................................................................. 38
5.2. Set Up for the Example Trigger ................................................................................................ 38
5.3. Creating a trigger ...................................................................................................................... 38
5.4. Getting information on triggers: ................................................................................................ 41
5.5. Disabling and Enabling a Trigger .............................................................................................. 41
5.6. Dropping a trigger ..................................................................................................................... 42

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 2
PL/SQL is used to add business logic to database application. This centralized logic can be run by any
program that can access database including SQL*plus, Java programs and C# programs etc.

3. Block Structure:
PL/SQL programs are divided up into structures known as blocks, with each block containing
PL/SQL and SQL statements. A PL/SQL block has the following structure:

[DECLARE
declaration_statements
]
BEGIN
executable_statements
[EXCEPTION
exception_handling_statements
]
END;
/

Where
Declaration_statements,declare the variables used in the rest of the PL/SQL block.DECLARE
blocks are optional.
executable_statements are the actual executable statements, which may includeloops,
conditional logic, and so on.
exception_handling_statements are statements that handle any execution errorsthat
mightoccur when the block is run. EXCEPTION blocks are optional.

Below is simple PL/SQL program includes only BEGIN block

SET SERVEROUTPUT ON
BEGIN
DBMS_OUTPUT.PUT_LINE('Welcome to PL/SQL Programming');
END;
/

Output displayed will be:

Welcome to PL/SQL Programming.

Every statement is terminated by a semicolon (;), and a PL/SQL block is terminated using
theforward slash (/) character.

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 4
4. Important PL/SQL Data types:

NUMBER - To store numeric values, its behavior is similar to SQL data type.
VARCHAR2 - To store character or string variables.
DATE - To store Date variables.
BOOLEAN - Boolean value, TRUE, FALSE or NULL is assigned
PLS_INTEGER - Using this data type for counter variables is a good practice and it is quick in
arithmetic calculations.

5. Operators:

Below are few important operators used in PL/SQL,

= - This operator is used for comparison of two values.


:= - This operator is used for assignment
/ - This operator is used to divide left operand by right operand and gives result.
+ - Addition operator.
- - Subtraction operator.
* - Multiplication operator.
& - This operator is used to accept input values.
: - Used to defined host or bind variables.
; - Statement terminator. Each statement in PL/SQL should be terminated by ';'
|| - Concatenation operator. Used to concatenate operands and gives result.

6. Variables:

Below are types of variables used in PL/SQL,

Scalar - These variables are used to hold a single value.


Composite - These variables are used to hold multiple values.
Reference or Anchor - These variables are usually referenced from SQL tables.
LOB (Large Objects) - These variables are used to store images and binary data.

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 5
 Write a simple PL/SQL program to calculate sum of two numeric values.

SET SERVEROUTPUT ON
DECLARE
Lc_first_num NUMBER(3) := 10;
Lc_second_num NUMBER(3) := 20;
Lc_sum NUMBER(4) ;
BEGIN
Lc_sum := Lc_first_num + Lc_second_num;
DBMS_OUTPUT.PUT_LINE('Sum of two numbers: '|| Lc_sum);
END;
/

Output displayed will be:

Sum of two numbers: 30

 Write a simple PL/SQL program to accept two numeric values and calculate sum.

SET SERVEROUTPUT ON
DECLARE
Lv_first_num NUMBER(3) := &Lv_first_num;
Lv_second_num NUMBER(3) := &Lv_second_num;
Lv_sum NUMBER(4) ;
BEGIN
Lv_sum := Lv_first_num + Lv_second_num;
DBMS_OUTPUT.PUT_LINE('Sum of two numbers: '|| Lv_sum);
END;
/

7. Conditional Statements:

IF, THEN, ELSE, ELSIF, and END IF keywords are used to perform conditional logic and below is a
sample conditional block.

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 6
IF condition1
THEN
statements1;
ELSIF condition2
THEN
statements2;
ELSE
statements3;
END IF;

Where,
Condition1 and condition2 are Boolean expressions that evaluate to true or false.statements1,
statements2, and statements3 are PL/SQL statements.

The conditional logic flows as follows:


 If condition1 is true, then statements1 are executed.
 If condition1 is false but condition2 is true, then statements2 are executed.
 If neither condition1 nor condition2 is true, then statements3 are executed.

IF statement can be embedded within another IF statement, as shown in the following,

IF condition1
THEN
statements1;
IF Condition4
THEN
Statment4;
END IF;
ELSIF condition2
THEN
IF Condition5
THEN
Statement5;
END IF;
statements2;
ELSE
statements3;
END IF;

 Write a PL/SQL program to find biggest number among input numbers.

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 7
SET SERVEROUTPUT ON
DECLARE
Lv_first_num NUMBER(3) := &Lv_first_num;
Lv_second_num NUMBER(3) := &Lv_second_num;
Lv_third_num NUMBER(3) :=&Lv_third_num;

BEGIN
IF Lv_first_num>Lv_second_num
THEN
IF Lv_first_num>Lv_third_num
C THEN
A DBMS_OUTPUT.PUT_LINE('Lv_first_num: '||Lv_first_num||' is biggest');
S END IF;
E ELSIF Lv_second_num>Lv_third_num
THEN
s DBMS_OUTPUT.PUT_LINE('Lv_second_num: '||Lv_second_num||' is biggest');
t ELSE
a DBMS_OUTPUT.PUT_LINE('Lv_third_num: '||Lv_third_num||' is biggest');
t END IF;
e END;
m /
e
nt:
CASE statement is also used as conditional statement. Below is the syntax to use CASE
statement.

 Write a PL/SQL program to find biggest number among 3 input numbers using CASE
statement.

SET SERVEROUTPUT ON
DECLARE
Lv_first_num NUMBER(3) := &Lv_first_num;
Lv_second_num NUMBER(3) := &Lv_second_num;
Lv_third_num NUMBER(3) :=&Lv_third_num;
CASE WHEN <Condition1> THEN ----------;
BEGIN WHEN <Condition2> THEN ---------;
CASE WHEN (Lv_first_num > Lv_second_num
WHEN <Condition3> AND THEN
Lv_first_num
---------; > Lv_third_num)
THEN dbms_output.put_line ('First number is biggest');
ELSE ----------------------------------------------;
WHEN Lv_second_num >
END CASE; Lv_third_num
THEN dbms_output.put_line('Second number is biggest');
ELSE dbms_output.put_line('Third number is biggest');
END CASE;
END;
/

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 8
8. Loops:
Loops are used to execute a statement or set of statements zero or more times. Below are different
types of loops available in PL/SQL,

1.1. Simple Loops

A simple loop runs until an explicit instruction is given to end the loop. The syntax for a simple
loop is as follows:

LOOP
Statements;
END LOOP;

To exit from the loop, either EXIT or EXIT WHEN statements are used. EXIT statement ends a
loop immediately whereas EXIT WHEN exists loop when specified condition occurs.

 Write a PL/SQL program to demonstrate simple loops.

SET SERVEROUTPUT ON
DECLARE
Lv_counter PLS_INTEGER := 1;
BEGIN
LOOP
Lv_counter := Lv_counter + 1;
DBMS_OUTPUT.PUT_LINE('Lv_counter value is: '|| Lv_counter);
EXIT;
END LOOP;
END;
/

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 9
DECLARE
Lv_counter PLS_INTEGER := 1;
BEGIN
LOOP
Lv_counter := Lv_counter + 1;
DBMS_OUTPUT.PUT_LINE('Lv_counter value is: '|| Lv_counter);
EXIT WHEN Lv_counter = 5;
END LOOP;
END;
/

1.2. While Loops

A WHILE loop runs until a specified condition occurs. The syntax for a WHILE loop is as follows,

WHILE <Condition>
LOOP
Statements;
END LOOP;

 Write a PL/SQL program to demonstrate WHILE loops.

SET SERVEROUTPUT ON
DECLARE
Lv_counter PLS_INTEGER := 1;
BEGIN
WHILE Lv_counter<=5
LOOP
DBMS_OUTPUT.PUT_LINE('Lv_counter value is: '|| Lv_counter);
Lv_counter := Lv_counter + 1;
END LOOP;
END;

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 10
/

Here in WHILE, no EXIT statement is used to come out of the loop. If Condition mentioned in
WHILE loop is failed then LOOP is automatically closed.

1.3. For Loops

A FOR loop is executed in predefined number of times . Loop runs based on lower and upper
bounds defined for a loop variable. The loop variable is then incremented or decremented each
time around the loop. Below is the syntax for FOR loops.

FOR <loop_variable> in [REVERSE] <lower_bound>..<upper_bound>


LOOP
Statements;
END LOOP;

 Write a PL/SQL program to demonstrate FOR loops.

SET SERVEROUTPUT ON
BEGIN
FOR idx IN 1..10
LOOP
DBMS_OUTPUT.PUT_LINE('Loop variable is: '||idx);
END LOOP;
END;
/
SET SERVEROUTPUT ON
BEGIN
FOR idx IN REVERSE 1..10
LOOP
DBMS_OUTPUT.PUT_LINE('Loop variable is: '||idx);
END LOOP;
END;
/
9. U
PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore
Contact No: 9739096158, 9739771750
www.pskinfo.com Page 11
sing SQL statements in PL/SQL:
A SQL statement can be used in a PL/SQL block to retrieve data of a table into local PL/SQL
variables and apply some business logic on those variables based on need.

 Write a PL/SQL program to retrieve salary and commission of employee and calculate total
salary.

SET SERVEROUTPUT ON
DECLARE
Lv_salary NUMBER(10);
Lv_comm NUMBER(4);
Lv_tot_sal NUMBER(10);
BEGIN
SELECT salary, commission_pct
INTO Lv_salary, Lv_comm
FROM Employees
WHERE employee_id = &employee_id;

Lv_tot_sal := Lv_salary + (NVL(Lv_comm,0)*Lv_salary);


DBMS_OUTPUT.PUT_LINE('Employee total salary is: '||Lv_tot_sal);
END;
/

 Write a PL/SQL program to retrieve salary and commission of employee and calculate total
salary using anchor data types.

SET SERVEROUTPUT ON
DECLARE
Lv_salary Employees.salary%TYPE;
Lv_comm Employees.commission_pct%TYPE;
Lv_tot_sal Employees.salary%TYPE;
BEGIN
SELECT salary, commission_pct
INTO Lv_salary, Lv_comm
FROM Employees
WHERE employee_id = &employee_id;

Lv_tot_sal := Lv_salary + (NVL(Lv_comm,0)*Lv_salary);


DBMS_OUTPUT.PUT_LINE('Employee total salary is: '||Lv_tot_sal);

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 12
END;
/

 Write a PL/SQL program to retrieve salary and commission of employee and calculate total
salary using record data types.

SET SERVEROUTPUT ON
DECLARE
Lv_emp_rec Employees%ROWTYPE;
Lv_tot_sal Employees.salary%TYPE;
BEGIN
SELECT salary, commission_pct
INTO Lv_emp_rec.salary, Lv_emp_rec.commission_pct
FROM Employees
WHERE employee_id = &employee_id;

Lv_tot_sal := Lv_emp_rec.salary+ (NVL(Lv_emp_rec.commission_pct,0)*Lv_emp_rec.salary);


DBMS_OUTPUT.PUT_LINE('Employee total salary is: '||Lv_tot_sal);
END;
/

10. Cursors:
Basically there are 3 types of cursors,

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 13
 Implicit cursors.
 Explicit cursors.
 Ref cursors.

1.4. Implicit Cursors:

Implicit cursors are automatically opened, processed and closed by oracle and user does
not need to explicitly perform these operations while using implicit cursors. Implicit
cursors are associated with the latest SQL used in PL/SQL program.

In general implicit cursors are not used in business as they are bit difficult to manage.Below
are different cursor attributes using for different purposes.

 %ISOPEN - Returns TRUE when cursor is opened.


 %FOUND - Returns TRUE when cursor finds record to process
 %NOTFOUND - Returns TRUE when cursor does not find record to
process.
 %ROWCOUNT - Returns the count of records processed by a cursor

 Write a PL/SQL program to demonstrate implicit cursors.


SET SERVEROUTPUT ON
DECLARE
Lv_emp_name Employees.first_name%TYPE;
BEGIN
SELECT first_name INTO Lv_emp_name
FROM emp_bkp WHERE employee_id = 101;

IF SQL%ISOPEN
THEN
DBMS_OUTPUT.PUT_LINE('Implicit cursor automatically opened');
DBMS_OUTPUT.PUT_LINE('Total number of cursor records: '||SQL%ROWCOUNT);
END IF;
DELETE FROM emp_bkp;
IF SQL%FOUND
THEN
DBMS_OUTPUT.PUT_LINE('Implicit cursor now opened to DELETE statement');
DBMS_OUTPUT.PUT_LINE('Total number of cursor records: '|| SQL%ROWCOUNT);
END IF;
ROLLBACK;
UPDATE emp_bkp set salary = salary+(salary*10/100) where department_id = 90;
IF SQL%FOUND
THEN
DBMS_OUTPUT.PUT_LINE('Implicit cursor now opened to UPDATE statement');
DBMS_OUTPUT.PUT_LINE('Total number of cursor records: '|| SQL%ROWCOUNT);
END IF;
ROLLBACK;
END;
/

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 14
1.5. Explicit Cursors:

Using Cursors multiple rows of a table can be fetched into PL/SQL variables and used to
apply business logic. Cursor fetches one row at a time and processes the data. Cursor
follows below sequence of steps,

 Declare variables to store the column values for a row.


 Declare the cursor, which contains a query.
 Open the cursor.
 Fetch the rows from the cursor one at a time and store the column values in the
variables declared in Step 1. You would then do something with those variables,
such as display them on the screen, use them in a calculation, and so on.
 Close the cursor.

Cursors can be operated in SIMPLE LOOPS, WHILE LOOPS and FOR LOOPS.

 Write a PL/SQL program to retrieve employee name, salary and commission of employees in a
department and calculate total salary using cursors with SIMPLE loops.

SET SERVEROUTPUT ON
DECLARE
Lv_emp_name Employees.first_name%TYPE;
Lv_salary Employees.salary%TYPE;
Lv_comm Employees.commission_pct%TYPE;
Lv_tot_sal Employees.salary%TYPE;

--Declaration of cursor
CURSOR cur_emp IS
SELECT first_name, salary, commission_pct
FROM Employees
WHERE department_id = &department_id;
BEGIN
OPEN cur_emp; --Opening cursor before fetching data.
LOOP
FETCH cur_emp INTO Lv_emp_name, Lv_salary, Lv_comm;
EXIT WHEN cur_emp%NOTFOUND;
Lv_tot_sal := Lv_salary + NVL(Lv_comm, 0)*Lv_salary;
DBMS_OUTPUT.PUT_LINE('Emp Name: '||Lv_emp_name||' and Total Salary: '||Lv_tot_sal);
END LOOP;
CLOSE cur_emp;
END;
/

 Write a PL/SQL program to retrieve employee name, salary and commission of employees in a
department and calculate total salary using cursors with WHILE loop.

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 15
SET SERVEROUTPUT ON
DECLARE
Lv_emp_name Employees.first_name%TYPE;
Lv_salary Employees.salary%TYPE;
Lv_comm Employees.commission_pct%TYPE;
Lv_tot_sal Employees.salary%TYPE;
Lv_tot_emps PLS_INTEGER;
CURSOR cur_emp IS
SELECT first_name, salary, commission_pct
FROM Employees
WHERE department_id = &department_id;
BEGIN
IF cur_emp%ISOPEN = FALSE
THEN
OPEN cur_emp;
END IF;
FETCH cur_emp INTO Lv_emp_Name, Lv_salary, Lv_comm;
WHILE cur_emp%FOUND
LOOP
--EXIT WHEN cur_emp%NOTFOUND;
IF cur_emp%FOUND = TRUE
THEN
Lv_tot_sal := Lv_salary + NVL(Lv_comm, 0)*Lv_salary;
DBMS_OUTPUT.PUT_LINE('Emp Name: '||Lv_emp_name||' and Total Salary: '||Lv_tot_sal);
END IF;
FETCH cur_emp INTO Lv_emp_name, Lv_salary, Lv_comm;
END LOOP;
Lv_tot_emps := cur_emp%ROWCOUNT;
DBMS_OUTPUT.PUT_LINE('Total number of employees: '||Lv_tot_emps);
IF cur_emp%ISOPEN = TRUE
THEN
CLOSE cur_emp;
END IF;
END;
/

 Write a PL/SQL program to retrieve employee name, salary and commission of employees in a
department and calculate total salary using cursors with FOR loop.

SET SERVEROUTPUT ON
DECLARE
Lv_tot_sal Employees.salary%TYPE;
BEGIN
FOR emp_rec IN (SELECT first_name, salary, commission_pct
FROM employees WHERE department_id = &department_id)
LOOP
Lv_tot_sal := emp_rec.salary+ NVL(emp_rec.commission_pct, 0)*emp_rec.salary;
DBMS_OUTPUT.PUT_LINE('Emp Name: '||emp_rec.first_name||' and Total Salary: '||Lv_tot_sal);
END LOOP;
END;
/

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 16
When cursors are used with FOR loops then cursor opening, retrieving data and closing happens
automatically and do not need any explicit operations. Please refer above program, which uses
cursor within FOR loop.

1.6. OPEN-FOR statements [OR] REF CURSORS:

REF cursors are used to point to various context areas by pointing to different SQL
statements. REF cursors use "OPEN FOR" command to open cursors.

 Write a PL/SQL program to retrieve employee name, salary and commission of employees in a
department and calculate total salary using cursors with FOR loop.
SET SERVEROUTPUT ON
DECLARE
Lv_emp_cur SYS_REFCURSOR;
Lv_emp_nameEmployees.first_name%TYPE;
Lv_emp_salEmployees.salary%TYPE;
Lv_emp_commEmployees.commission_pct%TYPE;
Lv_tot_salEmployees.salary%TYPE;
BEGIN
OPEN Lv_emp_cur FOR SELECT first_name, salary, commission_pct
FROM employees WHERE department_id = 90;
LOOP
FETCH Lv_emp_cur INTO Lv_emp_name, Lv_emp_sal, Lv_emp_comm;
EXIT WHEN Lv_emp_cur%NOTFOUND;
Lv_tot_sal := Lv_emp_sal+ NVL(Lv_emp_comm, 0)*Lv_emp_sal;
DBMS_OUTPUT.PUT_LINE('Emp Name: '||Lv_emp_name||' and Total Salary: '||Lv_tot_sal);
END LOOP;
CLOSE Lv_emp_cur;

OPEN Lv_emp_cur FOR SELECT first_name, salary, commission_pct


FROM employees WHERE department_id = 100;
LOOP
FETCH Lv_emp_cur INTO Lv_emp_name, Lv_emp_sal, Lv_emp_comm;
EXIT WHEN Lv_emp_cur%NOTFOUND;
Lv_tot_sal := Lv_emp_sal+ NVL(Lv_emp_comm, 0)*Lv_emp_sal;
DBMS_OUTPUT.PUT_LINE('Emp Name: '||Lv_emp_name||' and Total Salary: '||Lv_tot_sal);
END LOOP;
CLOSE Lv_emp_cur;

END;
/

Here in above example, Lv_emp_cursor is pointed to 2 context areas, one for the data of
department_id = 90 and another is data of department_id = 100. Ref cursors are mainly when
there is a possibility of processing data dynamically.

Additional Note:
PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore
Contact No: 9739096158, 9739771750
www.pskinfo.com Page 17
-- are used for single line comments
/* .....*/ are used for multi-line comments.

2. Collections or composite data types:


Composite data types are used to store more than a single value. There are
different types of composite data types,

 Associative arrays (also known as PL/SQL tables).


 Varrays
 Nested tables.

2.1. Associate arrays:

Associative arrays are used to list of values in a single variable. It will use index
for each element stored in associative array. Associative arrays are ideal when we does
not know the number items stored in the variable. Associative arrays are does not need
to initiate before using them. This is most commonly used composite data type in real
time scenarios to process bulk records. Index by data type in associate arrays can be a
integer or fixed length string value.

Syntax:

TYPE <type_name> IS TABLE OF <data_type> INDEX BY <data_type>;

 Write a PL/SQL program to display list of numbers stored in a associate array.

SET SERVEROUTPUT ON
DECLARE
TYPE list_type IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
list_t list_type;
BEGIN
FOR i IN 1..10
LOOP
list_t(i) := i;
DBMS_OUTPUT.PUT_LINE('Value stored in slot: '||i||' is: '||list_t(i));
END LOOP;
END;
/

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 18
 Write a PL/SQL program to display list of numbers stored in a associate array.

SET SERVEROUTPUT ON
DECLARE
Lv_department_id employees.department_id%TYPE := &deptid;
TYPE emp_sal_type IS TABLE OF employees.salary%TYPE INDEX BY
BINARY_INTEGER;
emp_sal_t emp_sal_type;
BEGIN
SELECT salary BULK COLLECT
INTO emp_sal_t
FROM employees
WHERE department_id = Lv_department_id;

dbms_output.put_line('Total number of elements in type is:


'||emp_sal_t.COUNT);

FOR i in emp_sal_t.FIRST..emp_sal_t.LAST
LOOP
DBMS_OUTPUT.PUT_LINE('Salary in slot: '||i|| emp_sal_t(i));
END LOOP;
END;
/

Records data types that are used along with Associative arrays:

A record datatype is a structure. A structure is a composite variable that contains a list


of variables that typically have names and different datatypes. You define a record datatype
either implicitly or explicitly. There are restrictions on the use of implicitly built records. You
cannot use an implicitly built record in an array. The %ROWTYPE enables you to define an
implicitly anchored record type.

Syntax:

TYPE <Record_name> IS RECORD


(
<variable_name> <data_type>,
<variable_name> <data_type>,
<variable_name> <data_type>
--------------------------------------------
--------------------------------------------
);

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 19
 Write a PL/SQL program to use record types together with associative arrays.

SET SERVEROUTPUT ON
DECLARE
lv_department_id employees.department_id%TYPE := &deptno;
TYPE emp_rec IS RECORD
(
emp_no employees.employee_id%TYPE,
emp_sal employees.salary%TYPE,
emp_job employees.job_id%TYPE
);

TYPE emp_type IS TABLE OF emp_rec INDEX BY BINARY_INTEGER;


emp_t emp_type;
BEGIN
SELECT employee_id, salary, job_id BULK COLLECT
INTO emp_t
FROM employees
WHERE department_id = lv_department_id;

DBMS_OUTPUT.PUT_LINE('Total number of records: '||emp_t.COUNT);

FOR i IN emp_t.FIRST..emp_t.LAST
LOOP
DBMS_OUTPUT.PUT_LINE('Employee id: '||emp_t(i).emp_no||' salary:
'||emp_t(i).emp_Sal||' Job is: '||emp_t(i).emp_job);
END LOOP;
END;
/

2.2. Varrays:

The VARRAY datatype is the most like a traditional array. Elements are of the
same type and use a sequential numeric index. This means the index of VARRAY
variables is densely populated. You opt to use a VARRAY when you know the number of
items that will go in the collection before declaring the variable.

Syntax:

TYPE <varray_name> IS VARRAY(SIZE) OF <data_type>;

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 20
 Write a PL/SQL program to display list of numbers stored in a varray.
SET SERVEROUTPUT ON
DECLARE
TYPE list_va IS VARRAY(10) OF NUMBER; --creating composite data type
list_va_t list_va := list_va(); --Declaring a new composite variable and
initialized.
BEGIN
FOR i IN 1..list_va_t.LIMIT
LOOP
list_va_t.EXTEND;
list_va_t(i) := i;
DBMS_OUTPUT.PUT_LINE('Value in Slot Number: '||i||' is: '||list_va_t(i));
END LOOP;
END;
/

2.3. Nested tables:

The nested table datatype is the more like a numerically indexed list or Java class. As in
the VARRAY, elements are of the same type and use a sequential numeric index. This means the
index of nested table variables is densely populated. You should use a nested table when you
don’t know the number of items that will go in the collection before declaring the variable. Like
lists in other programming languages, the nested table can grow in size after it is declared.

Syntax:

CREATE OR REPLACE TYPE <type_name> IS TABLE OF <data type>;

[OR]

TYPE <type_name> IS TABLE OF <data_type>;

 Write a PL/SQL program to display list of numbers stored in a nested table.

SET SERVEROUTPUT ON
DECLARE
TYPE list_nt_type IS TABLE OF NUMBER; --creating composite data type
list_nt_t list_nt_type := list_nt_type();
BEGIN
FOR i IN 1..100
LOOP
list_nt_t.EXTEND;
list_nt_t(i) := i;
DBMS_OUTPUT.PUT_LINE('Value in Slot Number: '||i||' is: '||list_nt_t(i));
END LOOP;
END;
/

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 21
1. Exceptions:
Exceptions are used to handle the run time errors of PL/SQL code. Exception is an abnormal
behavior of PL/SQL code. In PL/SQL there are different types of exceptions.

 Predefined exceptions.
 User defined exceptions.
 Pragma exception.
 Raise application errors.

1.1. Predefined exceptions:

Oracle handles few exceptions on its own such exceptions are called predefined
exceptions or oracle defined exceptions. There are various predefined exceptions and
below are few very important ones.

Exception Oracle Error Description


NO_DATA_FOUND ORA-1403 A SELECT INTO statement returned no rows, or an
attempt was made to access a deleted element in a
nested table or an uninitialized element in an
"index by" table.
TOO_MANY_ROWS ORA-01422 A SELECT INTO statement returned more than one
row.
ZERO_DIVIDE ORA-01476 An attempt was made to divide a number by zero.
DUP_VAL_ON_INDEX ORA-00001 An attempt was made to store a duplicate value in
a unique key column.
INVALID_CURSOR ORA-01001 An attempt was made to perform an illegal cursor
operation, such as closing an unopened cursor.
CURSOR_ALREADY_OPEN ORA-06511 Attempt was made to open a cursor, which is
already opened. A cursor must be closed before it
is reopened.
OTHERS N/A To handle all other exceptions.

 Write a PL/SQL program to demonstrate NO_DATA_FOUND exception.

SET SERVEROUTPUT ON
DECLARE
Lv_salaryEmployees.employee_id%TYPE;
Lv_commEmployees.salary%TYPE;
Lv_tot_salEmployees.salary%TYPE;
BEGIN
SELECT salary, commission_pct
INTO Lv_salary, Lv_comm
FROM Employees
WHERE employee_id = &employee_id;

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 22
Lv_tot_sal := Lv_salary + NVL(Lv_comm,0)*Lv_salary/100;
DBMS_OUTPUT.PUT_LINE('Employee total salary is: '||Lv_tot_sal);
EXCEPTION
WHEN NO_DATA_FOUND
THEN
DBMS_OUTPUT.PUT_LINE('Provided subscriber number is not found');
END;
/

 Write a PL/SQL program to demonstrate TOO_MANY_ROWS exception.

SET SERVEROUTPUT ON
DECLARE
Lv_salaryEmployees.employee_id%TYPE;
Lv_commEmployees.salary%TYPE;
Lv_tot_salEmployees.salary%TYPE;
BEGIN
SELECT salary, commission_pct
INTO Lv_salary, Lv_comm
FROM Employees
WHERE department_id = &department_id;

Lv_tot_sal := Lv_salary + NVL(Lv_comm,0)*Lv_salary/100;


DBMS_OUTPUT.PUT_LINE('Employee total salary is: '||Lv_tot_sal);
EXCEPTION
WHEN TOO_MANY_ROWS
THEN
DBMS_OUTPUT.PUT_LINE('Department has multiple rows to process, use cursors');
END;
/
 Write a PL/SQL program to demonstrate ZERO_DIVIDE exception.

SET SERVEROUTPUT ON
DECLARE
Lv_salaryEmployees.employee_id%TYPE;
Lv_commEmployees.salary%TYPE;
Lv_quotEmployees.salary%TYPE;
BEGIN
SELECT salary, commission_pct
INTO Lv_salary, Lv_comm
FROM Employees
WHERE employee_id = &employee_id;

Lv_comm := NVL(Lv_comm,0);
Lv_quot := Lv_salary/Lv_comm;
DBMS_OUTPUT.PUT_LINE('Employee total salary is: '||Lv_quot);
EXCEPTION
WHEN ZERO_DIVIDE
THEN
DBMS_OUTPUT.PUT_LINE('Wrong value is used to find quotient, use non zero value');
END;
/

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 23
 Write a PL/SQL program to demonstrate DUP_VAL_ON_INDEX exception.

SET SERVEROUTPUT ON
DECLARE
Lv_department_idDepartments.department_id%TYPE := &id;
Lv_department_nameDepartments.department_name%TYPE :=&name;
Lv_locationDepartments.location_id%TYPE:=&location;
Lv_managerDepartments.manager_id%TYPE:=&manager;
BEGIN
INSERT INTO departments (department_id, department_name, location_id, manager_id)
VALUES (Lv_department_id, Lv_department_name, Lv_location, Lv_manager);
COMMIT;
EXCEPTION
WHEN DUP_VAL_ON_INDEX
THEN
DBMS_OUTPUT.PUT_LINE('Trying to create new department with already existing id');
END;
/

 Write a PL/SQL program to demonstrate INVALID_CURSOR and CURSOR_ALREADY_OPEN.

SET SERVEROUTPUT ON
DECLARE
Lv_emp_nameEmployees.first_name%TYPE;
Lv_salaryEmployees.salary%TYPE;
Lv_commEmployees.commission_pct%TYPE;
Lv_tot_salEmployees.salary%TYPE;
CURSOR cur_emp IS
SELECT first_name, salary, commission_pct
FROM Employees
WHERE department_id = &department_id;
BEGIN
OPEN cur_emp;
LOOP
--OPEN cur_emp;
FETCH cur_emp INTO Lv_emp_name, Lv_salary, Lv_comm;
EXIT WHEN cur_emp%NOTFOUND;
Lv_tot_sal := Lv_salary + NVL(Lv_comm, 0)*Lv_salary;
DBMS_OUTPUT.PUT_LINE('Emp Name: '||Lv_emp_name||' and Total Salary: '||Lv_tot_sal);
--CLOSE cur_emp;
END LOOP;
CLOSE cur_emp;
--CLOSE cur_emp;
INSERT INTO departments (department_id, department_name, location_id, manager_id)
VALUES (&Lv_department_id, &Lv_department_name, &Lv_location, &Lv_manager);
COMMIT;

EXCEPTION
WHEN INVALID_CURSOR
THEN
DBMS_OUTPUT.PUT_LINE('Invalid cursor operation');
WHEN CURSOR_ALREADY_OPEN

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 24
THEN
DBMS_OUTPUT.PUT_LINE('Cursor is already open, close the cursor before reopen');
WHEN OTHERS
THEN
DBMS_OUTPUT.PUT_LINE('Exception raised due to: '||SQLCODE);
DBMS_OUTPUT.PUT_LINE('Error msg: '||SUBSTR(SQLERRM,1,100));
END;
/

1.2. User defined exceptions:

User defined exceptions are exceptions defined by the user to trap exceptional explicitly.
These exceptions do not raise by Oracle and user should pay attention to raise these kind
of exceptions. User defined exceptions are basically used to trap the application level
exceptions based on requirements.

 Write a PL/SQL program to demonstrate user defined exceptions.

SET SERVEROUTPUT ON
DECLARE
Lv_new_salEmployees.salary%TYPE;
Le_invalid_empException;
Le_max_thr_crossed Exception;
BEGIN
UPDATE Employees SET salary = salary+(10/100)*salary
WHERE employee_id = &employee_id RETURN salary INTO Lv_new_sal;
IF SQL%NOTFOUND
THEN
RAISE Le_invalid_emp;
END IF;
IF Lv_new_sal> 25000
THEN
RAISE Le_max_thr_crossed;
END IF;
DBMS_OUTPUT.PUT_LINE('Employee new salary is: '||Lv_new_sal);

EXCEPTION
WHEN Le_invalid_emp
THEN
DBMS_OUTPUT.PUT_LINE('Employee not found');
WHEN Le_max_thr_crossed
THEN
DBMS_OUTPUT.PUT_LINE('Employee crossed max threshold salary');
WHEN OTHERS
THEN
DBMS_OUTPUT.PUT_LINE('Salary update failed due to, '||SQLCODE);
END;
/

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 25
1.3. Pragma Exception:

Non predefined exceptions are similar to predefined exceptions; however, they are not
defined as predefined PL/SQL exceptions in Oracle server. They are standard Oracle errors.
Pragma exceptions are used to create and trap exceptions for non-predefined oracle errors

 Write a PL/SQL program to demonstrate user defined exceptions.

SET SERVEROUTPUT ON
DECLARE
Le_insert_null Exception;
PRAGMA EXCEPTION_INIT(Le_insert_null, -1400);
BEGIN
INSERT INTO departments (department_id, department_name) VALUES (285, NULL);
--COMMIT;
EXCEPTION
WHEN Le_insert_null
THEN
DBMS_OUTPUT.PUT_LINE('Null values are not allowed for specified column');
WHEN OTHERS
1.4.
THEN R
a
DBMS_OUTPUT.PUT_LINE('Failed due to : '||SQLCODE);
END; i
/
s
e Application Errors:

The RAISE_APPLICATION_ERROR procedure can be used in either the executable or


exception section of PL/SQL program or both. The returned error is consistent with how
the Oracle Server produces a predefined, non-predefined, or user-defined error. The error
number and message are displayed to the user. In RAISE_APPLICATION_ERROR procedure,
error numbers allowed are range from -20000 to -20999.

 Write a PL/SQL program to demonstrate RAISE_APPICATION_ERRORS.

SET SERVEROUTPUT ON
DECLARE
Lv_new_SalEmployees.salary%TYPE;
Le_max_thr_crossed Exception;
BEGIN
UPDATE employees SET salary = salary+(10/100)*salary WHERE employee_id = &employee_id
RETURN salary INTO Lv_new_Sal;
IF SQL%NOTFOUND
THEN
RAISE_APPLICATION_ERROR(-20001,'Invalid employee Id is used');
END IF;
IF Lv_new_sal> 25000
THEN
RAISE Le_max_thr_crossed;
END IF;
--COMMIT;
EXCEPTION

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 26
WHEN Le_max_thr_crossed
THEN
RAISE_APPLICATION_ERROR(-20123,'Employee crossed max salary limit');
WHEN OTHERS
THEN
DBMS_OUTPUT.PUT_LINE('Failed due to : '||SQLCODE);
DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
/

2. Procedures:
A procedure contains a group of SQL and PL/SQL statements. Procedures allow you to centralize
your business logic in the database and may be used by any program that accesses the
database.

2.1. Creating a procedure.

Procedure is created using "CREATE PROCEDURE" Statement. The simplified syntax for
the CREATE PROCEDURE statement is as follows,

CREATE [OR REPLACE] PROCEDURE Procedure_name


[(parameter_name [IN | OUT | IN OUT ] type [,.....])]
AS | IS
Declare local variables, cursors etc.
BEGIN
Procedure_body;
END Procedure_name;

Where,
 OR REPLACE means the procedure is to replace an existing procedure.
 Procedure_name is the name of the procedure.
 Parameter_name is the name of a parameter that is passed to the procedure.
You maypass multiple parameters to a procedure.
 IN | OUT | IN OUT is the mode of the parameter. You may pick one of the
following
modes for each parameter:
IN, which is the default mode for a parameter. An IN parameter must be set to a
value when the procedure is run. The value of an IN parameter cannot be
changedin the procedure body.

OUT, which means the parameter is set to a value in the procedure body.
IN OUT, which means the parameter can have a value when the procedure is
run,and the value can be changed in the body.
 Type is the type of the parameter.
 Procedure body contains the actual code for the procedure.

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 27
 Create a stored procedure to calculate total salary of each employee in a department.

CREATE OR REPLACE PROCEDURE Get_Dept_Emp_Salary (i_dept_id IN Employees.department_id%TYPE)


AS
Lv_emp_nameEmployees.first_name%TYPE;
Lv_salaryEmployees.salary%TYPE;
Lv_commEmployees.commission_pct%TYPE;
Lv_tot_salEmployees.salary%TYPE;
Lv_tot_emps PLS_INTEGER;
CURSOR cur_emp IS
SELECT first_name, salary, commission_pct
FROM Employees
WHERE department_id = i_dept_id;
BEGIN
IF cur_emp%ISOPEN = FALSE
THEN
OPEN cur_emp;
END IF;
LOOP
FETCH cur_emp INTO Lv_emp_name, Lv_salary, Lv_comm;
EXIT WHEN cur_emp%NOTFOUND;
IF cur_emp%FOUND = TRUE
THEN
Lv_tot_sal := Lv_salary + NVL(Lv_comm, 0)*Lv_salary;
DBMS_OUTPUT.PUT_LINE('Emp Name: '||Lv_emp_name||' and Total Salary: '||Lv_tot_sal);
END IF;
END LOOP;
Lv_tot_emps := cur_emp%ROWCOUNT;
DBMS_OUTPUT.PUT_LINE('Total number of employees: '||Lv_tot_emps);
PIF cur_emp%ISOPEN = TRUE
rTHEN
o CLOSE cur_emp;
cEND IF;
EXCEPTION
eWHEN OTHERS THEN
d DBMS_OUTPUT.PUT_LINE('Error code: '|| SQLCODE);
u DBMS_OUTPUT.PUT_LINE('Error msg: '||SUBSTR(SQLERRM,1,100));
END
r Get_Dept_Emp_Salary;
/e
body or procedure logic is similar Anonymous blocks learned earlier. Create procedure
just assigns a unique name to the anonymous block in the database.

2.2. Calling a procedure:

Exec[ute] <Procedure_name>(parameter list);


SQL> SET SERVEROUTPUT ON;
SQL> EXEC Get_Dept_Emp_Salary(100);

A procedure can also be called using CALL keyword as below.


SQL> CALL Get_Dept_Emp_Salary(100);

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 28
2.3. Getting information on procedures:

USER_PROCEDURES is the Meta data that gives information about the procedures.
Procedures can be identified based on OBJECT_TYPE column in USER_PROCEDURES.
SELECT * FROM user_procedres WHERE object_type = 'PROCEDURE';
[OR]
SELECT * FROM user_objects WHERE object_type = 'PROCEDURE';

2.4. Dropping a procedure:

DROP PROCEDURE <Procedure_name>;


SQL> DROP PROCEDURE Get_Dept_Emp_Salary;

2.5. Viewing Errors of a Procedure:

After compiling procedure, below command can be used to list the compilation errors of
procedure, if any.
SQL> SHOW ERRORS;

 Create a stored procedure to get employee name and Manager Information as output
parameters.

CREATE OR REPLACE PROCEDURE Get_Emp_name_Manager(i_employee_id IN Employees.employee_id%TYPE,


o_emp_name OUT Employees.first_name%TYPE,
o_manager_id OUT Employees.manager_id%TYPE,
io_ret_code IN OUT NUMBER,
io_ret_msg IN OUT VARCHAR2)
AS
BEGIN
SELECT first_name, manager_id INTO
o_emp_name, o_manager_id FROM employees
WHERE employee_id = i_employee_id;
io_ret_code := 0;
io_ret_msg := 'Sucess';
EXCEPTION
WHEN NO_DATA_FOUND THEN
io_ret_code := SQLCODE;
Io_ret_msg := SUBSTR(SQLERRM,1,100);
WHEN OTHERS THEN
io_ret_code := SQLCODE;
Io_ret_msg := SUBSTR(SQLERRM,1,100);
END Get_Emp_name_Manager;
/

Call Procedure from Anonymous Block:


Execute procedure for employee number 1001 (which do not exists in employees table)

SET SERVEROUTPUT ON;


DECLARE

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 29
Lv_emp_name employees.first_name%TYPE;
Lv_manager_id employees.manager_id%TYPE;
Lv_ret_code NUMBER := 0;
Lv_ret_msg VARCHAR2(100):= 'Success';
BEGIN
Get_Emp_name_Manager(i_employee_id => 1001,
o_emp_name => Lv_emp_name,
o_manager_id => Lv_manager_id,
io_ret_code => Lv_ret_code,
io_ret_msg => Lv_ret_msg
);
IF Lv_ret_code = 0
THEN
DBMS_OUTPUT.PUT_LINE('Employee Name: '||Lv_emp_name);
DBMS_OUTPUT.PUT_LINE('Manager ID: '||Lv_manager_id);
ELSE
DBMS_OUTPUT.PUT_LINE('Emp details can not be retrieved');
DBMS_OUTPUT.PUT_LINE('Response code: '|| Lv_ret_code);
DBMS_OUTPUT.PUT_LINE('Response message: '||Lv_ret_msg);
END IF;
END;
/

Output:

anonymous block completed


Emp details can not be retrieved
Response code: 100
Response message: ORA-01403: no data found

Call the Procedure from anonymous block:

Execute procedure from employee number 101.

SET SERVEROUTPUT ON;


DECLARE
Lv_emp_name employees.first_name%TYPE;
Lv_manager_id employees.manager_id%TYPE;
Lv_ret_code NUMBER := 0;
Lv_ret_msg VARCHAR2(100):= 'Success';
BEGIN
Get_Emp_name_Manager(i_employee_id => 101,
o_emp_name => Lv_emp_name,
o_manager_id => Lv_manager_id,
io_ret_code => Lv_ret_code,
io_ret_msg => Lv_ret_msg
);
IF Lv_ret_code = 0
THEN
DBMS_OUTPUT.PUT_LINE('Employee Name: '||Lv_emp_name);
DBMS_OUTPUT.PUT_LINE('Manager ID: '||Lv_manager_id);
ELSE
DBMS_OUTPUT.PUT_LINE('Emp details can not be retrieved');
DBMS_OUTPUT.PUT_LINE('Response code: '|| Lv_ret_code);
DBMS_OUTPUT.PUT_LINE('Response message: '||Lv_ret_msg);
END IF;
END;
/

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 30
Output:

anonymous block completed


Employee Name: Neena
Manager ID: 100

3. Functions:
A function is similar to a procedure, except that a function must return a value.
Together, stored procedures and functions are sometimes referred to as stored subprograms
because they are small programs.

Below section describes about functions in PL/SQL.

 Create a function.
 Call a function.
 Get information on functions.
 Drop a function.

3.1. Creating a Function

A function can be created using the CREATE FUNCTION statement.


The simplified syntax for the CREATE FUNCTION statement is as follows:

CREATE [OR REPLACE] FUNCTION function_name


[(parameter_name [IN | OUT | IN OUT] type [, ...])]
RETURN type
{IS | AS}
BEGIN
function_body
END function_name;

Where
 OR REPLACE means the function is to replace an existing function.
 Function_name is the name of the function.
 Parameter_name is the name of a parameter that is passed to the
function. Multiple parameters can be passed to a function.
 IN |OUT | IN OUT is the mode of the parameter.
 type is the type of the parameter.
 Function_body contains actual code for the function. Unlike a procedure,
the body of a function must return a value of the type specified in the
RETURN clause.

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 31
 Create a function to return the total salary of a employee.
CREATE OR REPLACE FUNCTION Get_emp_tot_sal (i_emp_id IN employees.employee_id%TYPE)
RETURN employees.salary%TYPE
AS
Lv_salary employees.salary%TYPE;
Lv_comm employees.commission_pct%TYPE;
Lv_tot_sal employees.salary%TYPE;
BEGIN
SELECT salary, commission_pct INTO Lv_salary, Lv_comm
FROM employees WHERE employee_id = i_emp_id;
Lv_tot_sal := Lv_salary + NVL(lv_comm, 0)*Lv_salary;
RETURN Lv_tot_sal;
EXCEPTION
WHEN OTHERS THEN
RETURN 0;
END Get_emp_tot_Sal;
/

Use Function in SQL*Plus session:

SQL> SELECT Get_emp_tot_sal(175) FROM DUAL;


GET_EMP_TOT_SAL(175)
--------------------
11000
Here employee salary is 8800 and commission_pct (percentage of commission) is 0.25, which means
commission is 2200 (0.25 of 8800) and total salary is 8800+2200 = 11000.

SQL> SELECT Get_emp_tot_sal(1750) FROM DUAL;

GET_EMP_TOT_SAL(1750)
---------------------
0
Here Employee number is 1750 which does not exists in table and hence total salary returned is 0.

 Create a function to check whether employee is available and return total salary of employee
if available else notify as subscriber is not found.

CREATE OR REPLACE FUNCTION Get_check_emp_tot_sal(i_emp_id IN employees.employee_id%TYPE,


o_tot_sal OUT employees.salary%TYPE)

RETURN BOOLEAN
AS
Lv_salary employees.salary%TYPE;
Lv_comm employees.commission_pct%TYPE;
BEGIN
SELECT salary, commission_pct INTO Lv_salary, Lv_comm
FROM employees WHERE employee_id = i_emp_id;
o_tot_sal := Lv_salary + NVL(lv_comm, 0)*Lv_salary;
RETURN TRUE;
EXCEPTION
WHEN OTHERS THEN
RETURN FALSE;
END Get_check_emp_tot_sal;
/

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 32
This function can not be used in SQL*plus session as this function has a output parameter apart from return value.
This function can be used in another procedure, function or anonymous block as described below.

CREATE OR REPLACE PROCEDURE Get_dept_emp_sal( i_dept_id IN employees.department_id%TYPE)


AS
Lv_tot_sal employees.salary%TYPE;
BEGIN
FOR emp_rec IN (SELECT employee_id, salary, commission_pct FROM employees WHERE department_id =
i_dept_id)
LOOP
IF Get_check_emp_tot_sal(i_emp_id => emp_rec.employee_id,
o_tot_sal => lv_tot_sal
)
THEN
DBMS_OUTPUT.PUT_LINE('Employee:' ||emp_rec.employee_id||' Tot sal is: '||lv_tot_sal);
END IF;
END LOOP;
END Get_dept_emp_sal;
/

SQL> SET SERVEROUTPUT ON;


SQL> CALL Get_dept_emp_sal(100);
Employee:108 Tot sal is: 12008
Employee:109 Tot sal is: 9000
Employee:110 Tot sal is: 8200
Employee:111 Tot sal is: 7700
Employee:112 Tot sal is: 7800
Employee:113 Tot sal is: 6900

3.2. Calling a function

A function can be called from SQL* plus session as other built-in functions do (but it
depends on the logic written in the function body).

A function can also be called in conditional statements (for e.g., in IF statements).

3.3. Getting information on Functions.

user defined functions information can be retrieved from data dictionary table called
USER_PROCEDURES where OBJECT_TYPE is "FUNCTION".

SELECT * FROM user_procedures WHERE object_name = 'FUNCTION';

[OR]

SELECT * FROM user_objects WHERE object_name = 'FUNCTION';

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 33
3.4. Dropping Functions.

User defined functions can be dropped using a command called "DROP FUNCTION". Below is an
example.

SQL> DROP FUNCTION Get_Emp_Tot_Sal;

4. Packages:
In this section, you’ll learn how to group procedures and functions together into
packages. Packages allow you to encapsulate related functionality into one self-contained unit.
By modularizing your PL/SQL code through the use of packages, you can build up your own
libraries of code that other programmers can reuse.

Packages are typically made up of two components: a specification and a body. The
package specification lists the available procedures, functions, types, and objects. You can make
the items listed in the specification available to all database users, and these items as being
referred as public (although only users you have granted privileges to access your package can
use it). The specification doesn’t contain the code that makes up the procedures and functions;
the code is contained in the package body.

Any items in the body that are not listed in the specification are private to the package.
Private items can be used only inside the package body. By using a combination of public and
private items, you can build up a package whose complexity is hidden from the outside world.
This is one of the primary goals of all programming: hide complexity from your users.

4.1. Creating a Package Specification

You create a package specification using the CREATE PACKAGE statement. The simplified
syntax for the CREATE PACKAGE statement is as follows:

CREATE [OR REPLACE] PACKAGE package_name


{IS | AS}
package_specification
END package_name;

Where
 OR REPLACE means the package specification is to replace an existing
package specification.
 Package_name is the name of the package.
 package_specification lists the public procedures, functions, types, and
objects available to your package’s users.

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 34
Below package (specification and body ) demonstrates usage of packages and how to
use types, functions and procedures in package.

Below is the package specification which contains TYPE for ref cursor, Function to get all
employee records and procedure to update employee salary. All these objects stored in
combine in a single unit called package.

CREATE OR REPLACE PACKAGE Emplployee_utility_pkg


IS
TYPE emp_ref_cursor IS REF CURSOR;
FUNCTION get_emp_ref_cursor RETURN emp_ref_cursor;
PROCEDURE update_emp_salary (i_emp_id IN Employees.employee_id%TYPE,
i_hike_percentage IN NUMBER
);
END Emplployee_utility_pkg;
/

4.2. Creating a Package Body

A package body can be created using "CREATE PACKAGE BODY" statement. The
simplified syntax for the CREATE PACKAGE BODY statement is as follows:

CREATE [OR REPLACE] PACKAGE BODY package_name


{IS | AS}
package_body
END package_name;

Where
 Package_name is the name of the package, which must match the
package name in the specification.
 Package_body contains the code for the procedures and functions.

CREATE OR REPLACE PACKAGE BODY Emplployee_utility_pkg


IS
FUNCTION get_emp_ref_cursor
RETURN emp_ref_cursor IS
lv_emp_ref_cursor emp_ref_cursor;
BEGIN
--get the ref cursor for employee records.
OPEN lv_emp_ref_cursor FOR
SELECT employee_id, first_name, salary
FROM employees;
RETURN lv_emp_ref_cursor;
END get_emp_ref_cursor;

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 35
PROCEDURE update_emp_salary (i_emp_id IN employees.employee_id%TYPE,
i_hike_percentage IN NUMBER
)
AS
lv_emp_count PLS_INTEGER;
BEGIN
--Count the number of employees with supplied emp_id
SELECT count(*) INTO lv_emp_count
FROM employees
WHERE employee_id = i_emp_id;

--if employee exists (lv_emp_count = 1)


IF lv_emp_count = 1
THEN
UPDATE employees SET salary = salary + (salary*i_hike_percentage)
WHERE employee_id = i_emp_id;
COMMIT;
END IF;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
END update_emp_salary;
The
get_emp END Emplployee_utility_pkg;
_ref_curs /
or()
function opens the cursor and retrieves the employee_id, name and salary columns from the
employees table. The reference to this cursor (the REF CURSOR) is stored in lv_emp_ref_cursor and
returned by the function.

The update_emp_salary() procedure updates salary with new hike percentage and
COMMITs transaction. This procedure is identical to the one shown earlier in the section
“Creating a Procedure".

4.3. Calling functions and procedures in a Package.

When calling functions and procedures in a package, you must include the package name in the
call. The following example calls " Emplployee_utility_pkg.get_emp_ref_cursor(), which returns
a reference to the cursor containing information of employee_id, first_name and salary.

SQL> SELECT Emplployee_utility_pkg.get_emp_ref_cursor FROM dual;

Now, call procedure in a package to update one of employee salary.

SQL> SELECT employee_id, first_name, salary FROM employees WHERE employee_id = 100;

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 36
EMPLOYEE_ID FIRST_NAME SALARY
------------------ ----------------- --- ----------
100 Steven 24000
SQL> CALL Emplployee_utility_pkg. update_emp_salary(100,0.25);

emplployee_utility_pkg. UPDATE_EMP_SALARY succeeded.


SQL> SELECT employee_id, first_name, salary FROM employees WHERE employee_id = 100;

EMPLOYEE_ID FIRST_NAME SALARY


------------------ ----------------- --- ----------
100 Steven 30000

Now, employee (employee_id = 100, Steven) salary increased to 30000 (24000 + 25% hike
added). update of employee information is done via procedure created in package.

4.4. Getting information on functions and procedures in a package:

You can get information on your functions and procedures in a package from the
user_procedures view; this view was covered earlier in the section “Getting Information
on Procedures.” The following example retrieves the object_name and procedure_name
columns from user_procedures :

SQL> SELECT * FROM user_procedures WHERE object_type = 'PACKAGE';


Above SQL query displays all public procedures and functions created under package.

SQL> SELECT * FROM user_objects WHERE object_type = 'PACKAGE';

4.5. Dropping a Package:

Package can be dropped by using "DROP PACKAGE " command. For e.g., the following
statement drops " EMPLPLOYEE_UTILITY_PKG".

SQL> DROP PACKAGE Emplployee_Utility_Pkg;

5. Triggers:
A trigger is a procedure that is run (or fired ) automatically by the database when a specified
DML statement (INSERT, UPDATE, or DELETE) is run against a certain database table. Triggers
are useful for doing things like advanced auditing of changes made to column values in a table.

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 37
5.1. When a trigger fires:

A trigger may fire before or after a DML statement runs. Also, because a DML statement can
affect more than one row, the code for the trigger may be run once for every row affected (a
row-level trigger), or just once for all the rows (a statement-level trigger). For example, if you
create a row level trigger that fires for an UPDATE on a table, and you run an UPDATE statement
that modified ten rows of that table, then that trigger would run ten times. If, however, your
trigger was a statement-level trigger, the trigger would fire once for the whole UPDATE
statement, regardless of the number of rows affected.

There is another difference between a row-level trigger and a statement-level trigger: A row
level trigger has access to the old and new column values when the trigger fires as a result of an
UPDATE statement on that column. The firing of a row-level trigger may also be limited using a
trigger condition; for example, you could set a condition that limits the trigger to fire only when
a column value is less than a specified value.

5.2. Set Up for the Example Trigger

As mentioned, triggers are useful for doing advanced auditing of changes made to column
values. In the next section, you’ll see a trigger that records when a employee's salary is
updated; when this occurs, the trigger will add a row to the employee_salary_audit table.
The employee_salary_audit table is created by the following statement

CREATE TABLE employee_salary_audit


( employee_id NUMBER(6)
CONSTRAINT emp_sal_aud_fk REFERENCES employees (employee_id),
old_salary NUMBER(8,2),
new_salary NUMBER(8,2));

As you can see, the employee_id column of the employee_salary_audit table is a foreign key to
the employee_id column of the employees table. The old_salary column will be used to store
the old salary of a employee prior to the change, and the new_salary column will be used to
store the new salary after the change.

5.3. Creating a trigger

You create a trigger using the CREATE TRIGGER statement. The simplified syntax for the
CREATE TRIGGER statement is as follows:

CREATE [OR REPLACE] TRIGGER trigger_name


{BEFORE | AFTER | INSTEAD OF | FOR} trigger_event
ON table_name
[FOR EACH ROW]

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 38
[{ENABLE | DISABLE}]
[WHEN trigger_condition]]
BEGIN
trigger_body
END trigger_name;

Where
 OR REPLACE means the trigger is to replace an existing trigger, if present.
 trigger_name is the name of the trigger.
 BEFORE means the trigger fires before the triggering event is performed. AFTER means the
trigger fires after the triggering event is performed. INSTEAD OF means the trigger fires instead
of performing the triggering event. FOR, which is new for Oracle Database 11g, allows you to
create a compound trigger consisting of up to four sections in the trigger body.
 trigger_event is the event that causes the trigger to fire.
 table_name is the table that the trigger references.
 FOR EACH ROW means the trigger is a row-level trigger, that is, the code contained within
trigger_body is run for each row when the trigger fires. If you omit FOR EACH ROW, the trigger is
a statement-level trigger, which means the code within trigger_body is run once when the
trigger fires.
 {ENABLE | DISABLE} is new for Oracle Database 11g and indicates whether the trigger is initially
enabled or disabled when it is created (the default is ENABLE). You enable a disabled trigger by
using the ALTER TRIGGER trigger_name ENABLE statement or by enabling all triggers for a table
using ALTER TABLE table_name ENABLE ALL TRIGGERS.
 trigger_condition is a Boolean condition that limits when a trigger actually runs its code.
 trigger_body contains the code for the trigger.

The example trigger you’ll see in this section fires before an update of the salary column in the
employees table; therefore, I’ll name the trigger before_emp_sal_update. Also, because I
want to use the salary column values before and after an UPDATE statement modifies the salary
column’s value, I must use a row-level trigger.

 Write a trigger to audit employee salary details.

STEP 1: Create Audit table as mentioned above.


SQL> CREATE TABLE employee_salary_audit
(employee_id NUMBER(6)
CONSTRAINT emp_sal_aud_fk REFERENCES employees(employee_id),
old_salary NUMBER(8,2),
new_salary NUMBER(8,2));

table EMPLOYEE_SALARY_AUDIT created

STEP2: Check the total number of rows in audit table.


SQL> SELECT * FROM employee_salary_audit;

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 39
no rows selected

STEP3: Write trigger to track salary changes in a audit table created above.

CREATE OR REPLACE TRIGGER before_emp_sal_update


BEFORE UPDATE OF salary
ON employees
FOR EACH ROW
BEGIN
dbms_output.put_line('employee_id = ' || :old.employee_id);
dbms_output.put_line('Old salary = ' || :old.salary);
dbms_output.put_line('New salary = ' || :new.salary);

-- insert row into the employee_salary_audit table


INSERT INTO employee_salary_audit( employee_id, old_salary, new_salary)
VALUES (:old.employee_id, :old.salary, :new.salary);
END before_emp_sal_update;
/

STEP4: Update salary of employees for department 100. Increase salary by 10%.
SQL> UPDATE employees SET salary = salary + (salary*0.10) WHERE department_id = 100;
6 rows updated.
SQL> COMMIT;
Committed

STEP5: Check the total number of rows now in audit table.


SQL> SELECT * FROM employee_salary_audit;

EMPLOYEE_ID OLD_SALARY NEW_SALARY


108 12008 13208.8
109 9000 9900
110 8200 9020
111 7700 8470
112 7800 8580
113 6900 7590

 Write a trigger to track the table changes with user name, time and type of operation.
STEP 1: Create Emp_Chg_Track_Tab
SQL> CREATE TABLE Emp_Chg_Track_Tab
(operation VARCHAR2(6),
User_name VARCHAR2(6),
date_of_operation DATE);

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 40
STEP 2: Check the data in Emp_Chg_Track_Tab;
STEP 3: Create trigger as below.
CREATE OR REPLACE TRIGGER Emp_Chg_Track_Trig
AFTER INSERT OR UPDATE OR DELETE ON Employees
BEGIN
CASE WHEN INSERTING THEN
INSERT INTO Emp_Chg_Track_tab VALUES ('INSERT',USER, SYSDATE);
WHEN DELETING THEN
INSERT INTO Emp_Chg_Track_tab VALUES ('DELETE',USER,SYSDATE);
WHEN UPDATING THEN
INSERT INTO Emp_Chg_Track_tab VALUES ('UPDATE',USER,SYSDATE);
END CASE;
END Emp_Chg_Track_Trig;
/

STEP 4: UPDATE salary of employees table for department 90.


STEP 5: Check data in Emp_Chg_Track_Tab; It should have only one record with operation as
UPDATE.

You can below info:

3 rows updated.
committed.
OPERATION USER_NAME DATE_OF_OPERATION
--------- --------- -----------------
UPDATE HR 12-APR-15

5.4. Getting information on triggers:

USER_TRIGGERS meta data or data dictionary gives the information about triggers
available in that particular user.

USER_OBJECTS meta data or data dictionary with OBJECT_TYPE as TRIGGER also gives
same info mentioned above.

5.5. Disabling and Enabling a Trigger

A trigger can be enabled or disabled at any time using below commands.

--Disable trigger.

SQL> ALTER TRIGGER Emp_Chg_Track_Trig DISABLE;

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 41
By disabling trigger, it can't be fired automatically when specified DML is executed. You
can test and verify the firing of trigger.

--Enable trigger.

SQL> ALTER TRIGGER Emp_Chg_Track_Trig ENABLE;

By Enabling trigger, it can be fired automatically when specified DML is executed. You
can test and verify the firing of trigger.

5.6. Dropping a trigger

A Trigger can be dropped by using DROP TRIGGER command. Below is the sample
command to drop trigger.

SQL> DROP TRIGGER Emp_Chg_Track_Trig;

PSK Real-time Institute, Opp. Innovative Multiplex, Marathahalli, Bangalore


Contact No: 9739096158, 9739771750
www.pskinfo.com Page 42

You might also like