0% found this document useful (0 votes)
11 views152 pages

ORACLE 4PM PLSQL

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
0% found this document useful (0 votes)
11 views152 pages

ORACLE 4PM PLSQL

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
Download as pdf or txt
You are on page 1/ 152

PL/SQL

Wednesday, June 14, 2023 4:48 PM

ORACLE
DATABASE
SQL TABLES
PL/SQL ROWS & COLUMNS

SQL:
• SQL is Non-Procedural Language
• just we write queries. we will not programs [set of statements]

PL/SQL:
• PL => Procedural Language
• SQL => Structured Query Language

• PL/SQL is a procedural language.

• In this, we write a set of statements or programs to


communicate with database.

• PL/SQL = SQL + Programming

• PL/SQL is extension of SQL.

• SQL queries can be written as statements in PL/SQL program.

Advantages of PL/SQL:

• Improves the performance.


• Provides Conditional Control Structures.
• Provides Looping Control Structures.
• Provides Modularity.
• Provides Exception Handling.
• Provides Security.

ORACLE 4PM PLSQL Page 1


Improves the performance:

ORACLE SERVER
Client
request
INSERT
response
DELETE

UPDATE

request
PL/SQL program

INSERT
response
DELETE
UPDATE

• We can group SQL commands as one request in PL/SQL


program.

• PL/SQL reduces no of requests and responses. So


automatically performance will be improved.

Provides Conditional Control Structures:

• Using Conditional Control Structures, we can perform the


actions based on conditions
• PL/SQL provides conditional control structures such as:
IF .. THEN, IF .. THEN .. ELSE, IF .. THEN .. ELSIF

Example:
increase salary
after increment if salary is more than 50000 => ROLLBACK
otherwise => COMMIT

Provides Looping Control Structures:

ORACLE 4PM PLSQL Page 2


• Looping Control Structures are used to execute the
statements repeatedly.
• PL/SQL provides looping control structures such as:
Simple Loop, While Loop and For Loop

Ex:
Update salary to all emps with different hikes

UPDATE => 7369 => 10% on sal


7499 => 15% on sal
7521 => 12% on sal

Modularity:
• Modularity is a programming style.

• Modularity means, dividing large program into small parts

Procedure-1

Procedure-2

.
.

Procedure-3

Advantages:

• improves understandability
• provides reusability
• reduces length of code
better maintenance
ORACLE 4PM PLSQL Page 3
• better maintenance

Exception Handling:

Exception => Run-Time Error

Exception Handling:
The way of handling run-time error is called Exception Handling.

100 lines

…..
…….
… 50th line => Run-Time Error
…..
…… Application will be closed

Abnormal termination will occur.


We may loss some data

To convert abnormal termination to normal termination,


we use Exception Handling.

Provides Security:

• All procedures and functions will be stored in centralized


location [SERVER].
• Only authorized users can use the procedures and functions.

Types of Blocks:

2 Types:

Anonymous Block
ORACLE 4PM PLSQL Page 4
• Anonymous Block
• Named Block

Anonymous Block Named block

BEGIN CREATE PROCEDURE demo AS


--Statements BEGIN
END; --Statements
/ END;
/

Anonymous Block:
A block without name is called "Anonymous Block".

Named Block:
A block with the name is called "Named Block"

Exs:
Procedures, Functions, Triggers, Packages

Syntax of Anonymous Block: / Run

DECLARE
--declare the variables declaration part [optional]
BEGIN
--executable statements
execution part
END;
/

DATA TYPES
DECLARE
ASSIGN
INITIALIZE
PRINT

ORACLE 4PM PLSQL Page 5


PRINT
READ

dbms_output.put_line('hello');

In C:
printf("hello");

In Java:
System.out.println("hello");
PACKAGE dbms_output

PROCEDURE put_line(s STRING)


AS
…….
……
…..

Syntax to call packaged procedure:


package_name.procedure_name(<arguments>);

Ex:
dbms_output.put_line('HELLO');

put_line():
• It is a packaged procedure.
• It is defined in "DBS_OUTPUT" package.
• It is used to print the data.

Developing PL/SQL Program:

ORACLE 4PM PLSQL Page 6


Program to print 'hello':

BEGIN
dbms_output.put_line('HELLO');
END;
/

• Type above program in text editor like Notepad, Edit Plus,


Notepad++ …etc.

• Save it in "D:" Drive, "ORA4PM" Folder, with the name


"HelloDemo.sql"

Compiling & Running PL/SQL Program:

• Open SQL PLUS

• Login as USER.
○ username: c##batch4pm
○ password: nareshit

• At SQL prompt type following commands:

Syntax: @<path_of_sqlfile>

SQL> SET SERVEROUTPUT ON


SQL> @d:\ora4pm\Helloemo.sql --compiling PL/SQL program
Output:
HELLO

SERVEROUTPUT:
• It is a parameter.
• Its default value is: OFF
• If it is OFF, messages cannot be sent to output.
• To send messages to output, it must be ON.

to set serveroutput as on write following command:

SQL> SET SERVEROUTPUT ON

ORACLE 4PM PLSQL Page 7


Data Types in PL/SQL:

Character Related Char(n)


Varchar2(n)
LONG
CLOB
STRING(n) => PL/SQL Only

nChar(n)
nVarchar2(n)
nCLOB

Integer Related Number(p)


INTEGER
INT
PLS_INTEGER => PL/SQL only
BINARY_INTEGER => PL/SQL only

Floating Point Related Number(p,s)


FLOAT
BINARY_FLOAT
BINARY_DOUBLE
REAL

Date & Time Related DATE


TIMESTAMP

Binary Related BFILE


BLOB

Boolean Related Boolean => PL/SQL Only [ORACLE 21c]

from ORACLE 23c version onwards,


BOOLEAN data type will be available for
SQL and PL/SQL

Cursor Related sys_Refcursor => PL/SQL only

Attribute Related %TYPE => PL/SQL only

ORACLE 4PM PLSQL Page 8


Attribute Related %TYPE => PL/SQL only
%ROWTYPE => PL/SQL only

Variable:
• It is an Identifier.
• It is a name of storage location.
• It holds a value.
• It can hold one value only.

Declaring Variable:

Syntax:
<variable> <data_type>;

Exs:
x INT;
s STRING(10);

a NUMBER(4);
b VARCHAR2(10);
c DATE;

Assigning Value:

:= Assignment Operator In C/Java:

x=25;
Syntax:
<variable> := <constant / variable / expression>;
= Assignment Operator
Exs: x y z
x := 25; --25 - constant 25 25 50
y := x; --x - variable
z := x+y; -- x+y - expression

x+y := z; //INVALID

25 := z; //INVALID
ORACLE 4PM PLSQL Page 9
25 := z; //INVALID

Initializing value:

Initialization => giving value at the time of declaration

Examples: x
x
null
25
x INT; --declare 25
x INT := 25;
x := 25; --assign

Printing data:

dbms_output.put_line(x);

Reading data:

x := &x;

Output:
enter value for x: 25
old: &x
new: 25
x := &x
x := 25

DECLARE x INT;
ASSIGN x := 25;
INITIALIZE x INT := 25;
PRINT dbms_output.put_line(x);
READ x := &x;

ORACLE 4PM PLSQL Page 10


READ x := &x;

Program to add 2 numbers:

declare x,y,z as int


x y
20 30 assign 20 to x
assign 30 to y
20+30 => 50
z := x+y add them & store result in z

print result

x y z
DECLARE
x INT; 20 30 50
y INT;
z INT;
BEGIN
x := 20;
y := 30;

z := x+y;

dbms_output.put_line('sum=' || z);
dbms_output.put_line('sum of ' || x || ' and ' || y || ' is ' || z);
END;
/

Output:
sum=50
sum of 20 and 30 is 50

Program to add 2 number. Read 2 numbers at runtiime:

ORACLE 4PM PLSQL Page 11


Program to add 2 number. Read 2 numbers at runtiime:

DECLARE
x INT;
y INT;
z INT;
BEGIN
x := &x;
y := &y;

z := x+y;

dbms_output.put_line('sum=' || z);
dbms_output.put_line('sum of ' || x || ' and ' || y || ' is ' || z);
END;
/

SQL> @d:\ora4pm\ReadDemo.sql
Enter value for x: 5
old 6: x := &x;
new 6: x := 5;
Enter value for y: 4
old 7: y := &y;
new 7: y := 4;
sum=9
sum of 5 and 4 is 9

VERIFY:
• it is a parameter
• its default value is ON
• set it as OFF to avoid OLD and NEW parameters

Type following command to set verify as OFF:

SQL> SET VERIFY OFF

SQL> @d:\ora4pm\ReadDemo.sql
Enter value for x: 10
Enter value for y: 5
sum=15
sum of 10 and 5 is 15

ORACLE 4PM PLSQL Page 12


DECLARE x INT;
ASSIGN x := 20;
INITIALIZE x INT := 20;
PRINT dbms_output.put_line(x);
READ x := &x;

Using SQL commands in PL/SQL:

• DRL, DML, TCL commands can be used directly in


PL/SQL program.

• DDL, DCL commands cannot be used directly in


PL/SQL program.

• To use DDL & DCL commands in PL/SQL, we use


Dynamic SQL.

Syntax of SELECT command in PL/SQL:

SELECT <column_list> INTO <variable_list>


FROM <table_name>
WHERE <condition>;

Example: x y
SELECT ename, sal INTO x, y SMITH 800
FROM emp
WHERE empno=7369;

EMP
EMPNO ENAME SAL HIREDATE
7369 SMITH 800 ..
7499 ALLEN 1600 ..
7521 WARD 2500 ..

ORACLE 4PM PLSQL Page 13


SELECT ename, sal, hiredate INTO x, y, z
x y z
FROM emp
ALLEN 1600 ..
WHERE empno=7499;

Example:

Display the emp name and salary of given empno:

Read empno => 7499


SELECT ename and sal => copy into variables
Print emp name and sal

Program: v_empno v_ename v_sal


EMP
7499 ALLEN 1600
DECLARE EMPNO ENAME SAL HIREDATE
v_empno NUMBER(4); 7369 SMITH 800 ..
v_ename VARCHAR2(10); 7499 ALLEN 1600 ..
v_sal NUMBER(7,2); 7521 WARD 2500 ..
BEGIN
v_empno := &empno;

SELECT ename, sal INTO v_ename, v_sal


FROM emp WHERE empno=v_empno;

dbms_output.put_line(v_ename || ' ' || v_sal);


END;
/

Output:
enter …empno: 7499
ALLEN 1600

Variable Table Column

v_empno NUMBER(2) empno NUMBER(4)


ORACLE 4PM PLSQL Page 14
Variable Table Column

v_empno NUMBER(2) empno NUMBER(4)

field sizes are mismatching

Variable Table Column

v_empno DATE empno NUMBER(4)

data types are mismatching

%TYPE:

Syntax:

<variable> <table_name>.<column_name>%TYPE;

Examples:
EMP
v_empno EMP.EMPNO%TYPE;
--empno NUMBER(4)

"v_empno" variable data type will be taken as "emp"


table's "empno" column's data type.

• %TYPE is an Attribute Related Data Type.

• It is used to declare a variable with table column's


data type and field size.

• It avoids mismatch between variable field size &


column field size.

• It avoids mismatch between variable data type &


table column data type.

ORACLE 4PM PLSQL Page 15


Display the emp name, salary and hiredate
of given empno:

DECLARE
v_empno EMP.EMPNO%TYPE;
v_ename EMP.ENAME%TYPE;
v_sal EMP.SAL%TYPE;
v_hiredate EMP.HIREDATE%TYPE;
BEGIN
v_empno := &empno;

SELECT ename,sal,hiredate INTO v_ename,v_sal,v_hiredate


FROM emp WHERE empno=v_empno;

dbms_output.put_line(v_ename || ' ' || v_sal || ' ' || v_hiredate);


END;
/

%ROWTYPE:

Syntax:

<variable> <TABLE_NAME>%ROWTYPE;

Example:
r EMP%ROWTYPE;

EMPNO ENAME JOB SAL MGR COMM HIREDATE DEPTNO


7499 ALLEN SALESMAN 1600 .. .. .. 30

r.ename
r.sal r.deptno
SELECT * INTO r FROM emp WHERE empno=7499;

ORACLE 4PM PLSQL Page 16


DEPT
DEPTNO DNAME LOC r DEPT%ROWTYPE;
10 ACCOUNTS CHICAGO
20 .. .. r
30 .. ..
40 .. ..
DEPTNO DNAME LOC
10 ACCOUNTS CHICAGO
SELECT * INTO r
FROM dept
WHERE deptno=10; r.dname r.loc
r.deptno

• %ROWTYPE is an Attribute Related Data Type.

• It is used to hold entire row of a table.

• It can hold one row at a time.

• It decreases no of variables.

Example on %ROWTYPE:

Display the emp record of given empno:


r
v_empno
empno ename job sal mgr deptno comm hiredate
7369
7369 SMITH CLERK 800 .. .. .. ..

DECLARE
v_empno EMP.EMPNO%TYPE;
r EMP%ROWTYPE;
BEGIN
v_empno := &empno;

SELECT * INTO r FROM emp


WHERE empno=v_empno;

ORACLE 4PM PLSQL Page 17


dbms_output.put_line(r.ename || ' ' || r.sal || ' ' || r.hiredate);
END;
/

SELECT ename,sal INTO x,y


FROM emp
WHERE empno=7369;

%TYPE:
to declare a variable with table column's data type

Ex:
v_empno EMP.EMPNO%TYPE;

%ROWTYPE:
used to hold entire row

r EMP%ROWTYPE;

r.empno
r.ename

Note:
UPDATE, DELETE and INSERT commands syntaxes in
SQL and PL/SQL are same.

Using UPDAT command in PL/SQL:

Program to increase salary of given empno


with given amount:

enter …. empno: 7369


enter …. amount: 2000
salary updated

ORACLE 4PM PLSQL Page 18


Read empno => v_empno
Read amount => v_amount
UPDATE query
display message => salary updated

DECLARE
v_empno EMP.EMPNO%TYPE;
v_amount FLOAT;
BEGIN
v_empno := &empno;
v_amount := &amount;

UPDATE emp SET sal=sal+v_amount WHERE empno=v_empno;


COMMIT;

dbms_output.put_line('salary increased');
END;
/

Using DELETE command in PL/SQL:

Program to delete an emp record of given empno:

enter value for empno: 7934


record deleted

Read empno

DELETE command

display message => record deleted

DECLARE
v_empno EMP.EMPNO%TYPE;
BEGIN
v_empno := &empno;

ORACLE 4PM PLSQL Page 19


DELETE FROM emp WHERE empno=v_empno;
COMMIT;

dbms_output.put_line('record deleted');
END;
/

Using INSERT command in PL/SQL:

Program to insert record into student table:

STUDENT
sid sname m1

CREATE TABLE student


(
sid NUMBER(4),
sname VARCHAR2(10),
m1 NUMBER(3)
);

DECLARE
r STUDENT%ROWTYPE;
BEGIN
r.sid := &sid;
r.sname := '&sname';
r.m1 := &m1;

INSERT INTO student VALUES(r.sid, r.sname, r.m1);


COMMIT;

dbms_output.put_line('record inserted');
END;
/

Program to find experience of given empno:

ORACLE 4PM PLSQL Page 20


enter value for empno: 7369
7369 experience is: 42 years

enter value for empno: 7788


7788 experience is: 40 years

read empno => v_empno


SELECT hiredate copy into variable v_hiredate

v_Exp := trunc((sysdate-v_hiredate)/365)

display message:

DECLARE
v_empno EMP.EMPNO%TYPE;
v_hiredate DATE;
v_exp INT;
BEGIN
v_empno := &empno;

SELECT hiredate INTO v_hiredate FROM emp


WHERE empno=v_empno;

v_exp := TRUNC((sysdate-v_hiredate)/365);

dbms_output.put_line(v_empno || ' experience is:' ||


v_exp || ' years');
END;
/

Program to display weekday name of given date:

enter value for d: 15-AUG-1947


FRIDAY

enter value for d: 17-JUN-2023


SATURDAY

DECLARE
d DATE;
s STRING(10);
BEGIN
d := to_date('&date');
ORACLE 4PM PLSQL Page 21
d := to_date('&date');

s := to_char(d,'DAY');

dbms_output.put_line(s);
END;
/

DECLARE x FLOAT;
ASSIGN x := 12.34;
INTIALIZE x FLOAT := 12.34;
PRINT dbms_output.put_line(x);
READ x := &x;

SELECT ename,sal INTO x,y


FROM emp
WHERE empno=7369;

INSERT
UPDATE
DELETE

%type to declare a variable with table column type


ex: v_empno emp.empno%type; [Number(4)]
%rowtype to hold table row
ex: r emp%rowtype;
r.ename r.sal

ORACLE 4PM PLSQL Page 22


Control Structures
Saturday, June 17, 2023 5:17 PM

DECLARE DECLARE
m INT; m INT;
BEGIN BEGIN
m := 70; m := 70;

dbms_output.put_line('PASS'); IF m>=40 THEN


dbms_output.put_line('FAIL'); dbms_output.put_line('PASS');
END; ELSE
/ dbms_output.put_line('FAIL');
END IF;
Output: END;
PASS /
FAIL
Output:
PASS

Control Structure Goal => changing sequential execution

Control Structure:

• To change sequential execution, to transfer the control to


our desired location, we use Control Structure.

• Control Structure controls the flow of execution of


statements.

• Which statement executed when and how many times can


be controlled by Control Structure.

PL/SQL provides following Control Structures:

Conditional IF .. THEN
IF .. THEN .. ELSE
IF .. THEN .. ELSIF
NESTED IF
CASE

Looping WHILE
FOR
SIMPLE LOOP

Jumping GOTO
ORACLE 4PM PLSQL Page 23
Jumping GOTO
EXIT WHEN
EXIT
CONTINUE

Conditional Control Structures:

Conditional Control Structures execute the statements


based on conditions.

PL/SQL provide following conditional control structure:


• IF .. THEN
• IF .. THEN .. ELSE
• IF .. THEN .. ELSIF
• NESTED IF
• CASE

IF .. THEN:

Syntax:

IF <condition> THEN
--Statements
END IF;

• The statements in "IF .. THEN" get executed


when condition is TRUE.

Example:

Program to delete an emp record of given empno.


If experience is more than 41 then only delete emp record:

enter value for empno: 7788


experience is: 40

enter value for empno: 7369


ORACLE 4PM PLSQL Page 24
enter value for empno: 7369
experience is: 42
record deleted

DECLARE
v_empno EMP.EMPNO%TYPE;
v_hiredate DATE;
v_exp INT;
BEGIN
v_empno := &empno;

SELECT hiredate INTO v_hiredate FROM emp WHERE


empno=v_empno;

v_exp := TRUNC((sysdate-v_hiredate)/365);

dbms_output.put_line('experience is:' || v_exp);

IF v_exp>41 THEN
DELETE FROM emp WHERE empno=v_empno;
COMMIT;
dbms_output.put_line('record deleted');
END IF;
END;
/

IF .. THEN .. ELSE:

Syntax:

IF <condition> THEN
--Statements
ELSE
--Statements
END IF;

The statements in "IF .. THEN" get executed when the


condition is TRUE.

The statements in "ELSE" get executed when the


condition is FALSE.

ORACLE 4PM PLSQL Page 25


condition is FALSE.

Example on IF .. THEN .. ELSE:

Program to increase salary of given empno based on


job as following:
if job is manager then increase 20% on sal
otherwise, increase 10% on sal

read empno
select job => v_job

IFv_job='MANAGER' THEN
UPDATE => 20%
ELSE
UPDATE => 10%
END IF;

DECLARE
v_empno EMP.EMPNO%TYPE;
v_job EMP.JOB%TYPE;
v_per INT;
BEGIN v_empno v_job v_per
v_empno := &empno;
7902 ANALYST 10
SELECT job INTO v_job FROM emp WHERE
empno=v_empno;

IF v_job='MANAGER' THEN
v_per := 20;
ELSE
v_per := 10;
END IF;

UPDATE emp SET sal=sal+sal*v_per/100


WHERE empno=v_empno;
COMMIT;

dbms_output.put_line('Your job is:' || v_job);


dbms_output.put_line(v_per || '% on salary increased');
ORACLE 4PM PLSQL Page 26
dbms_output.put_line(v_per || '% on salary increased');
END;
/

Assignment:

Write a program to increase salary of given empno


with given amount. After increment, if salary is more than 10000
cancel it. otherwise, save it:

Read empno => v_empno


Read amount => v_amount

UPDATE emp SET sal=sal+v_amount WHERE empno=v_empno;


SELECT sal => v_sal

IF v_sal>10000 THEN
ROLLBACK;
dbms_output.put_line('Tansaction cancelled');
ELSE
COMMIT;
dbms_output.put_line('Tansaction successful');
END IF;

IF .. THEN .. ELSIF:

Syntax:

IF <condition-1> THEN
--Statements
ELSIF <condition-2> THEN
--Statements
.
.
[ELSE
--Statements]
END IF;

ORACLE 4PM PLSQL Page 27


Example on IF .. THEN .. ELSIF:

Program to increase salary of given empno based on job as


following:
If job is MANAGER then increase 20% on sal
If job is CLERK then increase 10% on sal
others => increase 5% on sal

read empno
select job => v_job

if v_job='MANAGER' THEN
v_per := 20;
elsif v_job='CLERK' THEN
v_per := 10;
else
v_per := 5;
END IF;

UPDATE salary
commit

display message => salary increased

Assignment:

Program to increase salary of given empno based on deptno


as following:
if emp working in deptno 10 then increase 10% on sal
if emp working in deptno 20 then increase 20% on sal
if emp working in deptno 30 then increase 15% on sal
other than 10, 20, 30 => increase 5% on sal

NESTED IF:
Writing 'IF' in another 'IF' is called 'Nested If'

Syntax:

IF <condition-1> THEN
IF <condition-2> THEN
inner
outer --Statements condition-1 => T
if
if END IF; condition-2 => T
END IF;

ORACLE 4PM PLSQL Page 28


inner
outer --Statements condition-1 => T
if
if END IF; condition-2 => T
END IF;

Program to calculate total, average and result of given student id.


max marks: 100
min marks: 40 in each sub for pass
in any subject, if marks are <40 => FAIL
if pass check average
if avrg is 60 or more => FIRST DIV
if avrg is b/w 50 to 59 => SECOND DIV
if avrg is b/w 40 to 49 => THIRD
calculate total, avrg and result snd store them in RESULT table.

STUDENT RESULT
SID SNAME M1 M2 M3 sid total avrg result
1 A 60 80 70 1 210 70 FIRST
2 B 50 30 90

enter … sid: 1
result stored in result table

CREATE TABLE student


(
sid NUMBER(4),
sname VARCHAR2(10),
m1 NUMBER(3),
m2 NUMBER(3),
m3 NUMBER(3)
);

INSERT INTO student


VALUES(1,'A',60,80,70);

INSERT INTO student


VALUES(2,'B',50,30,90);

COMMIT;

CREATE TABLE result


(
ORACLE 4PM PLSQL Page 29
(
sid NUMBER(4),
total NUMBER(3),
avrg NUMBER(5,2),
result VARCHAR2(10)
);

Program:

DECLARE
v_sid STUDENT.SID%TYPE;
r1 STUDENT%ROWTYPE;
r2 RESULT%ROWTYPE;
BEGIN
v_sid := &sid;

SELECT * INTO r1 FROm student WHERE sid=v_sid;

r2.total := r1.m1+r1.m2+r1.m3;

r2.avrg := r2.total/3;

IF r1.m1>=40 AND r1.m2>=40 and r1.m3>=40 THEN


IF r2.avrg>=60 THEN
r2.result := 'FIRST';
ELSIF r2.avrg>=50 THEN
r2.result := 'SECOND';
ELSE
r2.result := 'THIRD';
END IF;
ELSE
r2.result := 'FAIL';
END IF;

INSERT INTO result VALUES(v_sid, r2.total, r2.avrg, r2.result);


COMMIT;

dbms_output.put_line('result calculated and stored in result table');


END;
/

ORACLE 4PM PLSQL Page 30


CASE:

It can be used in 2 ways. They are:


• Simple CASE [same as switch in C]
• Searched CASE [same as if else if]

switch if else if
can check equality condn only can check any condition

switch(expression)
{
if(x>0)
case <constant-1>:
//STATEMENTS
break;
else if(x<0)
case <constant-2>:
//STATEMENTS
else if(x==0)
break;
.
.
default:
//Statements
}

Simple CASE:
It can check equality condition only

Syntax:

CASE <expression>
WHEN <constant-1> THEN
--Statements
WHEN <constant-2> THEN
--Statements
.
.
[ELSE
--Statements]
END CASE;

ORACLE 4PM PLSQL Page 31


Searched CASE:
It can check any condition

Syntax:

CASE
WHEN <condition-1> THEN
--Statements
WHEN <condition-2> THEN
--Statements
.
.
[ELSE
--Statements]
END CASE;

Example on Simple CASE:

Program to check whether the given number is even or


odd using Simple CASE:

2,4,6,8,….. EVEN divide with 2 Remainder 0


1,3,5,7,….. ODD divide with 2 Remainder 1

DECLARE
n INT := &n;
BEGIN
CASE mod(n,2)
WHEN 0 THEN
dbms_output.put_line('EVEN');
WHEN 1 THEN
dbms_output.put_line('ODD');
END CASE;
END;
/

Assignment:
program to increase salary of given empno based on
joining year:
if emp joined in 1980, increase 22.5% on sal
if emp joined in 1981, increase 13.5% on sal
ORACLE 4PM PLSQL Page 32
if emp joined in 1981, increase 13.5% on sal
if emp joined in 1982, increase 10.2% on sal
others, increase 8% on sal
do it using SIMPLE CASE

CASE to_char(hiredate,'YYYY')
WHEN 1980 THEN
v_per := 22.5;

.
.

Example on Searched CASE:

Program to check whether the given number is +ve or -ve


or zero using Searched CASE:

-infinite… -4 -3 -2 -1 0 1 2 3 4 5 …….. infinite

n=0
n>0
n<0
zero
positive
negative

DECLARE
n INT := &n;
BEGIN
CASE
WHEN n>0 THEN
dbms_output.put_line('positive');
WHEN n<0 THEN
dbms_output.put_line('negative');
WHEN n=0 THEN
dbms_output.put_line('zero');
END CASE;
END;
/

Assignment:

ORACLE 4PM PLSQL Page 33


Assignment:
Program to increase salary of given empno based on
current salary as following:
if sal is 10000 or more => increase 20% on sal
if sal is b/w 5000 to 9999 => increase 15.5% on sal
if sal is is <5000 => increase 5.3% on sal

CASE
WHEN sal>=10000 THEN
v_per := 20;
WHEN sal>=5000 THEN
v_per := 15.5;
WHEN sal<5000 THEN
v_per := 5.3;
END CASE;

UPDATE

Looping Control Structures:


Looping Control Structures are used to execute the
statements repeatedly.

100 hellos
100 times
d_o.p_l('hello'); hello
LOOP 100 times
d_o.p_l('hello'); hello
d_o.p_l('hello');
d_o.p_l('hello'); hello
END LOOP;
. .
. .
d_o.p_l('hello'); hello
d_o.p_l('hello'); hello
d_o.p_l('hello'); hello

PL/SQL provides following Looping Control


Structures:

• WHILE
• SIMPLE LOOP
• FOR

WHILE:

Syntax:
ORACLE 4PM PLSQL Page 34
Syntax:
In C:
WHILE <condition>
LOOP while(<condition>)
--Statements {
END LOOP; //Statements
}

The statements in WHILE loop get executed as


long as the condition is TRUE.
Loop will be terminated when the condition is
FALSE.

Example on WHILE:

Program to print numbers from 1 to 4:


i=1

i DECLARE
1 i INT;
2 BEGIN
3 i := 1;
4
. dbms_output.put_line(i); --1
. i:=i+1; --i=2
100
dbms_output.put_line(i); --2
i:=i+1; --i=3

dbms_output.put_line(i); --3
i:=i+1; --i=4

dbms_output.put_line(i); --4

END;
/

i
WHILE i<=4
1
LOOP
2
dbms_output.put_line(i);
ORACLE 4PM PLSQL Page 35
WHILE i<=4
1
LOOP
2
dbms_output.put_line(i);
3
i:=i+1;
4
LOOP;

i<=4

Program:

declare
i INT;
begin
i := 1;

WHILE i<=4
LOOP
dbms_output.put_line(i);
i := i+1;
END LOOP;
end;
/

Program to print 2023 calendar:

d1 d2
1-jan-2023 31-dec-2023

WHILE d1<=d2
LOOP
d_o.p_l(d1);
d1:=d1+1;
END LOOP

Program:

DECLARE
d1 DATE := '1-JAN-2023';
d2 DATE := '31-DEC-2023';
BEGIN

WHILE d1<=d2
ORACLE 4PM PLSQL Page 36
WHILE d1<=d2
LOOP
dbms_output.put_line(d1 || ' ' || to_char(d1,'DY'));
d1 := d1+1;
END LOOP:
END;
/

Program to print 2023 calendar. print sundays only:

DECLARE
d1 DATE := '1-JAN-2023';
d2 DATE := '31-DEC-2023';
BEGIN

WHILE d1<=d2
LOOP
IF to_char(d1,'DY') = 'SUN' THEN
dbms_output.put_line(d1 || ' ' || to_char(d1,'DY'));
END IF;
d1 := d1+1;
END LOOP;
END;
/

Simple Loop:

Syntax:

LOOP
--Statements
EXIT WHEN <condition>; [or] EXIT;
END LOOP;

Note:
EXIT WHEN / EXIT are same as "break" in C / Java.
ORACLE 4PM PLSQL Page 37
EXIT WHEN / EXIT are same as "break" in C / Java.

EXIT WHEN:
• it is used to terminate the loop in the middle of
execution
• It can be used in "LOOP" Only.

Syntax:
EXIT WHEN <condition>;

When condition is true, loop will be terminated

EXIT:
• it is used to terminate the loop in the middle of
execution.
• It can be used in "LOOP" Only.

Syntax:
EXIT;

BEGIN
dbms_output.put_line('HI');
EXIT;
dbms_output.put_line('BYE');
END;
/

ERROR: EXIT can be used in loop only

Program to demonstrate simple loop:

print numbers from 1 to 4 using simple loop:

i DECLARE
1 i INT;
2 BEGIN
3 i := 1;
4
LOOP
dbms_output.put_line(i);

ORACLE 4PM PLSQL Page 38


3
4
LOOP
dbms_output.put_line(i);
EXIT WHEN i=4; IF i=4 THEN
i:=i+1; EXIT;
END LOOP; END IF;
END;
/

FOR LOOP:

Syntax:

FOR <variable> IN [REVRSE] <lower> .. <upper>


LOOP
--Statements
END LOOP;

Example on for loop:

Program to print numbers from 1 to 4:

i
BEGIN
1 FOR i IN 1 .. 4
2 LOOP
3 dbms_output.put_line(i);
4 END LOOP;
END;
/

Note:

• We have no need to declare loop variable. It will be


declared implicitly as NUMBER type.

• loop variable is read-only variable.

Example:

BEGIN
FOR i IN 1 .. 10 Output:
ERROR:
ORACLE 4PM PLSQL Page 39
BEGIN
FOR i IN 1 .. 10 Output:
LOOP ERROR:
i := 5; "I" loop variable is read-only variable
dbms_output.put_line(i);
END LOOP;
END;
/

• Loop variable scope is limited to LOOP only.

Example:

BEGIN
FOR i IN 1 .. 5
LOOP
dbms_output.put_line(i);
END LOOP;
dbms_output.put_line(i); --ERROR: loop variable cannot be accessed out of loop
END;
/

• Always INCREMENT BY value [step value] is 1.


It will be increased implicitly.

Example:

BEGIN
FOR i IN 1 .. 20
LOOP
dbms_output.put_line(i);
i := i+2; --ERROR
END LOOP;
END;
/

Jumping Control Structures:

GOTO:

ORACLE 4PM PLSQL Page 40


GOTO:
It transfers the execution to Label

Syntax:

<<LABEL>>

//Statements executes statements repeatedly

GOTO LABEL;

Example on GOTO:

Program to print numbers from 1 to 4:

DECLARE
i
i INT := 1;
1 BEGIN
2
3 <<xyz>>
4 dbms_output.put_line(i);
i := i+1;
IF i<=4 THEN
GOTO xyz;
END IF;

END;
/

CONTINUE:
• It is used to skip current iteration and continue the next
iteration.
• CONTINUE can be used in LOOP only.

BEGIN
dbms_output.put_line('HI');
continue;
dbms_output.put_line('BYE');
END;

ORACLE 4PM PLSQL Page 41


END;
/

Output:
ERROR: Continue can be used in LOOP only

Example on Continue:

Program to print numbers from 1 to 10 except 7:

1 BEGIN
2 FOR i IN 1 .. 10
3 LOOP
4 IF i=7 THEN
5 continue;
6 END IF;
8 dbms_output.put_line(i);
9 END LOOP;
10 END;
/

ORACLE 4PM PLSQL Page 42


CURSORS
Thursday, June 22, 2023 5:15 PM

CURSOR:
v_empno EMP.EMPNO%TYPE;

emp r EMP%ROWTYPE;
empno ename sal
1001 A 5000 r
1002 B 7000
1003 C 6000 empno ename sal

%TYPE used to hold 1 column value


%ROWTYPE used to hold 1 row
CURSOR used to hold multiple rows

GOAL:
• used to hold multiple rows & process them one by one
CURSOR:
• CURSOR is a pointer to the memory location in ORACLE INSTANCE [RAM]. This
memory location has multiple rows.

• To hold multiple rows & process them one by one, we use CURSOR

• Every CURSOR is associated with a SELECT query

ORACLE DB SERVER

INSTANCE DB
PL/SQL 1
Program 2
SELECT ename,sal
c1 FROM emp ename sal emp
A 5000 dept
.
B 6000
.
4. C 7000
address gives to c1

RAM Hard Disk


3
copies selected data
into instance

ORACLE 4PM PLSQL Page 43


Steps to use CURSOR:

4 steps:

• DECLARE
• OPEN
• FETCH
• CLOSE

Declaring Cursor:

ename sal
Syntax:
SMITH 800
CURSOR <name> IS <SELECT query>; ALLEN 1600
WARD 2450

Example:
CURSOR c1 IS SELECT ename,sal FROM emp;

c1

When we declare the cursor,


• cursor variable will be created
• SELECT query will be identified

Opening Cursor:

Syntax:

OPEN <cursor_name>;

Example:
OPEN c1; ORACLE DB SERVER
2 goes to DB
Instance DB

PL/SQL program 1 ename sal


emp
SELECT ename,sal SMITH 800
c1
FROM emp ALLEN 1600
WARD 2450

` 4
memory location address
ORACLE 4PM PLSQL Page 44
ALLEN 1600
WARD 2450

` 4
memory location address RAM HARD DISK
will be given to c1
3
selects data & copies
into instance

When CURSOR is opened,


1. SELECT query will be submitted to ORACLE DB SERVER.
2. ORACLE goes to Database.
3. Selects the data & copies into INSTANCE [RAM]
4. This memory location address will be given to cursor variable.

c1 Instance
Fetching Record from Cursor:

Syntax: BFR

SMITH 800
FETCH <cursor_name> INTO <variable_list>;
ALLEN 1600
WARD 2450
ALR
Example:
FETCH c1 INTO v_ename, v_sal;
stop BFR => Before First Row
when ALR => After Last Row
fetch
is
unsuccessful

When FETCH statement is executed, it goes to next row.

By default, CURSOR points to BFR [Before First Row]


when FETCH is executed for 1st time, it goes to first row
when FETCH is executed for 2nd time, it goes to second row
.
.

NOTE:
One FETCH statement can fetch 1 row only.
To FETCH multiple rows write FETCH statement in LOOP.

ORACLE 4PM PLSQL Page 45


Closing Cursor:
Instance
Syntax:
c1

CLOSE <cursor_name>;
SMITH 800
ALLEN 1600
WARD 2450
Example:
CLOSE c1;

When CURSOR is Closed,


• The data in INSTANCE will be cleared
• Reference to memory location will be gone

DELCARE CURSOR c1 IS SELECT ename,sal FROM emp;

OPEN OPEN c1;

FETCH FETCH c1 INTO v_ename, v_sal;

CLOSE CLOSE c1;

Cursor Attributes:

Cursor Attributes are:

• %FOUND
• %NOTFOUND
• %ISOPEN
• %ROWCOUNT

Syntax to use cursor attribute:

<cursor_name><attribute_name>;
%FOUND %NOTFOUND %ROWCOUNT

Examples: 0
c1%FOUND
c1%NOTFOUND c1 Instance
c1%ISOPEN BFR
c1%ROWCOUNT
SMITH 800

ORACLE 4PM PLSQL Page 46


c1%NOTFOUND c1 Instance
c1%ISOPEN BFR
c1%ROWCOUNT
SMITH 800
ALLEN 1600

%FOUND: WARD 2450


• It returns boolean value.
• If record is found, it returns TRUE.
• If record is not found, it returns FALSE.

%NOTFOUND:
• It returns boolean value.
• If record is not found, it returns TRUE.
• If record is found, it returns FALSE.

%ISOPEN:
• it returns boolean value
• it is used to check whether the cursor is opened or not.
• if cursor is opened, it returns TRUE.
• if cursor is not opened, it returns FALSE.

%ROWCOUNT:
• it returns row number.
• its default value is 0.
• When fetch is successful, it will be incremented by 1.

Examples on CURSOR:

Display all emp names and salaries:

DECLARE
CURSOR c1 IS SELECT ename,sal FROM emp;
v_ename EMP.ENAME%TYPE;
Instance
v_sal EMP.SAL%TYPE; c1
BEGIN v_ename v_sal BFR
OPEN c1; SMITH 800
ALLEN 1600
LOOP
WARD 2450
FETCH c1 INTO v_ename, v_sal;
EXIT WHEN c1%NOTFOUND;
dbms_output.put_line(v_ename || ' ' || v_sal);
END LOOP;

dbms_output.put_line(c1%ROWCOUNT || ' rows selected');

CLOSE c1;
END;
/

ORACLE 4PM PLSQL Page 47


steps to use cursor:

Program to increase salary of all emps according to HIKE


table:

EMPLOYEE HIKE
empno ename sal empno per
1001 A 6000 1001 10
1002 B 5000 1002 20
1003 C 7000 1003 15

create table employee


(
empno int,
ename varchar(10),
sal numeric(8,2)
);

insert into employee values(1001,'A',6000);


insert into employee values(1002,'B',5000);
insert into employee values(1003,'C',7000);

create table hike


(
empno int,
per int
);

insert into hike values(1001,10);


insert into hike values(1002,20);
insert into hike values(1003,15);

commit;

Program:

DECLARE
CURSOR c1 IS SELECT * FROM hike; Instance
r HIKE%ROWTYPE; c1
r
BEGIN BFR
empno per
OPEN c1;
1003 15 1001 10

LOOP 1002 20
FETCH c1 INTO r; 1003 15
EXIT WHEN c1%notfound;
UPDATE employee SET sal=sal+sal*r.per/100 WHERE empno=r.empno;
END LOOP;
c1%notfound
COMMIT;

ORACLE 4PM PLSQL Page 48


UPDATE employee SET sal=sal+sal*r.per/100 WHERE empno=r.empno;
END LOOP;
c1%notfound
COMMIT;
FALSE
dbms_output.put_line(c1%rowcount || ' rows updated');
c1%rowcount
CLOSE c1;
END; 01 23
/

Program to find total, average and result of all students.

STUDENT
sid sname m1 m2 m3 RESULT
1001 A 50 80 70 sid total avrg result
1002 B 78 30 60

create table student


(
sid number(4),
sname varchar2(10),
m1 number(3),
m2 number(3),
m3 number(3)
);

create table result


(
sid number(4),
total number(3),
avrg number(5,2),
result varchar2(10)
);

insert into student values(1001,'A',50,80,70);


insert into student values(1002,'B',78,30,60);
commit;
RESULT
sid total avrg result
Program: 1001 200 66.66 PASS
1002 168 56 FAIL
DECLARE
CURSOR c1 IS SELECT * FROM student;
c1
r1 STUDENT%ROWTYPE;
r2 RESULT%ROWTYPE; Instance
BEGIN
OPEN c1;
1001 A 50 80 70

ORACLE 4PM PLSQL Page 49


r2 RESULT%ROWTYPE; Instance
BEGIN
OPEN c1;
1001 A 50 80 70

LOOP 1002 B 78 30 60
FETCH c1 INTO r1;
EXIT WHEN c1%NOTFOUND; TRUE

r1
r2.total := r1.m1+r1.m2+r1.m3;
sid sname m1 m2 m3
r2.avrg := r2.total/3; 1002 B 78 30 60

IF r1.m1>=40 AND r1.m2>=40 AND r1.m3>=40 THEN


r2
r2.result := 'PASS';
ELSE sid total avrg result
r2.result := 'FAIL'; 168 56 FAIL
END IF;

INSERT INTO result VALUES(r1.sid, r2.total, r2.avrg, r2.result);


END LOOP;

COMMIT;
dbms_output.put_line('result calculated and stored in result table');

CLOSE c1;

END;
/

Cursor For Loop:

Syntax: Simple For Loop:

FOR <variable> IN <cursor_name>


FOR <variable> IN <lower> .. <upper>
LOOP
LOOP
--Statements
--Statements
END LOOP;
END LOOP;

• If we use CURSOR FOR LOOP,


we have no need to open the cursor, fetch the record from
cursor and close the cursor. All these 3 actions will be done
implicitly.

• We have no need to declare cursor for loop variable.


implicitly, it will be declared as %rowtype variable.

Example Cursor For Loop:

ORACLE 4PM PLSQL Page 50


Display all emp names and salaries using Cursor For Loop:

DECLARE
CURSOR c1 IS SELECT ename,sal FROM emp;
BEGIN
FOR r IN c1
LOOP
dbms_output.put_line(r.ename || ' ' || r.sal);
END LOOP;
END;
/

Inline Cursor:
If SELECT query is specified in cursor for loop then it is
called "Inline Cursor".

Syntax:

FOR <variable> IN (<SELECT query>)


LOOP
--Statements
END LOOP;

Example on Inline Cursor:

BEGIN
FOR r IN (SELECT ename,sal FROM emp)
LOOP
dbms_output.put_line(r.ename || ' ' || r.sal);
END LOOP;
END;
/

Program to find sum of salaries of all emps:

v_sum
SAL v_sal
c1 0 5000 9000 15000
5000
4000
6000

v_Sum := v_Sum + v_sal

v_sum := 0 + 5000 = 5000


v_sum := 5000 + 4000 = 9000
v_sum := 9000 + 6000 = 15000

ORACLE 4PM PLSQL Page 51


v_sum := 0 + 5000 = 5000
v_sum := 5000 + 4000 = 9000
v_sum := 9000 + 6000 = 15000

print v_Sum

DECLARE
CURSOR c1 IS SELECT sal FROM emp;
v_sum FLOAT := 0;
v_sal EMP.SAL%TYPE;
BEGIN
OPEN c1;

LOOP
FETCH c1 INTO v_sal;
EXIT WHEN c1%NOTFOUND;
v_sum := v_sum + NVL(v_sal,0);
END LOOP;

dbms_output.put_line('sum=' || v_sum);

CLOSE c1;
END;
/

Assignment:
Find max salary in all emps using CURSOR:

v_max
v_sal
SAL
0 5000 6000
5000
c1
4000
6000 IF v_sal>v_max THEN
v_max := v_sal;
END IF;

PRINT v_max

ORACLE 4PM PLSQL Page 52


Find min salary in all emps using CURSOR:

Program to concatenate all emp names and separate


them using ,
s
v_ename
c1 SMITH SMITH,ALLEN,WARD,
ALLEN
WARD
s := s || v_ename || ','

s := '' || SMITH || ',' => SMITH,

s := SMITH, || ALLEN || , => SMITH,ALLEN,

s := SMITH,ALLEN, || WARD || , => SMITH,ALLEN,WARD,

dbms_output.put_line(RTRIM(s,','));

SMITH,ALLEN,WARD

DECLARE
CURSOR c1 IS SELECT ename FROM
emp;
s STRING(500) := '';
v_ename EMP.ENAME%TYPE;
BEGIN
OPEN c1;

LOOP
FETCH c1 INTO v_ename;
EXIT WHEN C1%NOTFOUND;
s:= s || v_ename || ',';
END LOOP;

dbms_output.put_line(RTRIM(s,','));

CLOSE c1;
END;
/

ORACLE 4PM PLSQL Page 53


LISTAGG():
• It is an Aggregate Function.
• Introduced in ORACLE 11g version.
• It is used concatenate the strings by using a separator.

Syntax:

LISTAGG(<column>,<delimiter>)
[WITHIN GROUP(ORDER BY <column> ASC/DESC)]

Examples on LISTAGG():
Concatenate all emp names by separate them using ,:

SELECT ListAgg(ename,',') FROM emp;

ename
---------
SMITH SMITH,ALLEN,WARD
ALLEN
WARD

Concatenate all emp names by separate them using ,. Concatenate


them in Alphabetical order:

SELECT ListAgg(ename,',') WITHIN GROUP(ORDER BY ename ASC)


FROM emp;

Concatenate all emp names by separate them using ,. Concatenate


them according to salary descending order:

SELECT ListAgg(ename,',') WITHIN GROUP(ORDER BY sal DESC)


FROM emp;

Display dept wise empnames. Concatenate dept wise emp names


by using separator ,:

deptno ename Output:


10 SMITH
10 ALLEN deptno enames
20 WARD 10 SMITH,ALLEN
20 MILLER 20 WARD,MILLER

SELECT deptno,
LISTAGG(ename,',') WITHIN GROUP(ORDER BY ename ASC)as enames
FROM emp
GROUP BY deptno;

ORACLE 4PM PLSQL Page 54


NOTE:
• To process any DRL command or DML command
cursor is required.

Parameterized Cursor:
• A cursor which is declared using parameter is called "Parameterized
Cursor".

• When we don't the exact value at the time of declaration,


we define parameter to capture that value.

• When we open cursor, we pass value to cursor parameter.

Syntax to declare parameterized cursor:


CURSOR <name>(<parameter_list>) IS <SELECT query>;

Example:
CURSOR c1(n NUMBER) IS SELECT * FROM emp
WHERE deptno=n;

Syntax to Open parameterized cursor:


OPEN <cursor_name>(<parameter_value_list>);

Ex:
OPEN c1(20);

Example on Parameterized Cursor:

Program to display specific dept emp records:

DECLARE
CURSOR c1(n NUMBER) IS SELECT * FROM emp
WHERE deptno=n;
r EMP%ROWTYPE;
BEGIN
OPEN c1(20);

LOOP
FETCH c1 INTO r;
EXIT WHEN C1%NOTFOUND;
dbms_output.put_line(r.ename || ' ' || r.sal || ' ' || r.deptno);
END LOOP;

ORACLE 4PM PLSQL Page 55


CLOSE c1;
END;
/

Finding sum of salaris of all emps using


Cursor For Loop:

DECLARE
CURSOR c1 IS SELECT sal FROM emp;
v_sum FLOAT := 0;
BEGIN

FOR r IN c1
LOOP
v_sum := v_sum + NVL(r.sal,0);
END LOOP;

dbms_output.put_line('sum=' || v_sum);

END;
/

Ref Cursor:

Simple Cursor Ref Cursor

Cursor c1 => EMP Cursor c1 => Emp


Cursor c2 => Dept => Dept
Cursor c3 => Salgrade => Salgrade

• In Simple Cursor, One CURSOR can be used for one SELECT query only.

• In Ref Cursor, one CURSOR can be used for multiple SELECT queries.

• It reduces number of CURSORS.

• In REF CURSOR, Select query will be specified at the time of opening


cursor.

To use Ref Cursor follow 4 steps:


Declaring Ref Cursor

ORACLE 4PM PLSQL Page 56


• Declaring Ref Cursor
• Opening Ref Cursor
• Fetching Record From Ref Cursor => same as simple cursor
• Closing Ref Cursor => same as simple cursor

Declaring Ref Cursor:

Syntax:

<cursor_name> SYS_REFCURSOR;

Example:
c1 SYS_REFCURSOR;

• SYS_REFCURSOR is a data type.


• It is used to declare Ref Cursor Variable.

Opening Ref Cursor:

Syntax:

OPEN <cursor_name> FOR <SELECT query>;

Example:
OPEN c1 FOR SELECT * FROM emp;
.
.
OPEN c1 FOR SELECT * FROM dept;

Steps Simple Cursor Ref Cursor


Declare CURSOR c1 IS SELECT * FROM emp; c1 SYS_REFCURSOR;
Open OPEN c1; OPEN c1 FOR SELECT * FROM emp;
Fetch FETCH c1 INTO r; FETCH c1 INTO r;
Close CLOSE c1 CLOSE c1;
OPEN c1 FOR SELECT * FROM dept;

Example on Ref Cursor:

Program to display all emp table records and dept table records:

DECLARE

ORACLE 4PM PLSQL Page 57


DECLARE
c1 SYS_REFCURSOR;
r1 EMP%ROWTYPE;
r2 DEPT%ROWTYPE;
BEGIN
OPEN c1 FOR SELECT * FROM emp;

Loop
FETCH c1 INTO r1;
EXIT WHEN c1%NOTFOUND;
dbms_output.put_line(r1.ename || ' ' || r1.sal);
End Loop;

CLOSE c1;

OPEN c1 FOR SELECT * FROM dept;

LOOP
FETCH c1 INTO r2;
EXIT WHEN c1%notfound;
dbms_output.put_line(r2.deptno || ' ' || r2.dname || ' ' || r2.loc);
END LOOP;

CLOSE c1;
END;
/

Differences between Simple Cursor and Ref Cursor:

ORACLE 4PM PLSQL Page 58


Simple Cursor Ref Cursor

• One Cursor can be used for • Same Cursor can be used for multiple
1 SELECT query only. SELECT queries.

• It is static. • It is Dynamic.
SELECT query is fixed SELECT query can be changed

• No data type is there • SYS_REFCURSOR data type is used for


REF CURSOR

• At the time of declaring cursor, • At the time of Opening Cursor, we


we specify SELECT query specify SELECT query

• It cannot be used as procedure • It can be used as Procedure Parameter


parameter. Because, it has
no data type

Types of Cursors:

2 Types:

• Implicit Cursor
• Explicit Cursor

Implicit Cursor:
• A cursor which is defined implicitly by ORACLE is called
"Implicit Cursor".
• To process any DRL command or DML command a Cursor
will be used implicitly.
• This Implicit Cursor name is: SQL

Example on Implicit Cursor:

BEGIN
UPDATE emp SET sal=sal+1000;
dbms_output.put_line(SQL%ROWCOUNT || ' rows updated');
END;
/

• Explicit Cursor:
A cursor which is defined explicitly by user is called

ORACLE 4PM PLSQL Page 59


• A cursor which is defined explicitly by user is called
"Explicit Cursor".

2 Types:
• Simple Cursor
• Ref Cursor

CURSOR:
GOAL: to hold multiple rows & process them one by one

4 steps:
DECLARE CURSOR c1 IS SELECT * FROM emp;
OPEN OPEN c1;
FETCH FETCH c1 INTO r;

it can fetch 1 record only


to fetch multiple records write this statement in loop

CLOSE CLOSE c1;

Cursor For Loop:


no need to open, fetch & close

Inline Cursor:
we specify select query in cursor for loop

Parameterized Cursor:
• A cursor which is declared with parameter
• At the time of opening cursor we pass value to cursor
parameter

Ref Cursor:
Same cursor can be used for multiple SELECT queries

Cursor Attributes:
%FOUND
%NOTFOUND
%ISOPEN
%ROWCOUNT

ORACLE 4PM PLSQL Page 60


Exception Handling
Tuesday, June 27, 2023 5:21 PM

Types of Errors:

3 Types:

• Compile Time Error


• Logical Error
• Run Time Error

Compile Time Error:


This error occur due to syntax mistakes

Examples:
missing ;
missing )
missing '

Logical Error:
• This error occur due to mistake in logic.
• Due to logic mistake, it gives wrong result.
• Programmer is responsible for writing correct logic.

Example:
withdraw
v_balance := v_balance + v_amount

50000 + 10000 = 60000

Program [100 lines]


Run Time Error:
• This error occur due to several reasons
…..
such as:
…….
○ when we try to divide with zero …….. 100/0 => RTE => 50th line
○ if record is not found ……
○ opening the opened cursor ………
○ fetching record without opening cursor
○ inserting duplicate value in PK
Problem:
Abnormal Termination will occur

Exception => Run Time Error


Problem:
abnormal termination

ORACLE 4PM PLSQL Page 61


Exception Handling:
• The way handling run time errors is called
"Exception handling".
• It avoids abnormal Termination.

• We add "EXCEPTION" block to handle Run


Time Error.

Syntax of Exception Of Handling:

DECLARE
--declare the variables
BEGIN
--executable statements

EXCEPTION
WHEN <exception_name> THEN
--Handling Code
WHEN <exception_name> THEN
--Handling Code
.
.
END;
/

Program to divide 2 numbers:

DECLARE
x NUMBER(4);
y NUMBER(4);
z NUMBER(4);
BEGIN
x := &x;
y := &y;

z := x/y;

dbms_output.put_line('quotient=' || z);

EXCEPTION
WHEN zero_divide THEN
dbms_output.put_line('you cannot divide with 0');
WHEN value_error THEN
dbms_output.put_line('wrong input or value out of range');
WHEN others THEN
dbms_output.put_line('Run Time Error Occurred');
ORACLE 4PM PLSQL Page 62
dbms_output.put_line('Run Time Error Occurred');
END;
/

Output:
enter value for x: 10
enter value for y: 2
quotinet=5

Output:
enter value for x: 10
enter value for y: 2
quotient=5

Output:
enter value for x: 10
enter value for y: 0
you cannot divide with 0

Output:
enter value for x: 123456
enter value for y: 2
wrong input or value out of range

Output:
enter value for x: 'raju'
enter value for y: 2
wrong input or value out of range

OTHERS:
It can handle any type of exception

Example On Others:

program to divide 2 numbers:

DECLARE
x NUMBER(4);
y NUMBER(4);
z NUMBER(4);
BEGIN
x := &x;
y := &y;

z := x/y;

dbms_output.put_line('quotient=' || z);

ORACLE 4PM PLSQL Page 63


EXCEPTION
WHEN others THEN
dbms_output.put_line('Run Time
Error Occured');
END;
/

Output:
enter value for x: 10
enter value for y: 2
quotient=5

Output:
enter value for x: 10
enter value for y: 0
Run Time Error Occured

Output:
enter value for x: 123456
enter value for y: 2
Run Time Error Occured

Output:
enter value for x: 'raju'
enter value for y: 2
Run Time Error Occured

Types of Exceptions:

2 Types:

• Built-In Exception / Predefined Exception


• User-Defined Exception

Built-In Exception / Predefined Exception:


• The Exception which is already defined by Oracle Developers is
called "Built-In Exception".
• These will be raised implicitly by ORACLE.

Examples:
zero_divide
value_error
no_data_found
dup_val_on_index
too_many_rows

ORACLE 4PM PLSQL Page 64


too_many_rows
cursor_already_open
invalid_cursor
invalid_number

User-Defined Exception:
• The exception which is defined by the user is called "User-
Defined Exception".
• We can define our exceptions. These are called "User-Defined
Exceptions".
• User-Defined Exception must be raised explicitly using RAISE
keyword.

Examples:
Sunday_Not_Allow
One_Divide
Invalid_Marks
xyz

Built-In Exceptions:

zero_divide:
When we try to divide with zero, zero_divide exception will
be raised.

Example:
z := 5/0; --raises zero_divide exception

value_error:
when we give wrong input or when value is out of range then
value_error exception will be raised.

Examples:
x NUMBER(4);

x := &x;
enter value for x: 123456 => value_error will be raised

x := &x;
enter value for x: 'raju' => value_error will be raised

No_Data_Found:

ORACLE 4PM PLSQL Page 65


No_Data_Found:
When we retrieve the record if record is not found in table
then NO_Data_Found Exception will be raised.

Example: emp
v_empno := &empno; empno ename
1001
enter value for empno:5678
1002
--No_Data_Found Exception will be raised
..
1010

Example on No_Data_Found:

Program to display emp record of given empno:

DECLARE
v_empno EMP.EMPNO%TYPE;
r EMP%ROWTYPE;
BEGIN
v_empno := &empno;

SELECT * INTO r FROM emp WHERE empno=v_empno;

dbms_output.put_line(r.ename || ' ' || r.sal);

EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line('employee not existed with this empno');
END;
/

Output:
enter value for empno: 7369
SMITH 3080

Output:
enter value for empno: 1234
employee not existed with this empno

Note:
When Run Time Error Occurs execution goes EXCEPTION block. It searches for
corresponding Exception Name.

ORACLE 4PM PLSQL Page 66


corresponding Exception Name.
If Exception Name is Found that handling code will be executed.

Dup_Val_On_Index:
When we try to insert duplicate value in Primary Key Column
then DUP_VAL_ON_INDEX excpetion will be raised.

Example On Dup_Val_On_Index:

CREATE TABLE student


(
sid NUMBER(4) PRIMARY KEY,
sname VARCHAR2(10)
);

Program to insert student record in STUDENT table:

DECLARE
r STUDENT%ROWTYPE;
BEGIN
r.sid := &sid;
r.sname := '&sname';

INSERT INTO student VALUES(r.sid, r.sname);


COMMIT;

dbms_output.put_line('record inserted');

EXCEPTION
WHEN dup_val_on_index THEN
dbms_output.put_line('PK does not accept duplicate
value');
END;
/

Output:
Enter value for sid: 10
Enter value for sname: AA
record inserted

Output:
Enter value for sid: 10
Enter value for sname: BB
PK does not accept duplicate value

ORACLE 4PM PLSQL Page 67


Too_Many_Rows:
• If Select Query returns multiple rows then
TOO_MANY_ROWS exception will be raised.

Example on TOO_MANY_ROWS:

program to display the emp record based on job:

Cursor_Already_Open:
If we try to open opened cursor then
CURSOR_ALREADY_OPEN exception will be raised

Example On Cursor_Already_Open:

Program display all emp names and salaries:

DECLARE
CURSOR c1 IS SELECT * FROM emp;
r EMP%ROWTYPE;
BEGIN
OPEN c1;

OPEN c1;

LOOP
FETCH c1 INTO r;
EXIT WHEN c1%notfound;
dbms_output.put_line(r.ename || ' ' || r.sal);
END LOOP;

CLOSE c1;

EXCEPTION
WHEN cursor_already_open THEN
dbms_output.put_line('cursor is already opened');
END;
/

Invalid_Cursor:
If we try to fetch the record without opening cursor then
Invalid_Cursor Exception will be raised.

Example on Invalid_Cursor:

DECLARE
CURSOR c1 IS SELECT * FROM emp;
r EMP%ROWTYPE;
BEGIN

ORACLE 4PM PLSQL Page 68


LOOP
FETCH c1 INTO r;
EXIT WHEN c1%notfound;
dbms_output.put_line(r.ename || ' ' || r.sal);
END LOOP;

CLOSE c1;

EXCEPTION
WHEN invalid_cursor THEN
dbms_output.put_line('cursor not opened');

END;
/

Invalid_Number:
When ORACLE is unable to convert string to number
then Invalid_Number Exception will be raised

Example on Invalid_Number:

CREATE TABLE student


(
sid NUMBER(4),
sname VARCHAr2(10),
m1 NUMBER(3)
);

BEGIN
INSERT INTO student VALUES(&sid, '&sname', &m1);
COMMIT;

dbms_output.put_line('record inserted');

EXCEPTION
WHEN invalid_number THEN
dbms_output.put_line('expecting number here');
END;
/

Output:
Enter value for sid: 101
Enter value for sname: AA
Enter value for m1: 55
record inserted

Output:
Enter value for sid: 102
Enter value for sname: BB
ORACLE 4PM PLSQL Page 69
Enter value for sname: BB
Enter value for m1: '90'
record inserted

Output:
Enter value for sid: 103
Enter value for sname: CC
Enter value for m1: 'ABC'
expecting number here

Defining User-Defined Exception:

To define user-define exception follow 3 steps. They are:


• Declare the Exception
• Raise the Exception
• Handle the Exception

Declare the Exception:

Syntax:

<exception_name> EXCEPTION;

Example:
one_divide EXCEPTION;

• EXCEPTION is the data type.


• It is used to declare Exception Name.

Raise the Exception:

Syntax:

RAISE <exception_name>;

Example:
RAISE one_divide;

• RAISE is the keyword


• RAISE keyword is used to raise the exception.
• When exception is raised, execution goes to EXCEPTION block.
• IN EXCEPTION block if it is handled executes Handling Code. If it is
not handled it gives error as "Unhandled User-Defined Exception"

ORACLE 4PM PLSQL Page 70


not handled it gives error as "Unhandled User-Defined Exception"

Handle the Exception:

Syntax:

EXCEPTION
WHEN <exception_name> THEN
--Handling Code

Example:
EXCEPTION
WHEN one_Divide THEN
dbms_output.put_line('denominator cannot be 1');

To handle the exception define EXCEPTION block.

Built-In Exception User-Defined exception


1 step: 3 steps:
Handling the Exception declare
raise
handle

Example on User-Defined Exception:

write a program to divide 2 numbers. if user is giving


denominator as 1 then raise the exception and handle it. if
user is giving denominator as 0 zero_divide exception will be
raised. Handle it:

DECLARE
x NUMBER(4);
y NUMBER(4);
z NUMBER(4);
one_divide EXCEPTION;
BEGIN
x := &x;
y := &y;

IF y=1 THEN

ORACLE 4PM PLSQL Page 71


IF y=1 THEN
RAISE one_divide;
END IF;

z := x/y;

dbms_output.put_line('result=' || z);

EXCEPTION
WHEN one_divide THEN
dbms_output.put_line('denominator cannot be 1');
WHEN zero_divide THEN
dbms_output.put_line('denominator cannot be 0');
END;
/

Output:
Enter value for x: 10
Enter value for y: 2
result=5

Output:
Enter value for x: 10
Enter value for y: 0
denominator cannot be 0

Output:
Enter value for x: 10
Enter value for y: 1
denominator cannot be 1

Example on User-defined Exception:

Program increase salary of given empno with given amount.


If user tries to update on Sunday then raise the exception
and handle it:

DECLARE
v_empno EMP.EMPNO%TYPE;
v_amount FLOAT;
sunday_not_allow EXCEPTION;
BEGIN
v_empno := &empno;
v_amount := &amount;

IF to_char(sysdate,'dy')='sun' THEN

ORACLE 4PM PLSQL Page 72


IF to_char(sysdate,'dy')='sun' THEN
RAISE sunday_not_allow;
END IF;

UPDATE emp SET sal=sal+v_amount WHERE


empno=v_empno;
COMMIT;

dbms_output.put_line('salary increased');

EXCEPTION
WHEN sunday_not_allow THEN
dbms_output.put_line('you cannot update on sunday');
END;
/

on working days [from Monday to Saturday]:


Output:
Enter value for empno: 7369
Enter value for amount: 1000
salary increased

on Sunday:
Output:
Enter value for empno: 7369
Enter value for amount: 1000
you cannot update on sunday

Note:
We can raise the error using 2 ways. They are:
• using RAISE keyword
• using RAISE_APPLICATION_ERROR() procedure

RAISE_APPLICATION_ERROR():
• RAISE_APPLICATION_ERROR() is a built-in procedure.
• It is used to raise the error with our own error code and our own error message.

Syntax:
RAISE_APPLICATION_ERROR(user_defined_error_code,
user_defined error_message);

user_defined_error_code ranges from -20000 to -20999

Example:
RAISE_APPLICATION_ERROR(-20050,'divisor cannot be 1');

ORACLE 4PM PLSQL Page 73


Output:
ERROR
ORA-20050: divisor cannot be 1

Example on Raise_Application_Error():

Program to increase salary of given empno with given amount.


If Sunday raise the error using raise_application_error():

DECLARE
v_empno EMP.EMPNO%TYPE;
v_amount FLOAT;
BEGIN
v_empno := &empno;
v_amount := &amount;

IF to_char(sysdate,'dy')='sun' THEN
RAISE_APPLICATION_ERROR(-20070,'you cannot update on sunday');
END IF;

UPDATE emp SET sal=sal+v_amount WHERE empno=v_empno;


COMMIT;

dbms_output.put_line('salary increased');

END;
/

On Sunday:

Output:
ERROR at line 1:
ORA-20070: you cannot update on sunday
ORA-06512: at line 9

Differences between RAISE & RAISE_APPLICATION_ERROR():

ORACLE 4PM PLSQL Page 74


RAISE RAISE_APPLICATION_ERROR()

• is a keyword • is a procedure

• It raises exception using • It raises exception using error code


name

Example: Example:
RAISE Sunday_not_allow; Raise_Application_Error(-20070,'you cannot update on sunday');

Note:
-1 Error Code
unique constraint violated Error Message
DUP_VAL_ON_INDEX Error Name

-1476 Error Code


divisor is equal to zero Error Message
ZERO_DIVIDE Error Name

-2290 Error Code


check constraint violated Error Message
NO ERROR NAME Defined for it Error Name

-1400 Error Code


cannot insert null Error message
NO ERROR NAME Defined for it Error Name

Pragma Exception_Init():

• Some errors have name. Some errors does not have name.
• TO define name for unnamed Exception, we use
PRAGMA EXCEPTION_INIT()

• To handle the Exception, name is required in EXCEPTION block. If name


is not there we cannot handle it. That's why we need to define a name
for unnamed exception.

Syntax:
PRAGMA EXCEPTION_INIT(<exception_name>, <error_code>)

ORACLE 4PM PLSQL Page 75


Example:

CREATE TABLE student


(
sid NUMBER(4) PRIMARY KEY,
sname VARCHAR2(10),
m1 NUMBER(3) CHECK(m1 BETWEEN 0 AND 100)
);

PRAGMA EXCEPTION_INIT(check_violate, -2290);


PRAGMA EXCEPTION_INIT() => is compiler directive

• Any statement started with PRAGMA is called Compiler


Directive [command].
• It is command to the compiler. PRAGMA tells that
before compiling the program execute this line

Example On Pragma Exception_init():

define name for check constraint violation and handle it:

DECLARE
r STUDENT%ROWTYPE;
check_violate EXCEPTION;
PRAGMA EXCEPTION_INIT(check_violate,-2290);
BEGIN
r.sid := &sid;
r.sname := '&sname';
r.m1 := &m1;

INSERT INTO student VALUES(r.sid, r.sname, r.m1);


COMMIT;

dbms_output.put_line('record inserted');

EXCEPTION
WHEN dup_val_on_index THEN
dbms_output.put_line('PK does not dup value');
WHEN check_violate THEN
dbms_output.put_line('check constraint violated');

END;
/

SQLERRM & SQLCODE:

ORACLE 4PM PLSQL Page 76


SQLERRM & SQLCODE:

SQLERRM SQLERRM function returns error message


SQLCODE SQLCODE function returns error code

Example on SQLERRM:

DECLARE
x NUMBER(4);
y NUMBER(4);
z NUMBER(4);
BEGIN
x := &x;
y := &y;

z := x/y;

dbms_output.put_line('result=' || z);

EXCEPTION
WHEN others THEN
dbms_output.put_line(SQLERRM);
END;
/

EXCEPTION Run Time Error


EXCEPTION HANDLING • The way of handling run time error
• Exception block is used to handle
the exception

Types of exceptions:

2 Types:
Built-In Exception already defined by oracle developers
these will be raised implicitly by oracle
Examples:
zero_divide
value_error
no_data_found
too_many_rows

ORACLE 4PM PLSQL Page 77


1 step:
Handle the exception
User-Defined exception we can define our own exception
we have to raise it explicitly

3 steps:
declare
raise
handle

Raise_Application_error():
• is a procedure
• used to raise the error with our own error code & message

Pragma Exception_Init():
some exceptions does not have name
to define name to unnamed exception, we use it

ORACLE 4PM PLSQL Page 78


Procedures
Friday, June 30, 2023 4:28 PM

PL/SQL Basics

Control Structures
Coding

Cursors

Exception handling

Coding has to be implemented in Procedures, Functions and Packages


concepts

Procedure:
• Procedure is a named block of statements that gets
executed on calling.

In C:
Example: Function:
dbms_output.put_line('HELLO'); --procedure call is a set of statements
gets executed on calling
dbms_output package
In Java:
put_line() procedure
Method:
is a set of statements
gets executed on calling
PROCEDURE put_line(STRING s) AS
BEGIN
--Statements
END;

Procedure:
• Procedure is a named block of statements that gets
executed on calling.
• Every Procedure is defined to perform specific action.

Examples:
Withdraw Procedure
Deposit Procedure
DELETE_EMP PROCEDURE

Types of Procedures:

ORACLE 4PM PLSQL Page 79


Types of Procedures:

2 Types:
• Stored Procedure
• Packaged Procedure

Stored Procedure:
A procedure which is defined in SCHEMA is called
"Stored Procedure / Stand Alone Procedure".
Note:
Example: Schema = user
SCHEMA c##batch4pm
PROCEDURE withdraw => Stored Procedure

Packaged Procedure:
A procedure which is defined in PACKAGE is called
"Packaged Procedure".

Example:
SCHEMA c##batch4pm
PACKAGE bank
PROCEDURE withdraw => Packaged Procedure

Syntax to define Stored Procedure:

CREATE [OR REPLACE] PROCEDURE <procedure_name>[(<paramter_list>)]


IS / AS
--declare the variables
BEGIN
--executable statements
END;
/

Example on Stored Procedure:


define a stored procedure to add 2 numbers:
Note: don't define sizes for parameters
addition(x NUMBER(4), y NUMBER(4)) => Invalid

CREATE OR REPLACE PROCEDURE


addition(x NUMBER, y NUMBER)
IS
z NUMBER(4);
BEGIN

ORACLE 4PM PLSQL Page 80


BEGIN
z := x+y;
dbms_output.put_line('sum=' || z);
END;
/

• Save above code in "D:" Drive, "ORA4PM" Folder


with the name "ProcedureDemo.sql".

• Compile the procedure as following: ORACLE DB

SQL> d:\ora4pm\ProcedureDemo.sql PROCEDURE addition


Output:
………
Procedure Created compiled code
………

When procedure is created,


procedure's compiled code will be stored in procedure.
This procedure will be stored in ORACLE DB.

Procedure is a Db Object.

Calling Stored Procedure:

3 ways:
• From SQL prompt
• From PL/SQL program [main program]
• From Front-End Application [Java, C#, Python]

From SQL prompt:

SQL> EXEC addition(2,3); --procedure call


Output:
sum=5

EXEC[UTE]:
EXEC command is used to call the procedure from SQL prompt.

From PL/SQL program [main program]:

DECLARE
a INT;
b INT;
BEGIN
a := &a;
b:=&b;

addition(a,b); --procedure call


ORACLE 4PM PLSQL Page 81
addition(a,b); --procedure call
END;
/

Note:
A procedure contains 2 parts. They are:
• Procedure Header
Formal Parameters
• Procedure Body
Procedure
CREATE OR REPLACE PROCEDURE Procedure Header
addition(x NUMBER, y NUMBER)
IS +
z NUMBER(4);
BEGIN Procedure Body
z := x+y;
dbms_output.put_line('sum=' || z);
END;
/

Procedure Call:
EXEC addition(2,3); --2,3 => Actual Parameters

Parameter:
• Parameter is a local variable that is declared in Procedure Header

Syntax to define parameter:

<parameter_name> [<parameter_mode>]<data_type>

parameter modes:
• IN [default]
• OUT
• IN/OUT

Formal Parameter & Actual Parameter:

Formal Parameter:
A parameter which is declared in procedure header is
called "Formal Parameter"

ORACLE 4PM PLSQL Page 82


called "Formal Parameter"

Actual Parameter:
A parameter which is in procedure call is called "Actual parameter"

Parameter Modes:

There are 3 parameter modes. They are:


• IN
• OUT
• IN OUT

IN:
• It is default one. If we don't specify parameter mode default mode
will be taken as IN.
• In Parameter can be also called input parameter.
• It captures input from out of procedure.
• It is used to bring value into procedure from out of procedure.
• In procedure call, it can be variable or constant.
• It is read-only parameter. We cannot change its value.

Example:
CREATE OR REPLACE PROCEDURE
addition(x IN NUMBER, y IN NUMBER)
IS
z NUMBER(4);
BEGIN
x := 100; --ERROR: x is read-only parameter
z := x+y;
dbms_output.put_line('sum=' || z);
END;
/

Output:
procedure created with compilation errors

SQL> show error


expression 'X' cannot be used as an assignment target

OUT:
• OUT keyword is used to declare OUT parameter.
• OUT parameter can be also called as Output Parameter.
• It is used to send the result out of the procedure.
• It is read-write parameter.
• In procedure call, it must be variable only. it cannot be constant

IN OUT:
• IN OUT keyword is used to declare it.
IN OUT parameter can be used to bring value into procedure and
ORACLE 4PM PLSQL Page 83
○ IN OUT parameter can be used to bring value into procedure and
same parameter can be used to the result out of procedure.
○ It is read-write parameter.
○ In procedure call, it must be variable only.

IN used to bring input into procedure from out of procedure


read-only parameter
in procedure call, it can be variable or constant
OUT used to send output to out of procedure
read -write parameter
in procedure call, it must be variable only

Example on OUT parameter:

Define a procedure to add 2 numbers and send the result


out of procedure:

CREATE OR REPLACE PROCEDURE


addition(x IN NUMBER, y IN NUMBER, z OUT NUMBER)
IS
BEGIN
z := x+y;
END;
/

Calling from SQL prompt:


SQL> variable a NUMBER
SQL> EXEC addition(5,4,:a);
SQL> PRINT a
Output:
a
--
9

In above example a is called Bind variable

Bind Variable:
○ A variable which is declared at SQL prompt is called
Bind variable.
○ Its lifetime is limited to session
○ To use bind variable we use bind operator : [colon]

Calling from PL/SQL program [main program]:

ORACLE 4PM PLSQL Page 84


Calling from PL/SQL program [main program]:

DECLARE
a NUMBER(4);
b NUMBER(4);
c NUMBER(4);
BEGIN
a := &a;
b := &b;

addition(a,b,c);

dbms_output.put_line('sum=' || c);
END;
/

Define a procedure to update salary of an employee with specific


amount:

CREATE OR REPLACE PROCEDURE


update_Salary(p_empno NUMBER, p_amount FLOAT)
IS
BEGIN
UPDATE emp SET sal=sal+p_amount WHERE empno=p_empno;
COMMIT;

dbms_output.put_line('salary increased');
END;
/

Calling procedure from SQL prompt:

SQL> EXEC update_salary(7369,2000);


Outtut:
Salary Increased

Assignment:
Define a procedure to delete an employee record

procedure call: delete_emp(7900);

Define a procedure to increase salary of an employee


with specific amount. Updated salary send out of the

ORACLE 4PM PLSQL Page 85


with specific amount. Updated salary send out of the
procedure:

CREATE OR REPLACE PROCEDURE


update_salary(p_empno IN NUMBER, p_amount IN FLOAT,
p_sal OUT NUMBER)
IS
BEGIN select experience(7369)
UPDATE emp SET sal=sal+p_amount WHERE
empno=p_empno; oracle 23c WINDOWS
COMMIT; se

dbms_output.put_line('salary increased');

SELECT sal INTO p_sal FROM emp WHERE


empno=p_empno;

END;
/

Calling procedure from SQL Prompt:

SQL> variable s number


SQL> EXEC update_salary(7499,1000,:s);
SQL> PRINT s
Output:
s
----
7000

ACCOUNT
AcNo Name Balance
1001 A 500000
1002 B 800000

CREATE TABLE account


(
acno NUMBER(4),
name VARCHAR2(10),
balance NUMBER(9,2)
);

ORACLE 4PM PLSQL Page 86


INSERT INTO account VALUES(1001,'A',500000);
INSERT INTO account VALUES(1002,'B',800000);
COMMIT;

Define a procedure to perform withdraw operation:

Procedure:

CREATE OR REPLACE PROCEDURE


withdraw(p_acno NUMBER, p_amount
NUMBER)
AS
v_balance account.balance%type;
BEGIN
SELECT balance INTO v_balance FROM
account WHERE acno=p_acno;

IF p_amount>v_balance THEN
RAISE_APPLICATION_ERROR(-20050,'
Insufficient Balance');
END IF;

UPDATE account SET balance=balance-


p_amount WHERE acno=p_acno;
COMMIT;

dbms_output.put_line('amount debited');
END;
/

Calling Procedure:

SQL> EXEC withdraw(1001,700000);


Output:
ORA-20050: Insufficient Balance

SQL> EXEC withdraw(1001,100000);


Output:
amount debited

ORACLE 4PM PLSQL Page 87


Define a procedure to perform deposit operation:

CREATE OR REPLACE PROCEDURE


deposit(p_acno NUMBER, p_amount NUMBER) AcNo Name Balance
AS
1001 A 500000
BEGIN
UPDATE account SET balance=balance+p_amount 1002 B 800000
WHERE acno=p_acno;
COMMIT;

dbms_output.put_line('amount credited');
END;
/

Calling procedure:

SQL> EXEC deposit(1002,100000);


Output:
amount credited

Define a procedure to perform deposit operation.


After depositing, updated balance send out of the procedure:

CREATE OR REPLACE PROCEDURE


ACCOUNT
deposit(p_acno IN NUMBER, p_amount IN NUMBER,
p_balance OUT NUMBER) ACNO NAME BALANCE
AS 1001 A 400000
BEGIN
UPDATE account SET balance=balance+ p_amount
WHERE acno=p_acno;
COMMIT;
dbms_output.put_line('transaction successful');
deposit(1001,200000,:b);
SELECT balance INTO p_balance FROM account
WHERE acno=p_acno;
END;
/

Calling procedure:

SQL> VARIABLE b NUMBER

SQL> EXEC deposit(1001,200000,:b);


transaction successful

PL/SQL procedure successfully completed.

SQL> print b

ORACLE 4PM PLSQL Page 88


SQL> print b

B
----------
600000

Assignment:
Define a procedure to transfer the funds from one account to another:

AcNo Name Balance


1001 A 500000 procedure call:
fund_transfer(1001,1002,100000);
1002 B 800000

CREATE OR REPLACE PROCEDURE


fund_transfer(p_from NUMBER, p_to NUMBER, p_amount NUMBER)
AS
check sufficient balance is there or not
if sufficient balance is not there raise the error

if sufficient balance is there

UPDATE from account balance=> 1001 => balance-p_amount


UPDATE to account balance => 1002 => balance+p_amount
COMMIT

display message => funds transferred

Example on IN OUT parameter:

Define a procedure to find square value. Take parameter as


IN OUT:

CREATE OR REPLACE PROCEDURE


square(x IN OUT NUMBER)
rewrites as
AS
BEGIN BEGIN
EXEC addition(5,2);
x := x*x; addition(5,2);
END; END;
/ a

Calling Procedure: 5 25
begin
:a := 5;
SQL> variable a number
end;
SQL> exec :a := 5;
SQL> exec square(:a);
begin
SQL> PRINT a
square(:a);
Output:
end;
ORACLE 4PM PLSQL Page 89
SQL> exec :a := 5;
SQL> exec square(:a);
begin
SQL> PRINT a
square(:a);
Output:
end;
a
---
25

Parameter mapping techniques / Parameter association techniques /


Parameter notations:

There are 3 parameter mapping techniques. They are:


• Positional mapping
• Named Mapping
• Mixed mapping

Positional Mapping:
In positional mapping, actual parameter will be mapped with
formal parameter based on position.

Example:

PROCEDURE addition(x INT, y INT, z INT)

positional mapping

procedure call: addition(10,20,30);

Named Mapping:
In named mapping, actual parameter will be mapped with
formal parameter based on name.
=> Association operator
Example:

PROCEDURE addition(x INT, y INT, z INT)

Named mapping

procedure call: addition(z=>10,x=>20,y=>30);

Mixed Mapping:
In mixed mapping, actual parameters will be mapped with

ORACLE 4PM PLSQL Page 90


Mixed Mapping:
In mixed mapping, actual parameters will be mapped with
formal parameters based on positions and names.

Example:

PROCEDURE addition(x INT, y INT, z INT)

positional named

procedure call: addition(10,z=>20,y=>30);

procedure call: addition(z=>10,20,30);


--ERROR: after named mapping we cannot give positional mapping

Example:

CREATE OR REPLACE PROCEDURE


addition(x INT, y INT, z INT)
AS
BEGIN
dbms_output.put_line('sum=' || (x+y+z));
dbms_output.put_line('x=' || x);
dbms_output.put_line('y=' || y);
dbms_output.put_line('z=' || z);
END;
/

procedure calls:

SQL> EXEC addition(10,20,30);


sum=60
x=10
y=20
z=30

SQL> EXEC addition(z=>10,x=>20,y=>30);


sum=60
x=20
y=30
z=10

SQL> EXEC addition(z=>10,20,30);


BEGIN addition(z=>10,20,30); END;

*
ERROR at line 1:

ORACLE 4PM PLSQL Page 91


ERROR at line 1:
ORA-06550: line 1, column 22:
PLS-00312: a positional parameter association may not follow a
named association
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored

SQL> EXEC addition(10,z=>20,y=>30);


sum=60
x=10
y=30
z=20

Pragma Autonomous_Transaction:

Main Program
Procedure update_salary

BEGIN TRANSACTION T1 UPDATE => 7369,2000


UPDATE => 7499,1000 ROLLBACK; --cancels T1 Transaction
update_salary(7369,2000);
commit; --saves T1
END TRANSACTION T1

EMP
0 salaries are updated EMPNO ENAME SAL
7369 SMITH 5000
Rollback cancels Procedure action and main 7499 ALLEN 3000
action. Because, the transaction started in main
program applied for procedure

• By default, A Transaction started in main program will be


applied for procedure also.
• A separated transaction will not be created for procedure
by default.
• To create separate transaction for procedure, we use
"PRAGMA AUTONOMOUS_TRANSACTION".

Main Program
Procedure update_salary

BEGIN TRANSACTION T1 BEGIN TRANSACTION T2


UPDATE => 7499,1000 PRAGMA AUTONOMOUS_TRANSACTION
update_salary(7369,2000); UPDATE => 7369,2000
commit; --saves T1 ROLLBACK; --cancels T2 Transaction
END TRANSACTION T1 END TRANSACTION T2
ORACLE 4PM PLSQL Page 92
UPDATE => 7499,1000 PRAGMA AUTONOMOUS_TRANSACTION
update_salary(7369,2000); UPDATE => 7369,2000
commit; --saves T1 ROLLBACK; --cancels T2 Transaction
END TRANSACTION T1 END TRANSACTION T2

EMP
EMPNO ENAME SAL
1 salary updated 7369 SMITH 5000
7499 ALLEN 3000 4000

Example on Pragma Autonomous_Transaction:

Define a procedure to update salary of an employee with specific


amount:

CREATE OR REPLACE PROCEDURE


update_salary(p_empno NUMBER, p_amount NUMBER)
AS
BEGIN
UPDATE emp SET sal=sal+p_amount WHERE empno=p_empno;
ROLLBACK;
END;
/

main program:

BEGIN
UPDATE emp SET sal=sal+1000 WHERE empno=7499;
update_salary(7369,2000);
COMMIT;
END;
/

In the above program, transaction started in main program


applied for procedure also.

procedure's ROLLBACK is canceling procedure updation [7369]


and main updation [7499].

If we want to create a separate transaction for procedure use


PRAGMA AUTONOMOUS_TRANSACTION

Define a procedure to update salary of an employee with specific


amount. create a separate for procedure:

CREATE OR REPLACE PROCEDURE


update_salary(p_empno NUMBER, p_amount NUMBER)

ORACLE 4PM PLSQL Page 93


update_salary(p_empno NUMBER, p_amount NUMBER)
AS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
UPDATE emp SET sal=sal+p_amount WHERE empno=p_empno;
ROLLBACK;
END;
/

Pragma compiler directive


directive => command
it is command to compiler
it tells before compiling program execute this line

main program:

BEGIN
UPDATE emp SET sal=sal+1000 WHERE empno=7499;
update_salary(7369,2000);
COMMIT;
END;
/

In the above example, a separate will be created for procedure.


ROLLBACK in procedure cancels only procedure actions.

Dropping a procedure:

Syntax:
DROP PROCEDURE <procedure_name>;

Example:
DROP PROCEDURE update_salary;

Granting permission to other user to call our procedure:

c##batch4pm:

create procedure as follows:

CREATE OR REPLACE PROCEDURE


update_salary(p_empno NUMBER, p_amount NUMBER)
ORACLE 4PM PLSQL Page 94
update_salary(p_empno NUMBER, p_amount NUMBER)
AS
BEGIN
UPDATE emp SET sal=sal+p_amount WHERE empno=p_empno;
COMMIT;
dbms_output.put_line('salary increased');
END;
/

PROCEDURE update_salary
EXEC update_salary(7369,2000); --procedure call

GRANT execute ON update_salary TO c##batch8pm;

c##batch8pm
EXEC c##batch4pm.update_salary(7499,1000);
--ERROR: no permission

EXEC c##batch4pm.update_salary(7499,1000);
Output:
salary increased

user_procedures:
• it is a system table / predefined table / readymade table.
• It maintains all procedures, functions, packages and triggers
information

DESC user_procedures;

SELECT object_name, object_type FROM user_procedures;

user_source:
• It is a system table / readymade table.
• It maintains all procedures, functions, packages and
triggers information

DESC user_source;

to see procedures list:

SELECT DISTINCT NAME, TYPE FROM user_source;

to see procedure's code:

ORACLE 4PM PLSQL Page 95


SELECT LINE, TEXT FROM user_source
WHERE name='UPDATE_SALARY';

Note:
Within the Schema procedure name must be unique

CREATE PROCEDURE • it creates new procedure


demo • if procedure name already used it gives
error

CREATE OR REPLACE • if procedure is not created it creates new


PROCEDURE demo procedure.
• if procedure already created with this
name previous code will be replaced with
new code

Note:
To perform DML operation, define PROCEDURE.

Advantages of Procedure:
• improves the performance. It holds compiled code
• provides reusability
• reduces length of code
• provides security. authorized users only call the procedure
• better maintenance

ORACLE 4PM PLSQL Page 96


Stored Functions
Wednesday, July 5, 2023 4:15 PM

Note:
• Procedure may or may not return the value.
• Returning value is optional in procedure.
• To return value in procedure, we use OUT parameter.
• A procedure can return multiple values.

Function:
• Function is a named block of statements that gets executed on calling.

• Function returns the value. Here, returning value is mandatory.

• A Function can return one value only.

• To perform fetch [select] operations or calculations define FUNCTION


whereas to perform DML operations define PROCEDURE.

• Don't define a function to perform DML operation.

• Always use IN parameters only in FUNCTION.


Don't use OUT or IN PUT parameters in FUNCTION.

Examples:
Opening_Account => INSERT => PROCEDURE
Withdraw => UPDATE => PROCEDURE
Deposit => UPDATE => PROCEDURE
Closing_Account => DELETE => PROCEDURE

Check_Balance => SELECT => FUNCTION


experience => Calculation => FUNCTION

Types of Functions:

2 Types:

ORACLE 4PM PLSQL Page 97


• Stored Function
• Packaged Function

Stored Function:
• A function which is defined in SCHEMA is called "Stored Function".

Example:
SCHEMA c##batch4pm
FUNCTION check_balance => Stored Function

Packaged Function:
• A function which is defined in PACKAGE is called "Packaged Function".

Example:
SCHEMA c##batch4pm
PACKAGE bank
FUNCTION check_balance => Packaged Function

Syntax of defining stored function:

CREATE [OR REPLACE] FUNCTION


<name>(<parameter_list>) RETURN <type>
IS / AS
--declare the variables
BEGIN
--executable statements
RETURN <expression>;
END;
/

Example on defining stored function:

Define a function to multiply 2 numbers:

CREATE OR REPLACE FUNCTION


ORACLE 4PM PLSQL Page 98
CREATE OR REPLACE FUNCTION
product(x INT, y INT) RETURN INT
AS
z INT;
BEGIN
z := x*y;
RETURN z;
END;
/

Save above function in D: Drive, ORA4PM folder with the file


name "FunctionDemo.sql".

Open sqlplus

Oracle DB
compile the function as following:
SQL> @d:\ora4pm\FunctionDemo.sql
Function Product
Output:
Function created ……….
………..
compiled code

Calling a Function:

A function can be called in 3 ways:


• From SQL prompt
• From PL/SQL program [main program]
• From Front-End Application [Java, C#, Python]

From SQL prompt:

SQL> SELECT product(5,4) FROM dual;

Output:
20

From PL/SQL program:

DECLARE

ORACLE 4PM PLSQL Page 99


DECLARE
a INT;
b INT;
c INT;
BEGIN
a := &a;
b := &b;

c := product(a,b); --function call

dbms_output.put_line('product=' || c);
END;
/

Define a Function to check the balance of specific account:

ACCOUNT
ACNO NAME BALANCE
1001 A 600000
1002 B 900000

Check_balance(1001) => 600000

CREATE OR REPLACE FUNCTION


check_balance(p_acno NUMBER) RETURN NUMBER
AS
v_balance ACCOUNT.BALANCE%TYPE;
BEGIN
SELECT balance INTO v_balance FROM account WHERE
acno=p_acno;

RETURN v_balance;
END;
/

Calling Function:

SQL> SELECT check_balance(1002) FROM dual;

ORACLE 4PM PLSQL Page 100


Output:

CHECK_BALANCE(1002)
-------------------
900000

Define a Function to calculate experience of specific employee:

CREATE OR REPLACE FUNCTION


experience(p_empno NUMBER) RETURN NUMBER
AS
v_hiredate DATE;
BEGIN
SELECT hiredate INTO v_hiredate FROM emp WHERE
empno=p_empno;

RETURN TRUNC((sysdate-v_hiredate)/365);
END;
/

Calling Function:

SQL> SELECT experience(7900) FROM dual;

Output:

EXPERIENCE(7900)
----------------
41

SQL> SELECT empno,ename,sal,


experience(empno) as experience FROM emp;

Output:
empno ename sal experience
----------- ------------ ------- -------------------
7369 42
7499 42

Define a function to display emps of specific dept:

ORACLE 4PM PLSQL Page 101


Define a function to display emps of specific dept:

CREATE OR REPLACE FUNCTION


getdept(p_deptno NUMBER) RETURN sys_refcursor
AS
c1 SYS_REFCURSOR;
BEGIN
OPEN c1 FOR SELECT * FROM emp WHERE
deptno=p_deptno;

RETURN c1;
END;
/

Calling Function:

SQL> SELECT getdept(20) FROM dual;

Output:
--displays 20th dept emp records

Define a function to display topn salaried emp records:

CREATE OR REPLACE FUNCTION


topn(n INT) RETURN sys_refcursor
AS
c1 sys_refcursor;
BEGIN
OPEN c1 FOR SELECT * FROM (SELECT empno,ename,sal,
dense_rank() over(order by sal desc) as rank from emp)
where rank<=n;

RETURN c1;
END;
/

Calling Function:

SQL> SELECT topn(3) FROM dual;

Output:
--displays top 3 salaried emp records

ORACLE 4PM PLSQL Page 102


Differences between Procedure & Function:

Procedure Function

Procedure may or may not Function must return a value


return a value

Returning value is optional Returning value is mandatory

It can return multiple values It can return 1 value only

OUT parameter is used to return the RETURN keyword is used to return the
value value

To perform DML operations To perform fetch operations or


define PROCEDURE calculations define FUNCTION

It cannot be called from SQL It can be called from SQL command


command like SELECT, UPDATE like SELECT, UPDATE

EXEC command can be used to EXEC command cannot be used to call


call procedure function

Example: Withdraw() Example: Check_Balance()

Can we perform DML operations using FUNCTION?

Yes. It is not recommended. Because,

If we perform DML operation in FUNCTION it cannot be called


ORACLE 4PM PLSQL Page 103
If we perform DML operation in FUNCTION it cannot be called
from SQL command like SELECT, UPDATE. We can call it from
PL/SQL program.

CREATE OR REPLACE FUNCTION


demo RETURN INT
AS
BEGIN
UPDATE emp SET sal=sal+1000;
COMMIT;
RETURN 5;
END;
/

SQL> SELECT demo FROM dual;


SELECT demo FROM dual
*
ERROR at line 1:
ORA-14551: cannot perform a DML operation inside a query
ORA-06512: at "C##BATCH4PM.DEMO", line 5

Can we define OUT parameters in FUNCTION?

Yes. But, it is not recommended.

Function standard is:


Function must return 1 value only

If we take OUT parameters in FUNCTION,


FUNCTION meaning will be changed.

If we take OUT parameters in FUNCTION, it cannot called from


SELECT command

Dropping Function:

Syntax:
DROP FUNCTION <name>;

ORACLE 4PM PLSQL Page 104


DROP FUNCTION <name>;

Example:
DROP FUNCTION product;

user_procedures:
It maintans all procedures, functions, packages and triggers
information

to see list of procedures and functions:

COLUMN object_name FORMAT a15

SELECT object_name, object_type FROM user_procedures;

user_source:
It maintans all procedures, functions, packages and triggers
information

to see list of procedures and functions:

SELECT DISTINCT name, type FROM user_source;

to see function code:

SELECT TEXT FROM user_source


WHERE name='EXPERIENCE';

A procedure or Function can be also called sub program.

Advantages of sub program:

• provides reusability.
• reduces length of code.
• security.
• improves the performance.
• Better Maintenance.

ORACLE 4PM PLSQL Page 105


ORACLE 4PM PLSQL Page 106
PACKAGES
Thursday, July 6, 2023 4:55 PM

PACKAGE:
• PACKAGE is a Database Object.
• PACKAGE is a collection of procedures, functions
and variables … etc.

Example:

PACKAGE bank

PROCEDURE opening_account => INSERT


PROCEDURE withdraw => UPDATE
PROCEDURE deposit => UPDATE
PROCEDURE closing_account => DELETE

FUNCTION check_balance => SELECT


FUNCTION transaction_statement => SELECT

Creating a Package:

To create the package follow 2 steps:

• Define PACKAGE SPECIFICATION


• Define PACKAGE BODY

Defining PACKAGE SPECIFICATION:

• In this, we declare procedures, functions and global variables

• Defining package specification means, we are making


members as public.

Syntax of Package Specification:

ORACLE 4PM PLSQL Page 107


Syntax of Package Specification:

CREATE [OR REPLACE] PACKAGE <name>


IS / AS
--declare the procedures
--declare the functions
--declare the global variables
END;
/

Defining PACKAGE BODY:


In this, we define body of procedures and functions.

Syntax to define Package Body:

CREATE [OR REPLACE] PACKAGE BODY <name>


IS / AS
--define the procedures
--define the functions
END;
/

Example on creating package:

PACKAGE math

PROCEDURE addition
FUNCTION product

Defining Package specification:

CREATE OR REPLACE PACKAGE math


AS
PROCEDURE addition(x INT, y INT);

ORACLE 4PM PLSQL Page 108


PROCEDURE addition(x INT, y INT);
FUNCTION product(x INT, y INT) RETURN INT;
END;
/

Defining Package Body:

CREATE OR REPLACE PACKAGE BODY math


AS
PROCEDURE addition(x INT, y INT)
AS
BEGIN
dbms_output.put_line('sum=' || (x+y));
END addition;

FUNCTION product(x INT, y INT) RETURN INT


AS
BEGIN
RETURN x*y;
END product;
END;
/

Calling Packaged procedure:

SQL> EXEC math.addition(5,4);

Calling Packaged Function:

SQL> SELECT math.product(2,3) FROM dual;

Define a package as following:

ORACLE 4PM PLSQL Page 109


PACKAGE HR

PROCEDURE insert_emp
PROCEDURE update_salary
PROCEDURE delete_emp

FUNCTION experience

Defining Package specification:

CREATE OR REPLACE PACKAGE hr


AS
PROCEDURE insert_emp(p_empno NUMBER, p_ename VARCHAR2);
PROCEDURE update_Salary(p_empno NUMBER, p_amount NUMBER);
PROCEDURE delete_emp(p_empno NUMBER);

FUNCTION experience(p_empno NUMBER) RETURN NUMBER;


END;
/

Defining Package Body:

CREATE OR REPLACE PACKAGE BODY hr


AS
PROCEDURE insert_emp(p_empno NUMBER, p_ename VARCHAR2)
AS
BEGIN
INSERT INTO emp(empno,ename) VALUES(p_empno,p_ename);
COMMIT;
dbms_output.put_line('emp record inserted');
END insert_emp;

PROCEDURE update_Salary(p_empno NUMBER, p_amount NUMBER)


AS
BEGIN
UPDATE emp SET sal=sal+p_amount WHERE empno=p_empno;
ORACLE 4PM PLSQL Page 110
UPDATE emp SET sal=sal+p_amount WHERE empno=p_empno;
COMMIT;
dbms_output.put_line('salary updated');
END update_Salary;

PROCEDURE delete_emp(p_empno NUMBER)


AS
BEGIN
DELETE FROM emp WHERE empno=p_empno;
COMMIT;
dbms_output.put_line('emp record deleted');
END delete_emp;

FUNCTION experience(p_empno NUMBER) RETURN NUMBER


AS
v_hiredate DATE;
BEGIN
SELECT hiredate INTO v_hiredate FROM emp WHERE
empno=p_empno;

RETURN TRUNC((sysdate-v_hiredate)/365);
END experience;
END;
/

Calling packaged procedures and functions:

SQL> EXEC hr.insert_emp(1001,'A');


Output:
emp record inserted

SQL> EXEC hr.update_Salary(7902,2000);


Output:
salary updated

SQL> EXEC hr.delete_emp(1001);


Output:
emp record deleted

ORACLE 4PM PLSQL Page 111


SQL> SELECT hr.experience(7902) FROM dual;

HR.EXPERIENCE(7902)
-------------------
41

Assignment:

Define following package:

PACKAGE bank

PROCEDURE opening_account => INSERT


PROCEDURE withdraw => UPDATE
PROCEDURE deposit => UPDATE
PROCEDURE closing_account => DELETE

FUNCTION check_balance => SELECT

Advantages of Packages:

• We can group related procedures and functions


• provides reusability
• improves the performance
• we can make members as private or public
• we can declare global variables
• Packaged procedures or Packaged functions can be overloaded

Note:
• Stored procedures or Stored Functions cannot be overloaded
Packaged procedure or Packaged Function can be overloaded
ORACLE 4PM PLSQL Page 112
• Packaged procedure or Packaged Function can be overloaded

Function Overloading:
• Defining multiple functions with same name and different
signature is called "Function Overloading".

• Different signature means,


○ change in no of parameters
○ change in data types
○ change in order of parameters

Examples:
change in no of parameters:
Function f1(x INT, y INT)
FUNCTION f1(x INT, y INT, z INT)

change in data types:


FUNCTION f1(x INT, y VARCHAR2)
FUNCTION f1(x DATE, y CHAR)

change in order of parameters:


FUNCTION f1(x INT, y VARCHAR2)
FUNCTION f1(x VARCHAR2,y INT)

Example on Overloading:

PACKAGE mymath

FUNCTION addition(x INT, y INT)


FUNCTION addition(x INT, y INT, z INT)

Package Specification:

ORACLE 4PM PLSQL Page 113


CREATE OR REPLACE PACKAGE mymath
AS
x INT := 500;
FUNCTION addition(x INT, y INT) RETURN INT;
FUNCTION addition(x INT, y INT, z INT) RETURN INT;
END;
/

Package Body:

CREATE OR REPLACE PACKAGE BODY mymath


AS
FUNCTION addition(x INT, y INT) RETURN INT
AS
BEGIN
RETURN x+y;
END addition;

FUNCTION addition(x INT, y INT, z INT) RETURN INT


AS
BEGIN
RETURN x+y+z;
END addition;
END;
/

Calling overloaded functions:

SQL> SELECT mymath.addition(2,3) FROM dual;

MYMATH.ADDITION(2,3)
--------------------
5

SQL> SELECT mymath.addition(1,2,3) FROM dual;

MYMATH.ADDITION(1,2,3)
----------------------
6

ORACLE 4PM PLSQL Page 114


SQL> EXEC dbms_output.put_line(mymath.x);
500

DECLARE
a INT;
b INT;
BEGIN
a := &a;

b := mymath.x + a;

dbms_output.put_line('sum=' || b);
END;
/

Dropping package:

DROP PACKAGE <name>;

Example:

DROP PACKAGE mymath;

user_procedures:

to see package list:

SELECT object_name,procedure_name,object_type
FROM user_procedures
WHERE object_type='PACKAGE';

user_source:

ORACLE 4PM PLSQL Page 115


to see package list:

SELECT DISTINCT name FROM user_source


WHERE type='PACKAGE';

to see package code:

SELECT text FROM user_source


WHERE name='HR';

ORACLE 4PM PLSQL Page 116


Friday, July 7, 2023 4:22 PM

ORACLE DB SEREVR

Instance DB 20 times

call p1 p1,p2,…..p10

f1,f2,…..f10
call p2

10 stored procedures
10 stored functions

Instance DB 1 time

demo.p1 PACKAGE DEMO


p1,p2,, ….., p10
f1, f2, ….., f10
demo.p2

p1, p2, p10


f1, f2, f10

PACKAGE SPECIFICATION
DEMO PACKAGE BODY DEMO

ORACLE 4PM PLSQL Page 117


PROCEDURE p2 PROCEDURE p1
PROCEDURE p2

PROCEDURE p1 private => with in package body only


PROCEDURE p2 public => with in SCHEMA

ORACLE 4PM PLSQL Page 118


TRIGGERS
Friday, July 7, 2023 5:12 PM

TRIGGER:

PROCEDURE update_Salary
Procedure call call
…….
EXEC update_salary(7369,1000); ………
……..

DML
calls TRIGGER t1
UPDATE
……..
……
……..
DELETE

TRIGGER:
• TRIGGER is a named block of statements that gets
executed automatically when we submit DML command.

• TRIGGER is same as PROCEDURE. But,


For procedure execution explicit call is required.
For trigger execution submit DML command. Implicitly
trigger will be called. For trigger execution explicit call is
not required.

Note:
• TO perform DML operations define PROCEDURE
• To control DML operations define TRIGGER

EMP

TRIGGER t1
Trigger can be used for 3 purposes:

• To control DML operations.

Example:
○ Don't allow the user to perform DMLs on sunday
○ After /Before working hours don't allow DMLs [office timings: 10AM to
4PM]
• don't allow anyone to update empno

• To audit the tables or databases.

Example:
user
at which date and time
operations
old data
new data

ORACLE 4PM PLSQL Page 119


• can be used to implement our own business rules [constraints]

Example:
• don't allow the user to decrease salary
• don't allow the duplicates
• don't allow the nulls

Types of Triggers:

3 Types:

• Table Level Trigger / DML Trigger


• Schema Level Trigger / System Trigger / DDL Trigger
• Database Level Trigger / System Trigger / DDL Trigger

Table Level Trigger:

• If a Trigger is created on Table then it is called "Table


Level Trigger".

• There are 2 types in Table Level Trigger. They are:


○ Statement Level Trigger
○ Row Level Trigger

Statement Level Trigger:


• Trigger gets executed once for one DML statement.

Example:
UPDATE emp SET sal=sal+1000
WHERE job='MANAGER';

Output:
3 rows updated

Trigger gets executed 1 time

Row Level Trigger:


• Trigger gets executed once for every row affected by
DML command.

Example:
UPDATE emp SET sal=sal+1000
WHERE job='MANAGER';

Output:
3 rows updated

Trigger gets executed 3 times.


For every row one time trigger gets executed.

Trigger Specification /
Trigger Header

ORACLE 4PM PLSQL Page 120


Trigger Header
Syntax to define Table Level Trigger:

CREATE [OR REPLACE] TRIGGER <trigger_name>


BEFORE / AFTER INSERT OR UPDATE OR DELETE
ON <table_name>
[FOR EACH ROW]
DECLARE
--declare the variables
BEGIN Trigger Body
--executable statements
END;
/

Example on Statement Level Trigger:

CREATE OR REPLACE TRIGGER t1


AFTER UPDATE
ON emp
BEGIN
dbms_output.put_line('statement level trigger executed');
END;
/

UPDATE emp SET sal=sal+1000


WHERE job='MANAGER';

Output:
statement level trigger executed

3 rows updated

Before Trigger • First Trigger gets executed


• DML operation will be performed

After Trigger • DML operation will be performed


• Trigger gets executed

Example on Row Level Trigger:

CREATE OR REPLACE TRIGGER t2


AFTER UPDATE
ON emp
FOR EACH ROW
BEGIN
dbms_output.put_line('row level trigger executed');
END;
/

UPDATE emp SET sal=sal+1000


WHERE job='MANAGER';

Output:

ORACLE 4PM PLSQL Page 121


Output:
row level trigger executed
row level trigger executed
row level trigger executed

3 rows updated

Enabling & Disabling Trigger:

Syntax:
ALTER TRIGGER <name> <enable/disable>;

Example:
ALTER TRIGGER t2 disable;

ALTER TRIGGER t1 disable;

ALTER TRIGGER t2 enable;

ALTER TRIGGER t1 enable;

Define a Trigger not to allow the user to perform DMLs on Sunday:

CREATE OR REPLACE TRIGGER t3


BEFORE INSERT OR UPDATE OR DELETE
ON emp
BEGIN
IF to_char(sysdate,'dy')='sun' THEN
raise_application_error(-20050,'you cannot perform DMLs on
sunday');
END IF;
END;
/

Testing:
On Monday:
UPDATE emp SET sal=sal+1000;
Output:
12 rows updated

On Sunday:
UPDATE emp SET sal=sal+1000;
Output:
ERROR:
ORA-20050: you cannot perform DMLs on sunday
ORA-06512: at "C##BATCH4PM.T3", line 3

Define a Trigger not to allow the user to perform DMLs


before or after working hours. [working hours:10 AM to 4PM]:

CREATE OR REPLACE TRIGGER t4


BEFORE INSERT OR UPDATE OR DELETE
ON emp

ORACLE 4PM PLSQL Page 122


ON emp
DECLARE
h INT;
BEGIN
h := to_char(sysdate,'HH24');

IF h NOT BETWEEN 10 AND 15 THEN


RAISE_APPLICATION_ERROR(-20050,'DMLs allowed between
10AM to 4PM only');
END IF;

END;
/

Testing:
before 10am or after 4pm:
update emp set sal=sal+1000;

Output:
ERROR:
ORA-20050: DMLs allowed between 10AM to 4PM only
ORA-06512: at "C##BATCH4PM.T4", line 7

between 10am to 3.59pm:


update emp set sal=sal+1000;

Output:
12 rows updated

Assignment:

Define a trigger not to allow the user to perform DMLs as follows:


If mon to fri => allow DMLs between 10AM to 4PM only
on Saturday => allow DMLs between 10 AM to 2 PM
on Sunday => don't allow the DMLs

d := to_char(sysdate,'d')
h := to_char(sysdate,'hh24')

IF d BETWEEN 2 AND 6 AND h NOT BETWEEN 10 AND 15 THEN


raise the error
ELSIF d=7 AND NOT BETWEEN 10 AND 13 THEN
raise the error
ELSIF d=1 THEN
raise the error
END IF;

:NEW and :OLD variables:

• :NEW and :OLD are system variables


• They can hold entire row
• :NEW holds new row
• :OLD holds old row
• These can be also called as pseudo records.
These can be used in Row Level Trigger only. These cannot

ORACLE 4PM PLSQL Page 123


• These can be used in Row Level Trigger only. These cannot
be used in statement level trigger.

DML :OLD :NEW


INSERT null new row
DELETE old row null
UPDATE old row new row

Define a trigger to record deleted emps in "emp_resign"


table:

EMP_Resign

empno ename job sal DOR DOR => Date_Of_Resignation


7900 .. .. .. sysdate

DELETE FROM emp WHERE empno=7900;

:OLD
empno ename job sal
7900 .. .. ..

CREATE TABLE emp_resign


(
empno NUMBER(4),
ename VARCHAr2(10),
job VARCHAr2(10),
sal NUMBER(7,2),
DOR DATE
);

CREATE OR REPLACE TRIGGER t5


AFTER DELETE
ON emp
FOR EACH ROW
BEGIN
INSERT INTO emp_resign
VALUES(:OLD.empno, :OLD.ename, :OLD.job, :OLD.sal,
sysdate);
END;
/

Testing:

delete from emp where empno=7900;

Output:
1 row deleted.

select * from emp_resign;

ORACLE 4PM PLSQL Page 124


select * from emp_resign;

Output:
EMPNO ENAME JOB SAL DOR
---------- ---------- ---------- ---------- ---------
7900 JAMES CLERK 7950 10-JUL-23

Note:
Don't use COMMIT or ROLLBACK in Trigger.

Define a trigger not to allow the user to update the empno:

CREATE OR REPLACE TRIGGER t6


BEFORE UPDATE OF empno
ON emp
BEGIN
RAISE_APPLICATION_ERROR(-20050,'you cannot update empno');
END;
/

Testing:
UPDATE emp SET empno=1001
WHERE empno=7369;

Output:
ERROR:
ORA-20050: you cannot update empno
ORA-06512: at "C##BATCH4PM.T6", line 2

NOTE:
BEFORE UPDATE we cannot update any column value
BEFORE UPDATE OF empno we cannot update empno
BEFORE UPDATE OF empno,ename BEFORE UPDATE OF empno and ename

Example on auditing emp table:

EMP_AUDIT
user_name op_date_time op_type old_Empno old_ename old_sal new_empno new_ename new_sal

c##batch4pm 11-JUL-23 DELETE


4:38:0.0 PM
user systimestamp op
:old.empno :old.ename :old.sal :new.empno :new.ename :new.sal

CREATE TABLE emp_audit


(
user_name VARCHAR2(20),
op_date_time TIMESTAMP,
op_type VARCHAR2(10),
old_empno NUMBER(4),
old_ename VARCHAR2(10),
old_sal NUMBER(7,2),
new_empno NUMBER(4),

ORACLE 4PM PLSQL Page 125


new_empno NUMBER(4),
new_ename VARCHAR2(10),
new_sal NUMBER(7,2)
);

CREATE OR REPLACE TRIGGER t7


AFTER INSERT OR UPDATE OR DELETE
ON emp
FOR EACH ROW
DECLARE
op VARCHAR2(10);
BEGIN
IF inserting THEN
op := 'INSERT';
ELSIF deleting THEN
op := 'DELETE';
ELSIF updating THEN
op := 'UPDATE';
END IF;

INSERT INTO emp_audit VALUES(user, systimestamp,


op, :old.empno, :old.ename, :old.sal, :new.empno, :new.ename, :new.sal);
END;
/

Testing:

INSERT INTO emp(empno,ename,sal)


VALUES(5001,'ABC',7000);

DELETE FROM emp WHERE empno=7902;

UPDATE emp SET sal=sal+2000


WHERE empno=7499;

COMMIT;

SELECT * FROM emp_audit;

Define a Trigger not to allow the user to decrease the salary:

EMP
EMPNO ENAME SAL :old
7499 ALLEN 12000 EMPNO ENAME SAL
7369 .. .. 7499 ALLEN 12000
7521 .. ..

:new
UPDATE emp EMPNO ENAME SAL
SET sal=sal-2000 7499 ALLEN 10000
WHERE empno=7499;

:new.sal<:old.sal => T => decreasing =>


Raise Error

ORACLE 4PM PLSQL Page 126


CREATE OR REPLACE TRIGGER t8
BEFORE UPDATE
ON emp
FOR EACH ROW
BEGIN
IF :new.sal<:old.sal THEN
raise_application_error(-20070,'You cannot decrease the
salary');
END IF;
END;
/

Testing:
update emp set sal=sal-5000;

Output:
ERROR:
ORA-20070: You cannot decrease the salary
ORA-06512: at "C##BATCH4PM.T8", line 3

Schema Level Trigger:

• Schema => User

• Schema Level Trigger can be also called as "System Trigger /


DDL Trigger".

• It is defined by DBA.

• If trigger is created on SCHEMA then it is called "Schema Level


Trigger".

• To control 1 user we define it.

Syntax of Schema Level Trigger:

CREATE OR REPLACE TRIGGER <trigger_name>


BEFORE/AFTER DROP OR ALTER OR CREATE OR TRUNCATE
ON <schema_name>.SCHEMA
DECLARE
--declare the variables
BEGIN
--executable statements
END;
/

Example on Schema Level Trigger:

Define a Trigger not to allow the c##batch4pm user to drop the DB


Objects like tables, views, procedures, functions, triggers:

Login as DBA:
username: system
password: nareshit

CREATE OR REPLACE TRIGGER t9


BEFORE DROP
ON c##batch4pm.SCHEMA

ORACLE 4PM PLSQL Page 127


ON c##batch4pm.SCHEMA
BEGIN
raise_Application_error(-20080,'you cannot drop any DB oBject');
END;
/

Testing:

Login as c##batch4pm:

DROP TRIGGER t7;


ERROR

DROP TABLE emp;


ERROR

Define a Trigger not to allow the c##batch4pm user to


drop the tables:

System Variable Purpose


ora_dict_obj_type It holds object type
Exs:
TABLE, VIEW, PROCEDURE, TRIGGER
ora_dict_obj_name It holds object name
Exs:
EMP, DEPT, T1, WITHDRAW

Login as DBA:

CREATE OR REPLACE TRIGGER t9


BEFORE DROP
ON c##batch4pm.SCHEMA
BEGIN
IF ora_dict_obj_type='TABLE' THEN
raise_Application_error(-20080,'you cannot drop the table');
END IF;
END;
/

Testing:

Login as user c##batch4pm

DROP TRIGGER t7;


Output:
Trigger Dropped

DROP TABLE emp;


ERROR:

Database Level Trigger:

• If a Trigger is created on database then it is called "Database


Level Trigger".

ORACLE 4PM PLSQL Page 128


• It can be also called as "System Trigger / DDL Trigger".

• DBA creates it.

• To control all users or multiple users this trigger will be created.

Syntax of DB Level Trigger:

CREATE OR REPLACE TRIGGER <trigger_name>


BEFORE / AFTER DROP OR CREATE OR ALTER OR TRUNCATE
ON database
DECLARE
--declare the variables
BEGIN
--executable statements
END;
/

Example on Db Level Trigger:

Define a trigger no to allow following users to drop


any Db Object:
c##batch4pm, c##batch11am, c##batch8pm

CREATE OR REPLACE TRIGGER t11


BEFORE DROP
ON DATABASE
BEGIN
IF user IN('C##BATCH4PM', 'C##BATCH11AM',
'C##BATCH8PM') THEN
raise_application_error(-20050,'you cannot drop
any DB OBject');
END IF;
END;
/

Testing:
Log in as c##batch4pm:

DROP TABLE emp;

Output:
ERROR

Compound Trigger:
• Introduced in ORACLE 11g.
• Compound Trigger is a set of triggers.

Example:
EMP Table

BEFORE Statement Level Trigger => T1

ORACLE 4PM PLSQL Page 129


BEFORE Statement Level Trigger => T1
BEFORE Row Level Trigger => T2

AFTER Statement Level Trigger => T3


AFTER Row Level Trigger => T4

Instead of defining 4 different triggers on "emp" table,


define one compound trigger for all these 4 actions.

Syntax to define Compound Trigger:

CREATE OR REPLACE TRIGGER <trigger-name>


FOR <trigger-action> ON <table-name>
COMPOUND TRIGGER
-- Global declaration.
g_global_variable VARCHAR2(10);

BEFORE STATEMENT IS
BEGIN
NULL; -- Do something here.
END BEFORE STATEMENT;

BEFORE EACH ROW IS


BEGIN
NULL; -- Do something here.
END BEFORE EACH ROW;

AFTER EACH ROW IS


BEGIN
NULL; -- Do something here.
END AFTER EACH ROW;

AFTER STATEMENT IS
BEGIN
NULL; -- Do something here.
END AFTER STATEMENT;

END <trigger-name>;
/

Example on Compound Trigger:

CREATE OR REPLACE TRIGGER t12


FOR INSERT OR UPDATE OR DELETE ON
emp
COMPOUND TRIGGER

BEFORE STATEMENT IS
BEGIN
dbms_output.put_line('before statement
level trigger executed');
END BEFORE STATEMENT;

BEFORE EACH ROW IS


BEGIN
dbms_output.put_line('before row level

ORACLE 4PM PLSQL Page 130


dbms_output.put_line('before row level
trigger executed');
END BEFORE EACH ROW;

AFTER EACH ROW IS


BEGIN
dbms_output.put_line('after row level
trigger executed');
END AFTER EACH ROW;

AFTER STATEMENT IS
BEGIN
dbms_output.put_line('after statement
level trigger executed');
END AFTER STATEMENT;

END t12;
/

Testing:

UPDATE emp SET sal=sal+1000


WHERE job='MANAGER';

Output:
before statement level trigger executed
before row level trigger executed
after row level trigger executed
before row level trigger executed
after row level trigger executed
after statement level trigger executed

2 rows updated.

Dropping A Trigger:

Syntax:
DROP TRIGGER <trigger_name>;

Example:
DROP TRIGGER t12;

user_triggers:
• is a system table
• it maintains all triggers information
• it maintains the table name, column name, trigger type ..etc

DESC user_triggers;

SELECT trigger_name, trigger_type, triggering_event,


table_name, column_name
FROM user_triggers;

user_source:

It maintains trigger code.

ORACLE 4PM PLSQL Page 131


• It maintains trigger code.

to see trigger names:

SELECT DISTINCT name FROM user_source


WHERE type='TRIGGER';

to see trigger code:

SELECT text FROM user_Source


WHERE name='T1';

ORACLE 4PM PLSQL Page 132


Dynamic SQL
Wednesday, July 12, 2023 5:07 PM

SELECT * FROM emp --static query


'SELECT * FROM ' || n --dynamic query

DROP TABLE emp --static query


'DROP TABLE ' || n --dynamic query

• DRL, DML, TCL commands can be used directly in PL/SQL


program.

• DDL, DCL commands cannot be used directly in PL/SQL program.


To use them in PL/SQL we use "Dynamic SQL".

• "EXECUTE IMMEDIATE" command is used to execute


the dynamic query. Submit dynamic query as string to "execute
immediate" command.

• The query which is built at runtime is called "Dynamic Query"

Examples on Dynamic SQL:

Define a procedure to drop the specific table:

CREATE OR REPLACE PROCEDURE


drop_table(n VARCHAR2)
AS
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE ' || n;
dbms_output.put_line(n || ' table dropped');
END;

ORACLE 4PM PLSQL Page 133


END;
/

Calling procedure:
SQL> exec drop_table('dept');
dept table dropped

define a procedure to drop any db object:

DROP TABLE t1;

DROP VIEW v1;

DROP PROCEDURE p1;

DROP FUNCTION f1;

CREATE OR REPLACE PROCEDURE


drop_object(t VARCHAR2, n VARCHAR2)
AS
BEGIN
EXECUTE IMMEDIATE 'DROP ' || t || ' ' || n;

dbms_output.put_line(n || ' ' || t || ' dropped');


END;
/

Calling procedure:

SQL> exec drop_object('table','emp_resign');


Output:
emp_resign table dropped

SQL> EXEC drop_object('trigger','t2');


Output:
t2 trigger dropped

ORACLE 4PM PLSQL Page 134


Define a procedure to drop all tables:

CREATE OR REPLACE PROCEDURE


drop_all_tables
IS
CURSOR c1 is SELECT table_name FROM user_tables;
n VARCHAR2(20);
BEGIN
OPEN c1;

LOOP
FETCH c1 INTO n;
EXIT WHEN c1%NOTFOUND;
EXECUTE IMMEDIATE 'DROP TABLE ' || n || ' cascade constraints';
END LOOP;

dbms_output.put_line('all tables dropped');

CLOSE c1;
END;
/

Procedure Call:
EXEC drop_all_tables

ORACLE 4PM PLSQL Page 135


Working with LOBs
Thursday, July 13, 2023 4:13 PM

BFILE & BLOB:

• BFILE & BLOB data types are used to maintain


unstructured data like images, audios, videos, animations
…etc.

BFILE:
• BFILE stands for Binary File Large Object.

• It is used maintain multimedia object's [LOB's] path

• It is a pointer to multimedia object

• To maintain multimedia object path, we use "bfilename()"

Database
EMP1 D: Drive
EMPNO ENAME EPHOTO [BFILE] Images Folder
1001 Ravi bfilename('D1','Ravi.jpg')
Ravi.jpg

D1 = D:\Images

• BFILE can be also called as External Large Object.


Because, Multimedia object will be stored out of
the database.

• Just multimedia object's path will be stored inside


of Database

• It is not secured one.

bfilename():
• it is a function
• it is used to maintain multimedia object's path

Syntax:
bfilename(<directory_object>, <file_name>)

Example:
ORACLE 4PM PLSQL Page 136
Example:
bfilename('D1','Ravi.jpg')

Directory Object:
• It is a Database Object
• It is a pointer to particular folder

Syntax to create Directory Object:

CREATE DIRECTORY <directory_name> AS <folder_path>;

Creating Directory Object:

Login as DBA:

username: system
password: nareshit

CREATE DIRECTORY d1 AS 'D:\Images';

GRANT read, write


ON DIRECTORY d1
TO c##batch4pm;

Login as c##batch4pm:

CREATE TABLE emp1


(
empno NUMBER(4),
ename VARCHAR2(10),
ephoto BFILE
);

INSERT INTO emp1


VALUES(1001,'A',bfilename('D1','ellison.jpg'));

SELECT * FROM emp1;

empno ename ephoto


1001 A bfilename('D1','ellison.jpg')

ORACLE 4PM PLSQL Page 137


BLOB:

• BLOB stands for Binary Large Object

• It is used to maintain multimedia object [LOB] inside of


database.

• It can be also called as Internal Large Object.

• It is secured one.

Database
D: Drive
EMP2 Images Folder
EMPNO ENAME EPHOTO [BLOB]
1001 Ravi 57A23F456E123A
Ravi.jpg

Example on BLOB:

CREATE TABLE emp2


(
empno NUMBER(4),
ename VARCHAR2(10),
ephoto BLOB
);

INSERT INTO emp2 VALUES(1001,'A',empty_blob());

number null
char ''
blob empty_blob() =>
• it is a function
• inserts null in blob type column

Define a procedure to update emp photo:

DBMS_LOB package

OPEN procedure used to open the file in specific mode


ORACLE 4PM PLSQL Page 138
OPEN procedure used to open the file in specific mode
CLOSE procedure used to close opened file
GETLENGTH function used to find size of the file
LOADFROMFILE used to read specified number of bytes from file and store in
procedure variable

Steps to update emp photo:

• Select the LOB LOCATOR and copy into t variable [BLOB type]
and Lock the record

SELECT ephoto INTO t FROM emp2 WHERE empno=p_empno


FOR UPDATE;

FOR UPDATE Locks the record

• Open LOB [Image] file in read mode

s BFILE;
s := bfilename('D1','ellison.jpg');
dbms_lob.open(s, dbms_lob.lob_readonly);

• Find file size [file length]

length number;
length := dbms_lob.getlength(s); //5683 [no of bytes]

• read binary data from s file write into t variable

dbms_lob.LoadFromFile(t,s,length);
now t has s image's binary data

• Update t image data in table

UPDATE emp2 SET ephoto=t WHERE empno=p_empno;

• Close the opened file

dbms_lob.close(s);

CREATE OR REPLACE PROCEDURE

ORACLE 4PM PLSQL Page 139


CREATE OR REPLACE PROCEDURE
update_photo(p_empno NUMBER, n VARCHAR2)
AS
s BFILE;
t BLOB;
length NUMBER;
BEGIN
SELECT ephoto INTO t FROM emp2 WHERE empno=p_empno
FOR UPDATE;

s := bfilename('D1',n);
dbms_lob.open(s, dbms_lob.lob_readonly);

length := dbms_lob.getlength(s);

dbms_lob.loadfromfile(t,s,length);

UPDATE emp2 SET ephoto=t WHERE empno=p_empno;

dbms_lob.close(s);

dbms_output.put_line('emp photo saved in table');


END;
/

procedure call:
EXEC update_photo(1001,'ellison.jpg');

SQL> select * from emp2;

EMPNO ENAME EPHOTO


---------- ---------- ---------------------------------------------------------------------------------------
1001 A FFD8FFE000104A46494600010100000100010000FFDB0084000A
0708151512181512121818181818181918181818181818191818181A1A18
1A18181C212E251C1E2B21181A2638262B2F313535351A24

SQL> SELECT length(ephoto) FROM emp2;

LENGTH(EPHOTO)
--------------
5683

ORACLE 4PM PLSQL Page 140


Collections
Friday, July 14, 2023 4:18 PM
x

x INT; 20 30

x:=20;
.
.
x:=30;

Collection:
• Collection is a set of elements of same type.

• A variable can hold 1 value only. To hold multiple


values use "COLLECTION".

• To identify collection element uniquely, use INDEX

Example:
50 90 70 60 80
x(1) x(2) x(3) x(4) x(5)

Types of Collections:

3 Types:

• Associative Array / Index By Table / PL-SQL TABLE


• Nested Table
• V-Array [Variable Size Array]

Associative Array / Index By Table / PL-SQL TABLE:

• Associative is a table of 2 columns. First column is


INDEX. Second column is ELEMENT.

• INDEX can be also called as KEY.

• ELEMENT can be also called as VALUE.

• Associative Array holds KEY-VALUE pairs.

• Indexing can be started from anywhere.

• Index can be integer or char.

ORACLE 4PM PLSQL Page 141


Example of Associative Array:

INDEX ELEMENT
[KEY] [VALUE]
1 50
2 80
3 40
4 90

Creating Associative Array:

follow 2 steps:
• Define data type for associative array
• Declare variable for that associative array

Syntax to Define data type for associative array:

TYPE <name> IS TABLE OF <element_type> INDEX BY


<index_type>;

Example:
TYPE num_array IS TABLE OF NUMBER(4) INDEX BY binary_integer;

Note:
INDEX ELEMENT If index is number type then we can use
1 10 binary_integer or pls_integer
2 70
3 50

Syntax to Declare variable for that associative array:

Syntax:
<name> <collection_type>;

Example:
x NUM_ARRAY;

x NUMBER(4);
y VARCHAR2(10);

ORACLE 4PM PLSQL Page 142


Example on creating associative array:

Create an associative array and hold a set of numbers in it:

DECLARE
TYPE num_array IS TABLE OF NUMBER(4) INDEX BY binary_integer;
x NUM_ARRAY;
BEGIN x => associative array
x(1) := 50;
INDEX ELEMENT
x(2) := 90;
1 50
x(3) := 70;
2 90
FOR i IN x.first .. x.last 3 70
LOOP
dbms_output.put_line(x(i));
END LOOP;

dbms_output.put_line('first index=' || x.first);


dbms_output.put_line('last index=' || x.last);

dbms_output.put_line('prev index of 2=' || x.prior(2));


dbms_output.put_line('next index of 2=' || x.next(2));
END;
/

Output:
50
90
70
first index=1
last index=3
prev index of 2=1
next index of 2=3

Create an Associative array and hold all dept names in it:

INDEX ELEMENT
1 ACCOUNTING
2 RESEARCH
3 SALES
4 OPERATIONS

DECLARE

ORACLE 4PM PLSQL Page 143


DECLARE
TYPE dept_array IS TABLE OF varchar2(10) INDEX BY binary_integer;
d DEPT_ARRAY;
BEGIN
SELECT dname INTO d(1) FROM dept WHERE deptno=10;
SELECT dname INTO d(2) FROM dept WHERE deptno=20;
SELECT dname INTO d(3) FROM dept WHERE deptno=30;
SELECT dname INTO d(4) FROM dept WHERE deptno=40;

FOR i IN d.first .. d.last d


LOOP INDEX ELEMENT
dbms_output.put_line(d(i)); 1 ACCOUNTING
END LOOP;
2 RESEARCH
END;
3 SALES
/
4 OPERATIONS

PL/SQL Program
PL/SQL Engine
SQL statements
PL/SQL statement executor
PL/SQL statements

SQL Engine context switch

SQL stmt executor

If no of context switches are increased performance will be


degraded

In above program to fetch all dept names and store in


collection d 4 context switches will occur.

To reduce no of context switches, we use BULK COLLECT

DECLARE
TYPE dept_array IS TABLE OF varchar2(10) INDEX BY
binary_integer;
d DEPT_ARRAY;
BEGIN
SELECT dname BULK COLLECT INTO d FROM dept;

FOR i IN d.first .. d.last


LOOP INDEX ELEMENT
dbms_output.put_line(d(i)); 1 ACCOUNTING
END LOOP; 2 RESEARCh
END; 3 SALES
/
4 OPERATIONS

ORACLE 4PM PLSQL Page 144


BULK COLLECT:

• BULK COLLECT clause used to collect entire data at a


time and store in collection.

• With 1 context switch, it collects entire data from table.

• It reduces no of context switches. So, performance will


• be improved.

Create an Associative array and hold all emp table


records in it and print them:

INDEX ELEMENT

empno ename job sal deptno hiredate .. ..


1
7369 SMITH .. ..

empno ename job sal deptno hiredate .. ..


2
7499 ALLEn .. ..

3 empno ename job sal deptno hiredate .. ..


7521 WARD .. ..

emp%rowtype
binary_integer

DECLARE
TYPE emp_array IS TABLE OF emp%rowtype INDEX BY
binary_integer;
e EMP_ARRAY;
BEGIN

SELECT * BULK COLLECT INTO e FROM emp;

FOR i IN e.first .. e.last


LOOP
dbms_output.put_line(e(i).ename || ' ' || e(i).sal);
END LOOP;

dbms_output.put_line(e(5).ename || ' ' || e(5).sal);

ORACLE 4PM PLSQL Page 145


END;
/

Create an Associative Array hold hike table records in it.


According to this data, increase salary to all emps:

employee HIKE
empno ename sal EMPNO PER
1001 A 6000 1001 10
1002 B 5000 1002 20
1003 C 7000 1003 15

create table employee


(
empno int,
ename varchar(10),
sal numeric(8,2)
);

insert into employee values(1001,'A',6000);


insert into employee values(1002,'B',5000);
insert into employee values(1003,'C',7000);

create table hike


(
empno int,
per int
);

insert into hike values(1001,10);


insert into hike values(1002,20);
insert into hike values(1003,15);
commit;

INDEX ELEMENT

empno per
1
1001 10
hike%rowtype

empno per
binary_integer 2 1002 20

empno per
3
1003 15

ORACLE 4PM PLSQL Page 146


empno per
3
1003 15

DECLARE
TYPE hike_array IS TABLE OF hike%rowtype INDEX BY pls_integer;
h HIKE_ARRAY;
BEGIN

SELECT * BULK COLLECT INTO h FROM hike;

FOR i IN h.first .. h.last


LOOP
UPDATE employee SET sal=sal+sal*h(i).per/100 WHERE empno=h(i).empno;
END LOOP;

dbms_output.put_line('salary increased to all emps');


END;
/

In Above Example,
For loop will be executed by PL/SQL statement executor.
UPDATE command will be executed by SQL statement executor.

To update 3 records, 3 context switches will occur.

To update 20 records, 20 context switches will occur.


If no of context switches are increased, performance will be degraded.

To improve the performance, use BULK BIND

BULK BIND:
• For BULK BIND, we use FORALL.

• FORALL is used to submit BULK INSERT / BULK DELETE


/ BULK UPDATE commands

• with 1 context switch all commands will be executed

• it reduces no of context switches. So, performance will


be improved.

Syntax of FORALL:

FORALL <variable> IN <lower> .. <upper>

ORACLE 4PM PLSQL Page 147


FORALL <variable> IN <lower> .. <upper>
--DML statement

Example:

FORALL i IN h.first .. h.last


UPDATE employee SET sal=sal+sal*h(i).per/100 WHERE empno=h(i).empno;

DECLARE
TYPE hike_array IS TABLE OF hike%rowtype INDEX BY pls_integer;
h HIKE_ARRAY;
BEGIN

SELECT * BULK COLLECT INTO h FROM hike;

FORALL i IN h.first .. h.last


UPDATE employee SET sal=sal+sal*h(i).per/100 WHERE empno=h(i).empno;

dbms_output.put_line('salary increased to all emps');


END;
/

In above program, with 1 context switch all emp records will be updated.
It improves the performance.

Nested Table / Nested Array:

• It contains 1 column. i.e. element

• index is always number

• Indexing starts from 1

• It is same as single dimensional array in C

Example:

x(1)
10
20
90
50

ORACLE 4PM PLSQL Page 148


To create nested table follow 2 steps:
• define the data type of nested table
• declare variable for that data type

define the data type of nested table:

Syntax:
TYPE <type_name> IS TABLE OF <elent_type>;

Example:
TYPE num_array IS TABLE OF NUMBER(4);

declare variable for that data type:

Syntax:
<variable> <type>;

Ex:
x NUM_ARRAY;

Program to demonstrate nested table:

DECLARE
TYPE num_array IS TABLE OF number(4);
x NUM_ARRAY;
BEGIN
x := num_array(10,50,90,30,40);

for i in x.first ..x.last


loop
dbms_output.put_line(x(i));
end loop;

END;
/

num_array(10,50,90,30,40) • num_array is collection constructor


• when num_array data type is defined
implicitly num_array constructor will be
defined.
• it is a special function
• it initializes the collection

DECLARE
TYPE emp_array IS TABLE OF emp%rowtype;

ORACLE 4PM PLSQL Page 149


TYPE emp_array IS TABLE OF emp%rowtype;
e EMP_ARRAY;
BEGIN
SELECT * BULK COLLECT INTO e FROM emp;

FOR i IN e.first .. e.last


LOOP
dbms_output.put_line(e(i).ename || ' ' || e(i).sal);
END LOOP;
END;
/

V-Array:
• V-Array => Variable Size Array

• When we create V-Array Type, we must specify the size.

• When we know exact size then use V-Array

To create V-Array follow 2 steps. They are:


• Define V-Array Type
• Declare variable for that V-Array Type

• Define V-Array Type:

Syntax:
TYPE <type_name> IS VARRAY(<size>) OF <element_type>;

Example:
TYPE num_array IS VARRAY(10) OF NUMBER(4);

• Declare variable for that V-Array Type:

Syntax:
<variable> <data_type>;

Example:
x NUM_ARRAY;

Example on V-Array:

DECLARE
TYPE num_array IS VARRAY(10) OF NUMBER(4);

x NUM_ARRAY;

ORACLE 4PM PLSQL Page 150


x NUM_ARRAY;
BEGIN
x := num_array(10,50,20,30);

FOR i IN x.first .. x.last


LOOP
dbms_output.put_line(x(i));
END LOOP;
END;
/

Create one V-Array and store emp records in it:

DECLARE
TYPE emp_array IS VARRAY(20) OF emp%rowtype ;
e EMP_ARRAY;
BEGIN
SELECT * BULK COLLECT INTO e FROM emp;

FOR i IN e.first .. e.last


LOOP
dbms_output.put_line(e(i).ename || ' ' || e(i).sal);
END LOOP;
END;
/

Differences between Cursor & Collection:

CURSOR COLLECTION

• fetches row by row • fetches all rows at a time and copies


into collection

• It can move forward only • It can move forward or backward

• supports to sequential • supports to random accessing


accessing.

• Slower • Faster

ORACLE 4PM PLSQL Page 151


Collection_Type Index no_of_elements sparse / dense
Associative Array binary_integer /pls_integer / unlimited sparse or dense
VARCHAR2(n)

Nested Table binary_integer /pls_integer unlimited starts as dense


it can become sparse

V-Array binary_integer /pls_integer Limited dense

dense no gaps can be there


sparse gaps can be there

sparse dense

x(10) x(1)
x(20) x(2)
x(30) x(3)
x(37) x(4)

ORACLE 4PM PLSQL Page 152

You might also like