You are on page 1of 49

Pl/SQL Simple Notes

➢ PL/SQL is a procedural language and which is extension to a non-procedural language SQL. It is a block
structured language. PL/SQL tells how to do, SQL tells what to do.
➢ A collection of Executable statements is called Block. Pl/SQL block is a logical collection of procedural and
non-procedural statements.
➢ Pl/SQL features
▪ It is developed by oracle company in 1980’s.
▪ It is used by only oracle where as SQL can be used by any RDBMS, DBMS technologies.
▪ It processes only one row at a time.
▪ It supports executable block of statements at once.
▪ It supports variables & Constraints, SQL-bind variables, PL/SQL bind and host variables.
▪ It supports error handling.
▪ It supports conditional statements (if, else, if-else).
▪ It supports interaction controls (while loop, for loop….).
▪ It supports sub-programs
1. Procedures.
2. Functions.
3. Packages.
4. Triggers.
➢ Block structure
Syntax
Declare
[Variable declaration];
Begin
<executable statements>;
Exception when <Exception name> then
<executable statements>;
End;
➢ PL/SQL block contains 3 sections
1.Declaration Section
2.Executable section
3.Exception section
➢ Types of blocks
1.Anonomous block: - it has no name and it cannot be called, it is used in Developer tool kit. It is frontend
technologies which is developed by oracle corporation.
2.Named block: - It has name and it can be called. It is created by frontend & Backend technologies.
These are four types of named blocks 1. Procedure 2. Function 3. Package 4. Trigger
➢ Main drawback of SQL
Can’t execute a group of statements in SQL.
Can’t stop errors and convert messages as user defined messages means we can’t handle Exceptions.
➢ Simple PL/SQL blocks: - below three are Executable blocks.
▪ Begin
Null;
End;
▪ Begin
Return;
End;
▪ Declare
Begin
Return;
Exception when others then
1|Page
Null;
End;
➢ Some rules
Place semicolon (;) at the end of SQL statements or PL/SQL statements.
Use forward slash (/) to run the anonymous PL/SQL block in SQL * Plus buffer (in toad select total PL/SQL
source code and press F5).
Place period (.) to close SQL * Plus buffer without running the PL/SQL program.
In PL/SQL an error is called Exception.
Section keyword like declare, begin, exception should not contain semicolon (;).
➢ PL/SQL variables
Variables are used to store data values that are used by PL/SQL.
Variable represents memory locations used to store data temporarily.
PL/SQL variable will support all built in datatypes and Boolean datatypes (TRUE/FALSE).
Note: - Bind variables not support the Boolean datatypes.
▪ Bind variable: - The variable which is defined at SQL prompt called as bind variables.
Syntax
Var <variable name> type;
Var Name varchar2(20);

Assign value to bind variable


EXEC :Name:= ‘SMITH’;

Print bind variable


Print :Name
▪ Host variable: -
Syntax
Declare <variable name> Datatype (size);

Ex
Declare
Veno number:=1000;
Vname varchar2 (20):=’SMITH’;
Vdate date default sysdate;
Flag Boolean:=TRUE;
Pincode constant number(6):=567893;

PL/SQL supports the sub programs like DML, DRL, TCL.


It can’t use DDL, DCL.
➢ DBMS_OUTPUT.PUT_LINE (): - It is used to display the user message and variable name.
Ex : - dbms_output.put_line (‘Employee name is’||Ename);
➢ SET SERVEROUTPUT ON: - It is used to activate DBMS statements
➢ Syntax of select statement in PL/SQL block
Select <list of col> into <list of variables> from <table name> [where condition];
➢ A simple PL/SQL Program for sum of two numbers
Declare
Fnum number;
Snum number;
Total number;
Begin
Fnum:= :fn;
Snum:= :sn;
2|Page
Total:= Fnum+Snum;
Dbms_output.put_line(‘The sum of two numbers is : ’||Total);
End;
➢ Write PL/SQL program to display ename, sal, comm, net salary for entered employee number?
Declare
Vempno number(4):=:p_empno;
Vename varchar2(100);
Vsal number(7,2);
Vcomm number(7,2);
Netsal number(7,2);
Begin
Select ename,sal,comm into Vename,Vsal,Vcomm from emp where empno=Vempno;
Netsal:=Vsal+NVL(Vcomm,0);
Dbms_output.put_line(‘The Employee details are ’||Vename||’ ‘||Vsal||’ ‘||Vcomm||’ ‘||Netsal);
End;
➢ To save the program in SQL * Plus
Save <drive name>:\<folder nam>\<file name>
Ex: - Save e:\plsql\p1
➢ To run the script in SQL * plus
@ e:\plsql\p1
➢ To edit file in SQL * Plus
Ed e:\plsql\p1
➢ To get the source code in SQL * Plus
Get e:\plsql\p1
➢ To RUN and Get the script in SQL * Plus
Run e:\plsql\p1
➢ Some Banking business rules examples
Create unique and not null account no
1st we create one sequence
Create sequence s1;
Then create account no as bellow
select 'KCB'||101||to_char(sysdate,'DD MM YY')||LPAD(s1.nextval,5,'0') from dual;
so account no be like
KCB10117062100001
KCB10117062100002
KCB10117062100003
Create account type
Acctype char
S- savings account (it has min bal 5000, withdraw only 30000 per day)
C- current account (it has min bal 10000, perform n no of transaction per day)
R- Recurring account (it has min bal 5000, he can take loan upto 70% after 2 years he deposited amount)
Create KCB_ACC_TAB table
create table KCB_ACC_TAB
(ACCNO varchar2(50) constraint pk_ano PRIMARY KEY,
Name varchar2(30) constraint nn_name NOT NULL,
ACCTYPE char constraint chk_at CHECK (ACCTYPE in('S','C','R')),
DOO TIMESTAMP DEFAULT SYSDATE,
Bal number (7,2) constraint nn_bal NOT NULL,
Constraint chk_bal_at CHECK ((ACCTYPE='S' AND BAL>=5000) OR (ACCTYPE='C' AND BAL>=10000) OR
(ACCTYPE='R' AND BAL>=5000)));

3|Page
Insert values into KCB_ACC_TAB table
insert into KCB_ACC_TAB values('KCB'||101||to_char(sysdate,'DD MM YY') ||
LPAD(s1.nextval,5,'0'),'&NAME','&ACCTYPE','&DOO','&BAL');
Creating banking transaction table
create table KCB_TRAN2_TAB (TID number constraint pk_tid PRIMARY KEY,
ACCNO varchar2(30) constraint fk_acno references KCB_ACC_TAB(ACCNO),
TTYPE char constraint chk_type check(TTYPE in('D','W')),
DOT timestamp default sysdate,
AMT number (8,2) constraint chk_amt check (AMT>100));
➢ Wirte PL/SQL program to display name,exp,bal&acctype for entered account no (exp should in years)?
Declare
Vname varchar2(30);
Vacctype char;
Vbal number(7,2);
Vdoo timestamp;
Exp number;
Begin
Select NAME,ACCTYPE,DOO,BAL into Vname,Vacctype,Vdoo,Vbal from KCB_ACC_TAB where
ACCNO=:p_accno;
Exp:=ROUND(MONTHS_BETWEEN(sysdate,Vdoo)/12);
Dbms_output.put_line(‘The account holder details are ‘||Vname||’ ‘||Vacctype||’ ‘||Vdoo||’ ‘||Vbal||’
‘||Exp);
End;
➢ Nested blocks: -The block which is inside of another block is called nested block.
Forward reference is possible but backward reference is not possible.
Syntax
Declare
Begin
Declare
Begin
End;
End;
Example
Declare
M number:=100;
Begin
M:=200;
Declare
N number:=300;
Total number;
Begin
M:=500;
Total:=M+N;
Dbms_output.put_line (‘The sum of M,N is ‘||Total);
End;
Dbms_output.put_line (‘The value of M ‘||M);
End;

Output is
The sum of M,N is 800
The value of M is 300 (because it passes only forward declaration means last declaration value for variable)
4|Page
➢ Small procedure
Create or replace procedure display (V varchar2)
Is
Begin
Dbms_output.put_line (V);
End;
Execute this procedure in two ways
1. EXEC display(‘My name is kamal’);
2. Begin
Display(‘My name is kamal’);
End;
Note: - from now onwards we use ‘display’ keyword instead of ‘Dbms_output.put_line’ keyword.
➢ How to convert anonymous block to label block
We need to place label before declare keyword. It can also appear after end keyword.
Advantage of label block is we can access the outer block variables in the inner block.
The label should be represented with in the double angled brackets like “<<block>>”.
Example
<<block1>>declare
M number:=100;
N number:=400;
Begin
M:=200;
<<block2>>declare
N number:=300;
Total number;
Begin
M:=500;
N:=700;
Total:=M+block1.N;
Display(‘The sum of M,N is ’||Total);
Display(‘The value of inner block N is ‘||N);
End block2;
Display(‘The value of M is ‘||M);
Display(‘The value of N is ‘||N);
End block1;

Output is
The sum of M,N is 900
The value of inner block N is 700
The value of M is 500
The value of N is 400
➢ Write PL/SQL program to deposit amount , withdraw amount and enter that values into KCB_TRAN2_TAB
table and update KCB_ACC_TAB table?
Declare
Vaccno KCB_ACC_TAB.ACCNO%type:=:accno;
Vttype KCB_TRAN2_TAB.TTYPE%type:=:ttype;
Vamt KCB_TRAN2_TAB.AMT%type:=:amt;
Cbal KCB_ACC_TAB.BAL%type;
Begin
Select bal into Cbal from KCB_ACC_TAB where ACCNO=Vaccno;
if Vttype='D' then
5|Page
Cbal:=Cbal+Vamt;
Update KCB_ACC_TAB set BAL=Cbal where ACCNO=Vaccno;
Insert into KCB_TRAN2_TAB values (nvl((select max(TID) from
KCB_TRAN2_TAB),100)+1,Vaccno,Vttype,sysdate,Vamt);
elsif Vttype='W' then
Cbal:=Cbal-Vamt;
Update KCB_ACC_TAB set BAL=Cbal where ACCNO=Vaccno;
Insert into KCB_TRAN2_TAB values (nvl((select max(TID) from
KCB_TRAN2_TAB),100)+1,Vaccno,Vttype,sysdate,Vamt);
Commit;
end if;
End;
➢ Write PL/SQL program to display Name, total marks, avg marks, highest marks, lowest marks for entered
roll no?
1st create student table
Create table student(Rollno number, Sname varchar2(20), Sclass varchar2(20), S1 number, S2 number, S3
number, S4 number, S5 number);
Insert into student values(1,’Kamal’,’CSE’,100,95,98,78,89);
Insert into student values(2,’Raj’,’IT’,77,91,69,66,88);

Declare
i student%rowtype;
Vtm number;
Vavg number;
Vhm number;
Vlm number;
Begin
Select Sname,S1,S2,S3,S4,S5 into i.Sname, i.S1, i.S2, i.S3, i.S4, i.S5 from student where Rollno=:p_rollno;
Vtm:=i.S1+i.S2+i.S3+i.S4+i.S5;
Vavg:=Vtm/5;
Select greatest(i.S1, i.S1, i.S3, i.S4, i.S5), least(i.S1, i.S1, i.S3, i.S4, i.S5) into Vhm,Vlm from dual;
Display(‘The student details are ’||i.Sname||’ ‘||Vtm||’ ‘||Vavg||’ ‘||Vhm||’ ‘||Vlm);
End;
➢ Variable attributes
1. Column type variable
Sname student.Sname&type;
2. Row type variable
i student%rowtype;
➢ CASE expression
Declare
V_dname varchar2(20);
V_deptno number;
Begin
Select deptno into V_deptno from emp where empno=:p_empno;
Case V_deptno
When 10 then
V_dname:=’Accounting’;
When 20 then
V_dname:=’RESEARCH’;
When 30 then
V_dname:=’SALES’;
6|Page
Else
V_dname:=’UNKNOWN’;
End case;
Display(‘Emp department is ‘||V_dname);
End;
➢ Flow control statements
1. Conditional control statements (if, if..else, if…elsif…elsif…else)
2. Iterative control statements(loop,while,for)
➢ 1. Conditional control statements
a. If then end if
Write PL/SQL program to hike salary 500 if employee salary less then 2000 for entered employee no
and display employee name,hiked salary , deptno?
Declare
i emp%rowtype;
begin
select ename,sal,deptno into i.ename,i.sal,i.deptno from emp where empno=:p_empno;
if i.sal<2000 then
i.sal:=i.sal+500;
update emp set sal=i.sal where empno=:p_empno;
display('The employee details are '||i.ename||' '||i.sal||' '||i.deptno);
commit;
end if;
end;
b. If then else end if
Write PL/SQL program to find entered no either even or odd no?
Declare
Vnum number:=:p_num;
Begin
If mod(Vnum,2)=0 then
Display(‘The entered number ‘||Vnum||’ is ‘||’ Even number’);
else
Display(‘The entered number ‘||Vnum||’ is ‘||’ Odd number’);
End if;
End;
c. If then elsif then else end if
Write PL/SQL program to insert no of employees into temp_det table?
1.Create table temp_det(NOE_MSG varchar2(50));
2.Declare
Vtotal_emps number;
Begin
Select count(empno) into Vtotal_emps from emp;
If Vtotal_emps=0 then
Insert into temp_det values (‘There is no employee’);
Elsif Vtotal_emps<5 then
Insert into temp_det values (‘There are few employees’);
Elsif Vtotal_emps<10 then
Insert into temp_det values (‘There are little more employees’);
Else
Insert into temp_det values (‘There are many employees joined’);
End if;
Commit;
7|Page
End;
d. RAISE_APPLICATION_ERROR()
It Is built in function used to suspend the task and as well as display message also
Syntax
RAISE_APPLICATION_ERROR(<error no>,<error message>);
Note: - error no range is -20000 to -20999
Write a PL/SQL program to update bal after transaction?
Declare
Vaccno KCB_ACC_TAB.ACCNO%type:=:accno;
Vttype KCB_TRAN2_TAB.TTYPE%type:=:ttype;
Vamt KCB_TRAN2_TAB.AMT%type:=:amt;
Cbal KCB_ACC_TAB.BAL%type;
Vacctype KCB_ACC_TAB.ACCTYPE%type;
begin
select bal,acctype into Cbal,Vacctype from KCB_ACC_TAB where accno=Vaccno;
if upper(Vttype)='D' then
Cbal:=Cbal+Vamt;
elsif upper(Vttype)='W' then
Cbal:=Cbal-Vamt;
if Vacctype='S' and Cbal<5000 then
raise_application_error(-20457,'The bal is too low so there is no transaction');
elsif Vacctype='C' and Cbal<10000 then
raise_application_error(-20458,'The bal is too low so there is no transaction');
end if;
end if;
update KCB_ACC_TAB set bal=cbal where accno=Vaccno;
insert into KCB_TRAN2_TAB values(nvl((select max(TID) from
KCB_TRAN2_TAB),100)+1,Vaccno,Vttype,sysdate,Vamt);
commit;
end;
➢ 2.Loops
a. Simple loop
the most basic loop. Syntax is follows
Loop
Sequence of statements;
End loop;
The sequence of statements will be executed between ‘loop’ and ‘end loop’.
It can be terminated the loop in three methods
i.)by using EXIT statement
EXIT [when condition];
ii.)by using if condition
if condition then
executable statements;
EXIT;
End if;
iii.)by using GOTO statement. GOTO statement uses label
if condition then
GOTO endofloop;
End if;
End loop;<<endofloop>>

8|Page
Write PL/SQL program to display 1 to 10 numbers?
Declare
N number:=1;
Begin
Loop
Exit when N>10;
Display(N);
N:=N+1;
End loop;
End;
Write a PL/SQL program to display 100 adding by 25 to every result upto no reach 250.
Declare
A number:=100;
Begin
Loop
If A=250 then
Exit;
End if;
A:=A+25;
Display(A);
End loop;
End;
b. While loop
It is pretested loop. If condition evaluates true then sequence statements will be executed and again
control passes to beginning of the loop. If condition evaluates false then control passes to next
statement.
Write PL/SQL program to display 1 to 10 numbers horizontally?
Declare
n number:=1;
v varchar2(100);
begin
while n<=10
loop
v:=v||' '||n;
n:=n+1;
end loop;
display(v);
end;
c. For loop
It is numeric loop. Syntax is follows
For loop_counter in [REVERSE] lowerbound .. higherbound
Loop
Executable statements;
End loop;
Note: - ‘loop_counter’ is implicit variable it is declared by oracle, so no need to declare by user.
‘REVERSE’ will be used to process from higherbound to lowebound value.
We can’t perform any athematic operations on implicit variable that is ‘loop_counter’.
Write a PL/SQL program to display 1 to 10 no by using for loop?
Begin
For i in 1 .. 10
Loop
9|Page
Display(i);
End loop;
End;
Write a PL/SQL program to display the result as follows
1
12
123
1234
12345
Declare
N number:=:p_no;
V varchar2(30);
Begin
For i in 1 .. N
Loop
For j in 1 .. i
Loop
V:=V||j;
End loop;
Display(V);
V:=null;
End loop;
End;
Write a PL/SQL program to display factorial of given number?
Declare
V_fact_num number:=:p_factnum;
V_factorial number:=1;
Begin
For i in REVERSE 1 .. V_fact_num
Loop
V_factorial:=V_factorial*i;
End loop;
Display(‘The factorial of ‘||V_fact_num||’ is ‘||V_factorial);
End;
GOTO statement
1.create table temp_table(V_counter number,Description varchar2(50));
2.Declare
V_counter number:=1;
begin
loop
insert into temp_table values(V_counter,'loop count');
V_counter:=V_counter+1;
if V_counter>=50 then
GOTO endofloop;
end if;
end loop;<<endofloop>>
insert into temp_table (Description) values ('done');
end;

10 | P a g e
CURSOR
→ In order to process SQL statements oracle will allocate an area of memory known as context area. PL/SQL
uses it to store and execute SQL statements. The information retrieved from database which is available in
context area is known as active set. A CURSOR is pointer which works on active set. CURSOR points one row
at a time in context area. A CURSOR is used to process multiple rows using PL/SQL.
→ It is a private memory or buffer. It is used to hold the data from tables or views in memory location for
manipulation purpose. It is valid in PL/SQL block only.
→ CURSORs are variables that you can define in the declaration section.
→ Types of CURSORs
1.Implicit Cursor
2.Explicit Cursor
→ 1.Implicit Cursor
It is cursor that is automatically declared by oracle every time SQL statement is executed.
They are identified by “SQL % <CURSOR ATTRIBUTES>”.
When the executable part of the block is issued SQL statement, PL/SQL creates an implicit cursor.
A CURSOR is automatically associated with all DML statements like insert, update, delete.
CURSOR ATTRIBUTES: - there are 4 CURSOR attributes available in PL/SQL
A.%FOUND: - It is Boolean attribute it evaluates true if the most recent SQL statement affect one or more
rows.
B.%NOTFOUND: - It is Boolean attribute it evaluates true if the most recent SQL statement does not affect
no rows.
C.%IS OPEN: - It is Boolean attribute it evaluates true if the cursor is open else evaluates false.
D.%ROWCOUNT: - It is an integer value. It counts No of rows affected by most recent SQL statement.
Example Programs.
declare
rows_deleted varchar2(20);
V_empno emp.empno%type:=7788;
begin
delete from emp where empno=V_empno;
rows_deleted:=(SQL%ROWCOUNT||' ROWs DELETED');
display(rows_deleted);
commit;
end;
output is 1 ROWS DELETED
Example 2
declare
v_job emp.job%type:=:p_job;
begin
update emp set sal=sal+1000 where job=:p_job;
display(SQL%ROWCOUNT||' Rows are updated');
if SQL%NOTFOUND then
display('Data not found so no updation done');
end if;
commit;
end;
Implicit cursor with for loop
CREATE TABLE UPDATE_TRACE
(EMPNO NUMBER, NAME VARCHAR2(50), BASIC NUMBER, DEPTNO NUMBER, DOU TIMESTAMP);
Begin
for i in (select empno,ename,sal,deptno from emp)
loop
11 | P a g e
if i.sal<1000 then
i.sal:=i.sal+100;
update emp set sal=i.sal where empno=i.empno;
insert into update_trace values(i.empno,i.ename,i.sal,i.deptno,sysdate);
end if;
end loop;
end;
Example 2
begin
for i in (select empno,ename,job,sal,comm from emp where deptno=30)
loop
if i.comm is null then
i.sal:=i.sal+500;
update emp set sal=i.sal where empno=i.empno;
else
display(rpad(i.ename,8)||' '||rpad(i.sal,6)||' '||i.comm);
end if;
end loop;
end;
→ 2.Explicit Cursor: -
Explicit cursor are explicitly defined by user or program.
The life cycle of explicit cursor goes to four stages, Declare, Open, Fetch, Close.
In declarative section we can’t use ‘into’ clause. In between begin and end we must use into clause for select
statement.
Example
Declare
Cursor c1 is
Select empno,ename,sal,deptno from emp;
Vempno number;
Vename varchar2(50);
Vsal number(7,2);
Vdeptno number;
Begin
Open c1;
Loop
Fetch c1 into Vempno,Vename,Vsal,Vdeptno;
Exit when c1%NOTFOUND;
Display(Vempno||’ ‘||Vename||’ ‘||Vsal||’ ‘||Vdeptno);
End loop;
Close c1;
End;
Write PL/SQL cursor to give the comm is 250 when employee is not having anu comm , give comm 300 if
the employee has comm 0, other than these two conditions hike the comm as 25% and also display output
as empname,ename,comm,deptno?
Declare
Cursor c1 is
Select empno,ename,comm,deptno from emp;
Vempno emp.empno%type;
Vename emp.ename%type;
Vcomm emp.comm%type;
Vdeptno emp.deptno%type;
12 | P a g e
Begin
Open c1;
Display(‘The employee details are’);
Loop
Fetch c1 into Vempno,Vename,Vcomm,Vdeptno;
Exit when c1%NOTFOUND;
If Vcomm is null then
Vcomm:=250;
Elsif Vcomm=0 then
Vcomm:=300;
Else
Vcomm:=Vcomm+Vcomm*0.25;
End if;
Update emp set comm=Vcomm where empno=Vempno;
Display(Vempno||’ ‘||Vename||’ ‘||Vcomm||’ ‘||Vdeptno);
End loop;
Commit;
Close c1;
End;
Write a PL/SQL cursor to hike salary with following criteria
1.if emp sal is 0 to 1000 hike sal 100
2.if emp sal is 1001 to 2000 hike sal 200
3.other than these two hike sal 300
After update emp sal if emp sal has more than 3000 then enter employee details into UPDATE_TRACE
table?
declare
cursor cu is
select empno,ename,sal,deptno from emp;
i emp%rowtype;
begin
open cu;
loop
fetch cu into i.empno,i.ename,i.sal,i.deptno;
exit when cu%NOTFOUND;
if i.sal between 0 and 1000 then
i.sal:=i.sal+100;
elsif i.sal between 1001 and 2000 then
i.sal:=i.sal+200;
else
i.sal:=i.sal+300;
end if;
update emp set sal=i.sal where empno=i.empno;
if i.sal>3000 then
insert into update_trace values(i.empno,i.ename,i.sal,i.deptno,sysdate);
end if;
end loop;
commit;
close cu;
end;
write PL/SQL cursor to check the entered username and password is correct or not?
Create table UTAB(USERID varchar2(30),PASSWORD varchar2(30));
13 | P a g e
insert into UTAB
values(:userid,translate(upper(:password),'ABCDEFGHIJKLMNOPQRSTUVWXYZ','1234567890!@#$%^&*()_+{
}<>'));
we enter details as bellow
userid password
Kamal Welcome2021
Raj Welcome1990

declare
cursor PRIMARY_CUR is
select 'X' from UTAB
where USERID=upper(:userid) and
PASSWORD=translate(upper(:password),'ABCDEFGHIJKLMNOPQRSTUVWXYZ','1234567890!@#$%^&*()_+{}
<>');
DUMMY_VAR varchar2(300);
begin
open PRIMARY_CUR;
fetch PRIMARY_CUR into DUMMY_VAR;
if PRIMARY_CUR%FOUND then
display('The username and password is correct');
else
display('unknown userid and password');
end if;
close PRIMARY_CUR;
end;
write PL/SQL cursor to display deptno, no of employees, low sal, high sal, total sal, avg sal of each dept?
declare
cursor gc is
select deptno, count(empno) noe, min(sal) losal, max(sal) hisal, sum(sal) totalsal, avg(sal) avgsal from emp
group by deptno;
i gc%rowtype;
begin
open gc;
loop
fetch gc into i;
exit when gc%notfound;
display(i.deptno||’ ‘||i.noe||’ ‘||i.losal||’ ‘||i.hisal||’ ‘||i.totalsal||’ ‘||round(i.avgsal));
end loop;
close gc;
end;
note: - alias name should not keep with in “ “ .
to access the group function results the alias names are mandatory.
Types of explicit cursor
a.cursor with simple loop
b.cursor with for loop: - advantage of cursor with for loop
• No need to declare explicit variables.
• No need to open cursor.
• No need to fetch the data.
• No need to terminating loop by cursor attribute.
• No need to close the cursor
Note: - after close the cursor we can’t use any cursor attribute
14 | P a g e
a.cursor with simple loop example
write a PL/SQL cursor to display empno,basic,da,hra,pf and gross salary , if employee sal is more than
3000 he is eligible for PF so display no of employee eligible for pf?
Declare
Cursor cpf is
Select empno,ename,sal BASIC,sal*0.35 DA,sal*0.45 HRA,sal*0.5 PF from emp where sal>3000;
i cpf%rowtype;
Vgross number;
Begin
Open cpf;
Loop
Fetch cpf into i;
If cpf%found then
Vgross:=i.BASIC+i.DA+i.HRA-i.PF;
Display(i.empno||’ ‘||i.ename||’ ‘||i.BASIC||’ ‘||i.DA||’ ‘||i.HRA||’ ‘||i.PF||’ ‘||Vgross);
Else
Exit;
End if;
End loop;
Display(‘The employee eligible for PF is ‘||cpf%rowcount);
Close cpf;
End;
b.cursor with for loop example
write a PL/SQL cursor to display empno,ename,sal,hra,da,pf,gross salary and deptno, if employee sal is
more than 3000 he is eligible for PF so display no of employee eligible for pf?
Declare
Cursor cpf is
Select empno,ename,sal BASIC,sal*0.35 DA,sal*0.45 HRA,sal*0.5 PF,deptno from emp where sal>3000;
i cpf%rowtype;
Vgross number;
Cnt number:=0;
Begin
Display(‘The employee details are’);
For i in cpf
Loop
Vgross:=i.BASIC+i.DA+i.HRA-i.PF;
Display(i.empno||’ ‘||i.ename||’ ‘||i.BASIC||’ ‘||i.DA||’ ‘||i.HRA||’ ‘||i.PF||’ ‘||Vgross||’ ‘||i.deptno);
Cnt:=Cnt+1;
End loop;
Display(‘The no of employees eligible for PF is ‘||Cnt);
End;
→ Parametric cursor
The cursor is defined with parameter is called parametric cursor.
The parametric cursor can be assigned with default values.
Receive values from caller or program, no size for parametric variables.
Write a PL/SQL parametric cursor to hike sal as 15% for each employee whose sal is less than 2000 and
accept deptno,job is input to display output as ename,job,hiked sal,deptno?
Declare
Cursor pc (pdno in EMP.DEPTNO%type,pjob in emp.job%type)
is
select empno,ename,job,sal,deptno from emp where deptno=pdno and job=pjob;
15 | P a g e
i pc%rowtype;
begin
open pc(:pdno,:pjob);
loop
fetch pc into i;
exit when pc%notfound;
if i.sal<2000 then
i.sal:=i.sal+i.sal*0.15;
update emp set sal=i.sal where empno=i.empno;
display(rpad(i.ename,8)||' '||rpad(i.job,8)||' '||rpad(i.sal,6)||' '||i.deptno);
end if;
end loop;
close pc;
end;
write a PL/SQL cursor to display empno,ename,ename,job,sal,deptno by separate deptno wise?
Declare
Cursor DC
is
select deptno from dept;
cursor EC(pdno dept.deptno%type)
is
select empno,ename,job,sal,deptno from emp where deptno=pdno;
Vdno dept.deptno%type;
i EC%rowtype;
begin
open DC;
loop
fetch DC into Vdno;
exit when DC%notfound;
open EC(Vdno);
loop
fetch EC into i;
exit when EC%notfound;
display(i.empno||' '||rpad(i.ename,8)||' '||rpad(i.job,8)||' '||rpad(i.sal,6)||' '||i.deptno);
end loop;
if EC%rowcount>0 then
display('------------------------------------------------------------------------------------');
end if;
close EC;
end loop;
close DC;
end;
output: - it displays the result deptno wise, after one deptno wise date then place this line ------------
write a PL/SQL cursor to display and insert empno,ename,basic,hra,da,pf,gross,deptno by separate deptno
wise and one empty row after one deptno wise result and enter these values into EMP_REPORT table?
create table emp_report as select empno ecode,ename name,sal basic,sal hra,sal da,sal pf,sal gross,deptno
from emp where 1=2;

declare
cursor dc is
select unique deptno from emp;
16 | P a g e
cursor ec (pdno emp.deptno%type)
is
select empno,ename,sal basic,sal*0.35 hra,sal*0.45 da,sal*0.15 pf,deptno from emp where deptno=pdno;
vdno DEPT.DEPTNO%type;
i ec%rowtype;
vgross number;
begin
delete from emp_report;
open dc;
loop
fetch dc into vdno;
exit when dc%notfound;
open ec(vdno);
loop
fetch ec into i;
exit when ec%notfound;
vgross:=i.basic+i.hra+i.da-i.pf;
insert into emp_report values(i.empno,i.ename,i.basic,i.hra,i.da,i.pf,vgross,i.deptno);
end loop;
close ec;
insert into emp_report(ecode) values(null);
end loop;
close dc;
end;
→ Where current clause: -
It is to refer the current record fetched from the explicit cursor.
In order to use this clause you need to lock the record fetched from the cursor.
For update clause: -
It explicitly locks the records stored in private work area.
You need to provide an explicit commit to release the lock acquired by for update clause.
Write a PL/SQL cursor to display empno,ename,deptno if any employee belong to 50th dept remove the
employee after deleting that employee then display the remaining employees?
declare
cursor lc
is
select empno,ename,deptno from emp for update;
i lc%rowtype;
begin
display('The employee details are');
display('empno'||' '||'empname'||' '||'deptno');
display('------'||' '||'--------'||' '||'-------');
open lc;
loop
fetch lc into i;
exit when lc%notfound;
display(i.empno||' '||i.ename||' '||i.deptno);
if i.deptno=50 then
delete from emp where current of lc;
end if;
end loop;
commit;
17 | P a g e
close lc;
display('After delete 50th dept employees');
open lc;
loop
fetch lc into i;
exit when lc%notfound;
display(i.empno||' '||i.ename||' '||i.deptno);
end loop;
close lc;
end;
output: - 1st it display all employees and then after deleting 50th dept employee then display result without
50th dept employees.
Sub-Query in a cursor
→ Write a PL/SQL program to display deptno,dname,location and no of employees?
declare
cursor cs
is
select d.deptno,d.dname,d.loc,v.noe from dept d,(select deptno,count(empno) noe from emp group by
deptno) v where d.deptno=v.deptno;
begin
for i in cs
loop
display(i.deptno||' '||i.dname||' '||i.loc||' '||i.noe);
end loop;
end;
Cursor with ROWID
→ Write a PL/SQL program to display ename,sal,deptno for emp who update salary. If emp sal is less than
1000 then add 200 to sal , then update these details in emp_stage table?
Create table emp_stage as select ename,sal,deptno from emp;

Declare
Cursor rc
Is
Select rowid,ename,sal,deptno from emp_stage;
Vrowid rowid;
Vename emp_stage.ename%type;
Vsal emp_stage.sal%type;
Vdeptno emp_stage.deptno%type;
begin
open rc;
loop
fetch rc into Vrowid,Vename,Vsal,Vdeptno;
exit when rc%notfound;
if Vsal<1000 then
Vsal:=Vsal+200;
update emp_stage set sal=Vsal where rowid=Vrowid;
display(Vename||' '||Vsal||' '||Vdeptno);
end if;
end loop;
close rc;
end;
18 | P a g e
EXCEPTION Handling
→ An exception in PL/SQL block is raised during exception of a block. It terminates the main body of action
means a block always terminates when pl/SQL raises an exception.
→ We can specify an exception handler to perform final action.
→ If an exception raised in the executable block with there is no exception handler, then the PL/SQL block
terminates with the failure. If exception is handled then the Pl/SQL block terminates successfully.
→ Only one exception section is allowed with in single block and if more than one exception is required, we
must use nested blocks.
→ The exception handling consists of handlers of all the exceptions.
→ Each exception handler consists of a when clause which specifies an exception that has to be handled.
→ Syntax
Exception
When <exception 1…> then
Sql statement1;
Sql statement2;
When others then
Sql statement1;
Sql statement2;
End;
→ The other exception is optional and it should always be the last handler in the block.
→ Types of exceptions
1.Raised implicitly (or) Implicit Exception: - This is predefined oracle server exception which are raised by
oracle server
2.Raised explicitly (or) Explicit Exception: - These exceptions are defined by user and raised by the user
itself.
Predefined exception list
Error no Exception Name Description
ORA-00001 Duplicate_Value_On_index Unique constraint violated.
ORA-1001 Invalid_cursor Illegal cursor operation.
ORA-1403 NO_DATA_FOUND No data found.
ORA-1422 TO_MANY_ROWS A select … into statement matches more than one row.
ORA-1722 Invalid_Number Conversion to a number failed.
ORA-6502 Value_error Truncation, arithmetic conversion error.
ORA-6511 Cursor_already_open When a cursor is opened without clause.
ORA-01017 Login_denied When enter wrong username and password.
ORA-01476 0_devide Any value is divided by the zero.
ORA-06592 Hence_Not_Found When case not matched.
Note: -A program can have ‘n’ no of exception and many nested blocks are needed.
Example
declare
i emp%rowtype;
begin
i.empno:=:p_empno;
select ename,sal,deptno into i.ename,i.sal,i.deptno from emp where empno=i.empno;
if i.sal<2000 then
i.sal:=i.sal+i.sal*0.25;
update emp set sal=i.sal where empno=i.empno;
display('The Employee details are '||i.ename||' '||i.sal||' '||i.deptno);
end if;
exception when no_data_found then
display('The employee no is not exists please enter correct empno');

19 | P a g e
when others then
display('There is some abnormal exception');
end;
➢ Raise_application_error: - It is built in function this enables user defined error messages.
Syntax: raise_application_error(<errorno>,<errormessage>); error no range is -20000 to -20999.
Example
declare
Vempno number;
Vsal number;
begin
select sal,empno into Vsal,Vempno from emp where empno=:p_empno;
if Vsal<2000 then
raise_application_error(-20001,'The sal is less then 2000 then so no updation');
update emp set sal=sal+200 where empno=Vempno;
else
Vsal:=Vsal+Vsal*0.15;
update emp set sal=Vsal where empno=Vempno;
display('The employee details are '||Vempno||' '||Vsal);
end if;
exception when no_data_found then
display('Yhe employee no is invalid');
end;
→ User defined exception
SQLCODE: - it codes the currently raised error no.
SQLERRM: - it codes the currently raised error message.
Example: - write pl/sql program to display ename,sal if emp sal is null then raise user defined error then
add sal 3000 to that employee?
declare
salary_missing exception;
i emp%rowtype;
begin
select empno,ename,sal into i.empno,i.ename,i.sal from emp where empno=:p_empno;
if i.sal is null then
raise salary_missing;
else
i.sal:=i.sal+i.sal*0.25;
end if;
update emp set sal=i.sal where empno=i.empno;
display('The employee details are '||i.ename||' '||i.sal);
exception when no_data_found then
display('The employee not exists');
when salary_missing then
display('The employee is not having salary so give the salary as 3000');
display(SQLCODE||' '||SQLERRM);
update emp set sal=3000 where empno=i.empno;
when others then
display('unknown error');
end;
→ Pragma exception_init: -
Which tells compiler to associated error no with user defined exception at compile time.
Example
20 | P a g e
declare
pk_vio exception;
pragma exception_init(pk_vio,-00001);
begin
insert into dept values(40,'EXPORT','Hyd');
commit;
exception when pk_vio then
display('Duplicate deptno not allowed here');
end;
User defined datatypes or composite data types
There are 5 types
1.Objects
2.Varray
3.Pl/SQL record
4.Pl/SQL table
5.Ref cursor or dynamic cursor
Here objects, Varray are database objects which are stored permanently into database.
Remaining all are user defined data types which are not stored anywhere in database, they can use only in PL/SQL.
1.Object: - These are discussed in SQL
→ Creation of user defined object data type
➢ Create or replace type addr_type
As
Object (Hno varchar2(30), Streetname varchar2(30), City varchar2(20), Pincode number (7));
➢ Create or replace type PF_type
As
Object (PFnumber number (20), Amt number (12,2));
➢ Above statements create the user defined object datatype as addr_type, PF_type in the data dictionary
called user_types.
➢ These datatypes are also called as collection in oracle. This collection is reusable when ever the same
datatype collection is required by the project.
➢ Creating table with user defined object data type
Create table Employee (Ecode number (3), Name varchar2 (30), Address addr_type, Basic number (12,2), PF
PF_type);
➢ How to Insert data into table Employee with user defined object datatype
Insert into Employee (100, ‘kamal’, addr_type (12, ‘Reddynagar’, ‘Vinukonda’, 522647), 8000, PF_type
(1564235,450));
Commit;
➢ How to select data from object table
Select * from Employee;
Select Address from Employee;
Select e.Address, e.Address.city from Employee e;
➢ How to update data in object table
Update Employee e set Basic=Basic+5000 where e.Address.city=’Vinukonda’;
➢ How to delete data in object table
Delete from Employee e where e.Address.city=’Vinukonda’;
✓ Creating user defined object table
➢ Create type Info as object (Code number (10), Name varchar2(30), Hno varchar2(30), Street varchar2(30),
City varchar2(20), Pin number (7));
➢ Create table Emp_info of Info;
Here Info is object by using this we can create Emp_info table.

21 | P a g e
➢ Inserting values into object table
Method 1
Insert into Emp_info values (1001, ’Ramu’, ‘2-34’, ‘SR Nagar’, ‘Hyderabad’, 522001);
Method 2
Insert into Emp_info values (Info (1002, ‘Raju’, ‘1-102’, ‘SR Nagar’, ‘Hyderabad’, 522001));
2.Varray: - It is one of user defined datatype. It is created in SQL and it is stored in database.
➢ Syntax
Create type <type name> is varray(size) of datatype(size);
Example
Create type vph is varray(3) of varchar2(15);
➢ How to use this datatype in create table?
Create table cust(cid number,name varchar2(50),phn_no vph);
➢ How to insert data
Insert into cust(101,’kamal’,vph(7396617240,9412365470,9562321456));
3.Pl/SQL Record: -
➢ PL/SQL record holds list of elements with different datatypes.
➢ Syntax
Type <recordname> is record
(element 1 <datatype>, element 2 <datatype>, … element n <datatype>);
➢ Write a Pl/SQL program to display ename,basic,deptno,dname and gross salary for entered empno?
declare
type erec is record
(eno number,name emp.ename%type,basic emp.sal%type,i dept%rowtype,gross number);
el erec;
begin
el.eno:=:p_empno;
select ename,sal,d.deptno,d.dname into el.name,el.basic,el.i.deptno,el.i.dname from emp e,dept d where
e.deptno=d.deptno and e.empno=el.eno;
el.gross:=el.basic+el.basic*0.45+el.basic*0.35-el.basic*0.15;
display('The employee details are '||el.name||' '||el.basic||' '||el.i.deptno||' '||el.i.dname||' '||el.gross);
end;
4.Pl/SQL Table: -
➢ It holds the elements of similar datatypes. It is similar to C-Array.
➢ Syntax
Type <table name> is table of <datatype> index by binary_integer;
Example
declare
type name is table of varchar2(50) index by binary_integer;
n name;
begin
n(-1):='Budala';
n(-2):='Kamal';
n(-3):='Raj';
display('The full name is '||n(-1)||' '||n(-2)||' '||n(-3));
end;
write a PL/SQL program to display ename and hiked salary with the following condition
1.if emp sal is between 0 and 1000 hike 15%
2.if emp sal is between 1001 and 2000 hike 25%
3.other than this hike sal 35%
The hiked sal is above 3000 then insert ename,esal,eno,hiked sal into update_trace table?

22 | P a g e
declare
type eno is table of emp.empno%type index by binary_integer;
type name is table of EMP.ENAME%type index by binary_integer;
type pay is table of emp.sal%type index by binary_integer;
e eno;
n name;
p pay;
ctl number:=1;
begin
for i in(select empno,ename,sal from emp)
loop
e(ctl):=i.empno;
n(ctl):=i.ename;
p(ctl):=i.sal;
ctl:=ctl+1;
end loop;
for k in 1 .. n.count
loop
if p(k) between 0 and 1000 then
p(k):=p(k)+p(k)*0.15;
elsif p(k) between 1001 and 2000 then
p(k):=p(k)+p(k)*0.25;
else
p(k):=p(k)+p(k)*0.35;
end if;
update emp set sal=p(k) where empno=e(k);
if p(k)>3000 then
insert into update_trace(empno,name,basic,dou) values(e(k),n(k),p(k),sysdate);
end if;
display(e(k)||' '||n(k)||' '||p(k));
end loop;
commit;
end;
Returning into clause: - It is introduced in oracle 8.0 version. It return values to the variable and it collect
only one value into variable.
open sql * plus then do bellow steps.
var vsal number;
var vname varchar2(20);
update emp set sal=sal*0.25 where empno=7499 returning ename,sal into :vname,:vsal;
print :vname :vsal;
Bulk collect: - it is used to collect more than one row at a time. It is used with select, update, delete, fetch.
Write a PL/SQL program to delete the 30th dept employees, after delete if any emp sal is above 1500 take
that eno, ename, sal insert into update_trace table?
declare
type eno is table of EMP.EMPNO%type index by binary_integer;
type name is table of EMP.ENAME%type index by binary_integer;
type pay is table of EMP.SAL%type index by binary_integer;
e eno;
n name;
p pay;
begin
23 | P a g e
delete from emp where deptno=30 returning empno,ename,sal bulk collect into e,n,p;
for k in 1 .. e.count
loop
if p(k)>1500 then
insert into update_trace values(e(k),n(k),p(k),null,sysdate);
end if;
end loop;
commit;
end;
write a PL/SQL program to hike sal if job is CLERK hike 15%, job is SALESMAN hike 25%, other than these
hike 35% and display ename,sal,job?
declare
type eno is table of EMP.EMPNO%type index by binary_integer;
type name is table of EMP.ENAME%type index by binary_integer;
type pay is table of EMP.SAL%type index by binary_integer;
type job is table of EMP.JOB%type index by binary_integer;
e eno;
n name;
p pay;
j job;
begin
select empno,ename,job,sal returning bulk collect into e,n,j,p from emp;
for k in 1 .. e.count
loop
if j(k)='CLERK' then
p(k):=p(k)+p(k)*0.15;
elsif j(k)='SALESMAN' then
p(k):=p(k)+p(k)*0.25;
else
p(k):=p(k)+p(k)*0.35;
end if;
update emp set sal=p(k) where empno=e(k);
display(n(k)||' '||p(k)||' '||j(k));
end loop;
commit;
end;
Cursor fetch with bulk collect
declare
type name is table of EMP.ENAME%type index by binary_integer;
type pay is table of EMP.SAL%type index by binary_integer;
cursor c1 is select ename,sal from emp;
n name;
p pay;
begin
open c1;
fetch c1 bulk collect into n,p;
for i in 1 .. n.count
loop
display(n(i)||' '||p(i));
end loop;
close c1; end;
24 | P a g e
5.Ref cursor or dynamic cursor: -
➢ Explicit cursor is static cursor and it refers always one work area in the memory.
➢ Implicit cursor is dynamic or REF cursor and it refers diff work area in the memory at a time.
➢ It is used to declare a cursor without select statement.
➢ A REF cursor is re used it declare in package. It supports to return more than one row from subprogram.
➢ Types of REF cursors, 1.WEAK REF Cursor, 2.STRONG REF Cursor.
➢ 1.WEAK REF cursor: - cursor variable with out return type is called WEAK REF Cursor.
Syntax
1.type <typename> is ref cursor;
2.<cursor variable name> <ref cursor name>;
3.Open < cursor variable name >;
For (select statement);
Fetch;
Exit;
Close;
Write a PL/SQL Procedure to display the emp details according to the entered deptno , if deptno=10
display ename, empno, deptno. If deptno=20 display ename, job, sal, deptno. Other than these two
display ename, job, deptno ?
create or replace procedure procef(pdeptno number)
is
vempno emp.empno%type;
vename emp.ename%type;
vdeptno emp.deptno%type;
vjob EMP.JOB%type;
vsal emp.sal%type;
type ref_c is ref cursor;
c1 ref_c;
begin
if pdeptno=10 then
open c1 for select empno,ename,deptno from emp where deptno=pdeptno;
elsif pdeptno=20 then
open c1 for select ename,job,sal from emp where deptno=pdeptno;
else
open c1 for select ename,job,deptno from emp where deptno=pdeptno;
end if;
if pdeptno=10 then
loop
fetch c1 into vempno,vename,vdeptno;
exit when c1%notfound;
display(vempno||' '||vename||' '||vdeptno);
end loop;
close c1;
elsif pdeptno=20 then
loop
fetch c1 into vename,vjob,vsal;
exit when c1%notfound;
display(vename||' '||vjob||' '||vsal);
end loop;
close c1;
else
loop
25 | P a g e
fetch c1 into vename,vjob,vdeptno;
exit when c1%notfound;
display(vename||' '||vjob||' '||vdeptno);
end loop;
close c1;
end if;
end procef;
execute this procedure: - EXEC procef(10);
➢ 2.Strong REF cursor: - A cursor variable with return type is called as Strong REF cursor.
Syntax
1.type <typename> is ref cursor return <tablename>%rowtype;
2.<cursor variable name> <ref cursor name>;
3.open <cursor variable name>
For select statement;
Fetch;
Exit;
Close;
Write a pl/sql package to display deptno, ename, hiredate, sal, total sal for entered deptno. If deptno >=40
then multiply sal+comm with 1.4, if deptno=30 then multiply sal+comm with 1.3, if deptno=20 then
multiply sal+comm with 1.2 ,other than these then multiply sal+comm with 1.1 and then display result?
1st step create package
create or replace package emp_det
is
type r_comp is record
(deptno emp.deptno%type,
ename emp.ename%type,
hiredate EMP.HIREDATE%type,
sal emp.sal%type,
total_sal emp.sal%type);
type comp_rc is ref cursor return r_comp;
function emp_sal(pdeptno number)
return comp_rc;
end emp_det;
2nd step create package body
create or replace package body emp_det
is
function emp_sal(pdeptno number)
return comp_rc
is
c_emp EMP_DET.comp_rc;
v_raise number;
begin
if pdeptno>=40 then
v_raise:=1.4;
elsif pdeptno=30 then
v_raise:=1.3;
elsif pdeptno=20 then
v_raise:=1.2;
else
v_raise:=1.1;
end if;
26 | P a g e
open c_emp for select deptno,ename,hiredate,sal,v_raise*(sal+nvl(comm,0)) total_sal from emp where
deptno=pdeptno;
return c_emp;
end emp_sal;
end emp_det;
3rd step to execute package
Select emp_det.emp_sal(20) from dual;
Note: - here emp_det is package name and emp_sal is function name called in the package.

Sub programs in PL/SQL


➢ Sub programs are used to provide modularity and encapsulate a sequence of statements.
➢ Once sub programs are built and validated they can be used in a no of applications. It also provide binding
the data. These are named PL/SQL blocks that can access parameters.
➢ Sub programs can also have declaration part, executable part, Exception handling part.
➢ Important features of sub program: -
1. Modularity: - Sub programs allows us to break program into some modules to manage easily.
2. Reusability: - Sub programs once executed can be used in any no of applications.
3. Maintainability: - if a sub program is effected only its definition changes that means only modified lines
are compiled not the overall program so it can easily maintains.
➢ Sub programs are two types
1. Procedures
2. Functions
Procedures
→ A names anonymous PL/SQL block.
→ It is called as stored procedure in oracle. It is stored in database as object.
→ It accepts parameters and it is explicitly called. It is used to perform an action or pass values.
→ It may or may not return a value and it is compiled and stored into database.
→ Tables for view procedures
User_source, user_procedures, user_objects, dba_objects
→ Types of procedures
1. Stand-alone schema object: - The procedure which is created outside of the package called as stand-
alone schema object or stored procedures.
2. A Part of package: - The procedure which is defined inside of the package is called as A Part of package.
This procedure can’t recognize without reference of a package. Calling this package as
“<packagename>.<Procedurename>” while execution time.
→ Syntax of procedure
Create or replace procedure <procedure name> (parameter [mode] datatype, ….)
Is/as
[local variables];
Begin
<executable statements>;
Exception when condition then
<executable statements>;
End <procedure name>;
Or replace: -it is optional keyword to replace the existing procedure with modification with same name.
<Procedure name> is mandatory.
Parameter: - Every procedure may or may not have the parameters. Parameter name is mandatory,
parameter mode is optional. The default parameter mode is ‘IN’ and parameter datatype should mention.
There are three types of parameter modes 1.IN, 2.OUT, 3.IN/OUT.
Is/as: - after this keyword the procedure execution part will be start.
Local Variable: -it is optional and the procedure may or may not have variables
27 | P a g e
Invoking or executing stored procedure or stand-alone schema object
Step1: - exec <procedure name> (required parameters or arguments);
Step2: - begin
<procedure name> (required parameters or arguments);
End;
Example program
create or replace procedure cal_intr( p in number,n in number, r in number)
is
si number; --simple interest
ci number; --compound interest
begin
si:=(p*n*r)/100;
ci:=round(p*power(1+(r/100),n),2);
display('The simple interest is '||si);
display('The compound interest is '||ci);
end cal_intr;
To execute this procedure
exec cal_intr(100,2,10);
write PL/SQL procedure to deposit, withdraw amount and update in kcb_acc_tab table and insert that
transaction into kcb_tran2_tab table?
create or replace procedure upd_bal (paccno in kcb_acc_tab.accno%type,
pttype in kcb_tran2_tab.ttype%type,
pamt in kcb_tran2_tab.amt%type)
is
cbal kcb_acc_tab.bal%type;
vacctype kcb_acc_tab.acctype%type;
begin
select bal,acctype into cbal,vacctype from kcb_acc_tab where accno=paccno;
if upper(pttype)='D' then
cbal:=cbal+pamt;
elsif upper(pttype)='W' then
cbal:=cbal-pamt;
if vacctype='S' and cbal<5000 then
raise_application_error(-20345,'The bal is too low so no transaction');
elsif vacctype='C' and cbal<10000 then
raise_application_error(-20346,'The bal is too low so no transaction');
end if;
end if;
update kcb_acc_tab set bal=cbal where accno=paccno;
insert into kcb_tran2_tab values(nvl((select max(tid) from
kcb_tran2_tab),100)+1,paccno,pttype,sysdate,pamt);
commit;
end upd_bal;
To execute this procedure
exec upd_bal('KCB10117 06 2100023','D',500);
Write a PL/SQL procedure to calculate bonus salary and hike emp salary with bonus under fallowing
condition. If emp job is ‘CLERK’ then hike net sal by 15%, if emp job is ‘SALESMEN’ then hike net sal 25%,
other than these two conditions hike net sal by 35% and display ename, bonus, deptno, job?
CREATE OR REPLACE PROCEDURE cal_bonus
is
cursor cb is
28 | P a g e
select empno,ename,job,sal+nvl(comm,0) net,deptno from emp;
i cb%rowtype;
bonus number;
begin
open cb;
loop
fetch cb into i;
exit when cb%notfound;

if i.job='CLERK' then
bonus :=i.net*0.15;
elsif i.job='SALESMAN' then
bonus :=i.net*0.25;
else
bonus :=i.net*0.35;
end if;
update emp set sal=sal+bonus
where empno=i.empno;

display(i.ename||' '||i.job||' '||i.deptno||' '||bonus);


end loop;
commit;
close cb;
end;
To execute this procedure
Exec cal_bonus;
→ Parameter modes: -
1. IN: - It is default type. Always accept a value into a sub-program and we can assign value for it.
2. OUT: - It is used to written a value to sub program and we can assign value in sub program.
3. IN-OUT: - It carry a value into sub program and written a value from sub program.
Note: - Max 32 parameters can support by sub program.
→ Passing values to parameter by two methods
1.By position notation: -by position we can pass the parameters.
2.By named notation: -by name of the parameter we can pass values by using ‘=>’ .
Write a PL/SQL Procedure to written a square and cube of entered number?
CREATE OR REPLACE procedure proc_Sc(n in number,
s out number,
c out number)
is

begin
s:=n*n;
c:=n*n*n;
end proc_Sc;
To call this procedure in another PL/SQL program by position notation
declare
n number:=:p_number;
sr number;
cr number;
begin
proc_sc(n,sr,cr);
29 | P a g e
display('The suare and cube of number '||n||' is '||sr||' '||cr);
end;
To call this procedure in another PL/SQL program by named notation
declare
nr number:=:p_nr;
cr number;
sr number;
begin
proc_sc(n=>nr,s=>sr,c=>cr);
display('The suare and cube of the value '||nr||' is '||sr||' '||cr);
end;
write a PL/SQL procedure to written a no of employees for entered deptno?
CREATE OR REPLACE procedure pio(pdnoe in out number)
is
begin

select count(empno) into pdnoe from emp where deptno=pdnoe;

end;
To call this procedure in another PL/SQL program
declare
nr number:=:p_nr;
begin
pio(nr);
display('No of employees in the entered deptno '||:p_nr||' is '||nr);
end;
→ Grant permission on procedure to another user
Grant execute on proc_sc to public;
Here proc_sc is procedure name , in place of public we can mention particular user also.
If another user uses this procedure like this SQLCLASS.proc_sc
Here SQLCLASS is that procedure owner user and proc_sc is procedure name.
→ Synonym for procedure
Create public synonym pc for proc_sc; note: -here pc is synonym for procedure proc_sc
We can’t create a synonym for procedure which is part of the procedure.
→ Procedure overloading: -Oracle permits to call a same procedure with different signatures.
Types of different signatures
1. Different no of parameters: -
<Procedure name>(a in number)
<Procedure name>(a in number, b in number)
2. Different datatypes of the parameter: -
<Procedure name>(a in number, b in number)
<Procedure name>(a in number, b in varchar2(20))
3. Different sequence of datatypes of parameter: -
<Procedure name>(a in number, b in varchar2(20))
<Procedure name>(a in varchar2(20), b in number)
→ PRAGMA Autonomous_transaction: -it is introduced in oracle 8i. it allows to write TCL in trigger.
It also used in nested procedures to make each procedure independent for TCL.
Example
1.CREATE OR REPLACE procedure add_emp
is
PRAGMA Autonomous_transaction;
30 | P a g e
Begin
insert into emp(empno,ename,sal,deptno) values(1001,'JOHN',2000,40);
COMMIT;
end add_emp;
2.CREATE OR REPLACE PROCEDURE ADD_DEPT
is
begin
INSERT INTO DEPT Values(50,'EXPORT','HYD');
commit;
add_emp;
end ADD_DEPT;
To execute these procedures: - EXEC ADD_DEPT;
Note: -1. In this case add_emp is called procedure and ADD_DEPT is calling procedure.
2.Called procedure commit should not effect on calling procedure transaction.
→ Dropping a procedure
Drop procedure <procedure name>;
→ How to store images into database by using procedure
Steps: -
• Create one directory in operating system like as ‘IMAGES_DIR;’ is name of the folder.
• Store images in that folder.
• Create a table for storing the images
create table images (image_name varchar2(30), iex varchar2(20), image blob);
• Create one directory in a database with the reference of operating system directory like this
Create directory IMAGESDIR as ‘e:\IMAGES_DIR;’;
Note: -Database directory information stored in dba_directories
Write a PL/SQL procedure to load images into database?
CREATE OR REPLACE procedure load(filename varchar2)
as
f_lob bfile;
b_lob blob;
begin
insert into images values(filename,substr(filename,instr(filename,'.')+1),empty_blob())
return image into b_lob;

f_lob:=BFILENAME('IMAGEDIR',filename);

dbms_lob.fileopen(f_lob,dbms_lob.file_readonly);
dbms_lob.loadfromfile(b_lob,f_lob,dbms_lob.getlength(f_lob));
dbms_lob.fileclose(f_lob);
commit;
end;
To execute this procedure
Exec load(‘1.jpb’);
Empty_blob(): - it is a function and return null value when image is not available.
BFILENAME: - it is built in function it written the path of the imge.
Fileopen(): - it is built in function, it is used to open the image filename.
File_readonly(): - it is built in function, it read the image and check that now the image is available or not.
Loadfromfile(): - this function is used to load the image into variables.
Getlength(): - it is used to find out the image length and checks the image length with column length, if the
image length is more than column length it throws the error.
Fileclose(): - this function is used to close the image after complete the process.
31 | P a g e
FUNCTIONS
➢ A function is similar to procedure. It is named block in PL/SQL and it may or may not take parameter but it
must return a value.
➢ Function must have return clause in the executable section of the function.
➢ Function mainly used to perform the calculation.
➢ The datatype of return values must be declared in the header of the function.
➢ Procedures and functions are stored in database, these are declared with in block.
➢ A procedure call is a pl/sql statement by itself, a function call is part of an expression.
Procedure call function call
Begin declare
<Procedurename>(<variables>); variable datatype;
End; begin
Variable:=<function name>(<variables>);
End;
➢ A function has output that needs to be assign to a variable or it can be used in select statement.
➢ Function can’t call when it has written a datatype as Boolean (true/false) at sql prompt.
➢ A function has more than one return statement and each exception should have a return statement.
➢ Syntax
Create or replace function <function name>
(Parameter list)
Return datatype; Exception block
Is Exception when condition1 then
[local variables]; Return;
Begin Exception when condition2 then
<body>; Return;
Return(value); Exception when others then
Exception Return;
Executable statements;
End <function name>;
Note: - we can’t call function with sql statement when function return Boolean value or outmode parameter.
➢ Function can call at SQL prompt, select statement in PL/SQL block, in procedure, in trigger, in package, in
function and in another applications.
Invoke or call a function at SQL prompt
Exec :variable:=<function name>(parameter 1, argument 2);
➢ Write a PL/SQl user defined function to calculate the compound interest?
CREATE OR REPLACE function cal_cintr (p in number, n in number, r in number)
return number
is
ci number;
begin
ci :=p*power((1+r/100),n);
return ci;
end;
To call this function in sql prompt
Var bcr number;
Exec :bcr:=cal_cintr (1000, 12, 2);
Print bcr;
To call this function in SQL statement
Select cal_cintr (1000, 12, 2) compound from dual;
Note: - If function return a value as Boolean we can’t call here in select statement.
To call this function in PL/SQL Program or Block
32 | P a g e
Declare
Bcr number;
Begin
Bcr:=round (cal_cintr (1000, 12, 2));
Display(‘The compound interest is : ‘||Bcr);
End;
➢ Create a function to find the entered year is leap year or not and display employees who were joined In
leap year by using this function?
CREATE OR REPLACE function leap_year(y in number)
return varchar2
is
begin
if mod(y,400)=0 or (mod(y,4)=0 and mod(y,100)!=0) then
return ('It is a leap year');
else
return ('It is not a leap year');
end if;
end leap_year;
To call this function in select statement
1st check hiredate with leap year
select ename,hiredate, leap_year(to_char(hiredate,'yyyy')) from emp;
select ename,hiredate from emp where leap_year(to_char(hiredate,'yyyy'))='It is a leap year';
➢ Write a PL/SQL function to calculate the factorial value and find the entered no is even or odd number?
CREATE OR REPLACE function feo_fact (n in number, f out number)
return boolean
is
fact number :=1;
begin
if n=0 or n=1 then
f :=1;
else
for i in reverse 1 .. n
loop
fact:=fact*i;
end loop;
end if;
f:=fact;
if mod(n,2)=0 then
return true;
else
return false;
end if;
end;
note: - we can’t call this function in sql prompt because it return Boolean.
To call this function in another program
declare
vn number:=:p_no;
vf number;
begin
if feo_fact(vn,vf) then
display(vn||' is even number');
33 | P a g e
else
display(vn||' is odd number');
end if;
display(vn||' factorial vlaue is '||vf);
end;
➢ Create a procedure to update balance and insert that transaction into kcp_tran2_tab table?
CREATE OR REPLACE procedure upd_bal (paccno in kcb_acc_tab.accno%type,
pttype in kcp_tran2_tab.ttype%type,
pamt in kcp_tran2_tab.amt%type)
is
cbal kcb_acc_tab.bal%type;
vacctype kcb_acc_tab.acctype%type;
begin
select bal,acctype into cbal,vacctype from kcb_acc_tab where accno=paccno;
if upper(pttype)='D' then
cbal:=cbal+pamt;
elsif upper(pttype)='W' then
cbal:=cbal-pamt;
if vacctype='S' and cbal<5000 then
raise_application_error(-20345,'The bal is too low so no transaction');
elsif vacctype='C' and cbal<10000 then
raise_application_error(-20346,'The bal is too low so no transaction');
end if;
end if;
update kcb_acc_tab set bal=cbal where accno=paccno;
insert into kcp_tran2_tab values(nvl((select max(tid) from
kcp_tran2_tab),100)+1,paccno,pttype,sysdate,pamt);
commit;
end upd_bal;
To call this Procedure like below
exec upd_bal('10113 05 2100003','W',5000);
➢ Create a function to check balance when withdraw amount, and check account holder to eligible withdraw
amount or not?
CREATE OR REPLACE function chk_bal(paccno in kcb_acc_tab.accno%type,
pamt in kcp_tran2_tab.amt%type
)
return boolean
is
cbal kcb_acc_tab.bal%type;
vacctype kcb_acc_tab.acctype%type;
begin
select acctype,bal into vacctype,cbal from kcb_acc_tab where accno=paccno;
cbal:=cbal-pamt;
if vacctype='s' and cbal<5000 then
return(false);
elsif vacctype='c' and cbal<10000 then
return(false);
else
return(true);
end if;
end chk_bal;
34 | P a g e
To call this function in another procedure
create or replace procedure upd_bal2(paccno kcb_acc_tab.accno%type,ptrtype
kcp_tran2_tab.ttype%type,pamt kcb_acc_tab.bal%type)
is
cbal kcb_acc_tab.bal%type;
begin
select bal into cbal from kcb_acc_Tab where accno=paccno;
if upper(ptrtype)='D' then
cbal:=cbal+pamt;
elsif upper(ptrtype)='W' then
if chk_bal(paccno,pamt)then
cbal:=cbal-pamt;
else
Raise_application_error(-20456,'There IB so we cannot do the transaction:');
end if;
end if;
update kcb_acc_tab set bal=cbal where accno=paccno;
insert into kcp_tran2_tab values(nvl((select max(tid) from
kcp_tran2_tab),100)+1,paccno,ptrtype,sysdate,pamt);
commit;
exception
when no_data_found then
display(paccno||'is not exist');
end upd_bal2;
To call this
exec upd_bal2('10113 05 2100003','W',11000);
➢ Create a function to insert row in dept table?
CREATE OR REPLACE function ADD_DEPT1
return number
is
begin
INSERT INTO DEPT Values(70,'EXPORT1','HYD');
commit;
return null;
end ADD_DEPT1;
To Call this
declare
aa number;
begin
aa:=add_dept1;
end;
➢ How to drop function
Drop function <function name>;
Drop function add_dept1;

35 | P a g e
Database Triggers
→ A set of pl/sql statements automatically executed whenever the DML operation is performed on a table.
→ It is a pl/sql block like procedure and function and it is also database object.
→ It is associated with table or view.
→ It is not called explicitly and it is executed implicitly against the event taken place for a table.
→ It is stored in user_triggers table.
→ Event: - There are three different types of events those are insert, update and delete to trigger the trigger.
→ It doesn’t accept parameters and it is used to impose business rules on data, it can provide high security, it is
activated when tables are manipulated from the other software’s also.

Application Database

update Table
Update Trigger
Back End

FrontEnd Insert
Insert Trigger

Delete
Delete Trigger

→ Trigger Parts: - It indicates when to activate the trigger. These are two parts 1. Before, 2. After.
→ Trigger Types: - There are two types of triggers.
1.Row level trigger: - Trigger will be fired every row manipulated. To make a row level trigger use “for each
row” keyword.
2.Statement level or Table level trigger: - Trigger will be fired only once for DML statement and it is default
level Trigger.
→ Trigger Restriction
The Trigger condition mentioned in a when clause.
→ Trigger body contains a set of sql and pl/sql statements.
→ Trigger name can’t be duplicate. Trigger can be attached only one table at a time.
→ Trigger qualifiers: - There are two types of qualifiers. 1. New, 2. Old.
Qualifiers can use only in row level triggers.
:New.<Column name>
:Old.<Column name>
Qualifiers can’t be prefix with colon in the when condition of trigger.
When (:New) --- error
When (New) ---Execute
Insert Update Delete
New ✓ ✓ 
Old  ✓ ✓
Insert: - Insert into dept values (60,’Software’,’AP’);
:New.dname :Old,dname
Software

At the time of insert :Old.dname don’t have a value.


The :New.dname hav ethe value after insert.
Update: - Update dept set dname=’SOFTWARE’ where deptno=10;

36 | P a g e
:New.dname :Old.dname

SOFTWARE ACCOUNTING

:Old.dname have the value ACCOUNTING but replaced with SOFTWARE so that :New.dname contain
SOFTWARE.
Delete: - Delete dept where deptno=10;
:New.dname :Old.dname
ACCOUNTING

The :Old.dname contain value ACCOUNTING before delete, then :New.dname contain nothing after delete.
→ Kinds of Triggers
1.Application Trigger: - It is fired when DML event occurs within the application. Ex: Oracle forms.
2.Database Trigger: - It is fired when DML event occurs on a table or view, no matter which user is
connected. If validations are common for all applications, we can use Database Trigger.
Ex: - No transaction in weekend, No transaction before 9AM after 7PM, No Transaction in holidays.
→ Syntax
Create or replace trigger <trigger name>
Before/after insert/update/delete
[of column] on <table name>
[for each row]
When [condition]
[declare
Variable declaration];
Begin
<executable statements>;
Exception when condition then
<executable statements>;
End <trigger name>;
→ Write a pl/sql trigger to convert the account holder name in upper case?
CREATE OR REPLACE TRIGGER trg_uppcon
before insert or update
of name ON KCB_ACC_TAB
for each row
begin
:new.name:=upper(:new.name);
end trg_uppcon;
→ Write a pl/sql trigger to avoid the dname has no duplicate and not null from now onwards?
CREATE OR REPLACE TRIGGER trg_nnd
before insert or update
of dname ON DEPT
for each row
declare
cnt number;
begin
select count(dname) into cnt from dept where dname=:new.dname;
if :new.dname is null then
raise_application_error(-20345,'dname can not be null');
elsif cnt>0 then
raise_application_error(-20346,'dname can not be duplicate');
end if;
end trg_nnd;
37 | P a g e
→ Write a pl/sql trigger to perform 30000 withdraw only per day using trigger with function?
1st create a function
CREATE OR REPLACE function chk_wamt(paccno in kcb_acc_tab.accno%type,
pamt in kcb_tran2_tab.amt%type
)
return booleAn
is
wamt number;
begin
select sum(amt) INTO wamt from kcb_tran2_tab
where accno=paccno
and to_date(dot)=to_Date(sysdate)
and ttype='W'
and exists (select acctype from kcb_acc_tab where accno=paccno and acctype='S');

wamt:=wamt+pamt;

if wamt<30000 then
return true;
else
return false;
end if;
end chk_wamt;
2nd create trigger
CREATE OR REPLACE TRIGGER trg_chk_wamt
before insert
ON KCP_TRAN2_TAB
for each row
begin

if chk_wamt(:new.accno,:new.amt) then
upd_bal(:new.accno,:new.ttype,:new.amt);
else
raise_application_error(-20456,'Withdraw amount morethan 30000 so no transaction');
end if;

end trg_chk_wamt;
→ Write a pl/sql trigger to place the employee details after delete from emp table into delete_trace table
and also trace the empno, ename, job, sal, date of delete?
1st create a table
Create table delete_trace as select empno, ename, sal, deptno, hiredate ddate from emp where 1=2;
2nd create a trigger
create or replace trigger trg_del
after delete
on emp
for each row
begin
insert into delete_trace values(:old.empno, :old.ename, :old.sal, :old.deptno, sysdate);
end trg_del;
3rd delete rows from emp
Delete from emp where deptno=10;
38 | P a g e
For this example, suppose rows delete from emp is 3, so the trigger fired three times to delete 3 rows and
insert into trace table 3 times.
→ Write a pl/sql trigger to store the user and data delete information into a trace table after delete records
from emp table?
1st create a table trace
Create table trace1 (userid varchar2(20), dod timestamp);
2nd create a row level trigger
create or replace trigger trg_dell
after delete
on emp
for each row
begin
insert into trace1 values(user,sysdate);
end trg_dell;
For this example, suppose rows delete from emp is 4, so the trigger fired four times to delete 4 rows and
insert into trace table 4 times.
3rd create a table level trigger
create or replace trigger trg_dell
after delete
on emp
begin
insert into trace1 values(user,sysdate);
end trg_dell;
For this example, suppose rows delete from emp is 4, so the trigger fired four times to delete 4 rows and
insert into trace table only one time because it is table level trigger.
→ Write a pl/sql trigger to insert emp details automatically in bonus table as soon as insert into emp table?
1st create a table
create table bonus1(empno number,ename varchar2(100),sal number,job varchar2(30),comm number,dot
timestamp);
2nd create a trigger
create or replace trigger trg_bonus
after insert
on emp
for each row
declare
pragma autonomous_transaction;
begin
insert into bonus1 values (:new.empno,:new.ename,:new.sal,:new.job,:new.comm,sysdate);
commit;
end trg_bonus;
for this example, whenever we insert a row into emp table it automatically enters into bonus1 table. And if
we not using ‘PRAGMA AUTONOMOUS_TRANSACTION’ it gives error as ‘cannot commit in trigger’.
When we rollback emp transaction only rollback, but bonus table not effected.
→ Write a pl/sql trigger to trace the emp details after remove from the emp table those emp having sal
above 1500?
1st create a trace table
Create table trace (empno number, ename varchar2(30), sal number, userid varchar2(20), dod timestamp);
2nd create trigger
create or replace trigger trg_trace
after delete
on emp
39 | P a g e
for each row
when(old.sal>1500)
begin
insert into trace values(:old.empno,:old.ename,:old.sal,user,sysdate);
end trg_trace;
for this example, whenever we delete emp details from emp table whose sal is above 1500 these details are
entered into trace table automatically.
Trigger three events on a single table
→ Syntax
Create or replace trigger trg_name
Before/after insert or delete or update
On table_name
For each row
When <condition>
Begin
If inserting then
Sql statements;
End if;
If updating then
Sql statements;
End if;
If deleting then
Sql statements;
End if;
End trg_name;
→ Write a pl/sql trigger for,
if insert a record into emp table insert that details into int_tab table,
if update the emp records insert into upd_tab table,
if deleting any record from emp table insert that into del_tab table?
1st create tables
Create table int_tab (ecode number, name varchar2(50), sal number);
Create table upd_tab (ecode number, name varchar2(50), job varchar2(20));
Create table del_tab (ecode number, name varchar2(50), deptno number);
2nd create trigger
create or replace trigger trg_iud
after insert or update or delete
on emp
for each row
begin
if inserting then
insert into int_tab values(:new.empno,:new.ename,:new.sal);
end if;
if updating then
insert into upd_tab values(:new.empno,:new.ename,:new.job);
end if;
if deleting then
insert into del_tab values(:new.empno,:new.ename,:new.deptno);
end if;
end trg_iud;
→ Write a pl/sql trigger to accept employee sal in range between high_pay and low_pay according to their
job except president?
40 | P a g e
1st create a table
Create table job_list
As
Select job, min(sal) low_pay, max(sal) high_pay from emp group by job;
2nd create a trigger
create or replace trigger trg_js
before insert or update
on emp
for each row
when(new.job<>'PRESIDENT')
declare
lpay job_list.low_pay%type;
hpay job_list.high_pay%type;
begin
select low_pay,high_pay into lpay,hpay from job_list where job=upper(:new.job);
if :new.sal not between lpay and hpay then
raise_application_error(-20345,:new.job||' sal between '||lpay||' and '||hpay);
end if;
exception when no_data_found then
raise_application_error(-20346,:new.job||' job is not exists');
end trg_js;
→ Write a pl/sql trigger to stop the transaction on emp table based on following conditions
1.on week end days.
2.before 9AM and after 7PM.
3.in holidays.
1st create a holiday table
Create table holiday (hdate date);
Insert into holiday (’01-jan-2011’);
Insert into holiday (’26-jan-2011’);
Insert into holiday (’15-aug-2011’);
Insert into holiday (’25-dec-2011’);
Commit;
2nd create trigger
create or replace trigger trg_wht
before insert or update or delete
on emp
declare
cnt number;
begin
select count(*) into cnt from holiday where to_date(hdate)=to_date(sysdate);
if to_char(sysdate,'DY') in ('SAT','SUN') then
raise_application_error(-20345,'No transaction on weekend');
elsif cnt>0 then
raise_application_error(-20346,'No transaction on holiday');
elsif to_char(sysdate,'HH') not between 9 and 19 then
raise_application_error(-20347,'No transaction on this time');
end if;
end trg_wht;
→ Drop trigger
Drop trigger <trigger name>;
Drop trigger trg_wht;
41 | P a g e
→ How to disable or enable trigger on a table
Alter trigger <trigger name> enable;
Alter trigger <trigger name> disable;
Alter table <table name> disable all triggers;
Alter table <table name> enable all triggers;

Instead of triggers

→ It is a trigger on view and for each row is not required in instead of trigger.
→ It is used to manipulate views instead of insert, instead of update, instead of delete.
→ Example
Create or replace view v1
As
Select * from emp;

CREATE OR REPLACE TRIGGER trg_v


instead of delete
ON V1
begin
display ('recode is removed');
end;

delete from v1;


if 14 rows deleted from view v1 then result display 14 times as ‘record is removed’.
→ Example 2
Create or replace view ed
As
Select e.empno, e.ename, e.sal, d.deptno, d.dname from emp e, dept d where e.deptno=d.deptno;

Create or replace trigger trg_ed


Instead of delete
On ed
Begin
Delete from emp where deptno=:old.deptno;
Delete from dept where deptno=:old.deptno;
End trg_ed;

By using instead of trigger we can remove data from both tables when we delete data from ed view.

DDL Trigger

→ The only difference between DML and DDL is the firing event. DDL triggers are used to enforce rules or audit
the creation of database objects.
→ Event attribute functions()
1.ORA_DICT_OBJ_OWNER: - This function takes no formal parameters and it written owner of the object
acted upon by the event as a varchar datatype.
2.ORA_DICT_OBJ_NAME: - it written an object name as varchar datatype and this object name represents
target of the DDL statement.
→ Example
1st create a table
CREATE TABLE AUDIT_CREATION
(AUDIT_CREATION_ID NUMBER CONSTRAINT ACID PRIMARY KEY,
AUDIT_OWNER_NAME VARCHAR2(30) CONSTRAINT AUDIT_CREATION_NN1 NOT NULL,
42 | P a g e
AUDIT_OBJ_NAME VARCHAR2(30) CONSTRAINT AUDIT_CREATION_NN2 NOT NULL,
AUDIT_DATE DATE CONSTRAINT AUDIT_CREATION_NN3 NOT NULL);
2nd create a sequence
Create sequence audit_creation_s1;
3rd create a trigger
create or replace trigger trg_audit_creation
before create
on database
begin
insert into audit_creation values
(audit_creation.s1.nextval,ORA_DICT_OBJ_OWNER,ORA_DICT_OBJ_NAME,sysdate);
end trg_audit_creation;

PACKAGES

➢ It is a database object, it groups logically related pl/sql types, objects and sub programs.
➢ It has usually two parts. 1.Specification. 2.Body.
➢ Package can’t be invoked directly, can’t be parameterized, can’t be nested.
➢ It allows oracle server to read multiple objects into memory at once. It means when we call package pl/sql
construct for the 1st time the whole package is loaded into memory at once.
➢ Collection of related procedures and functions and variables is called package.
➢ Package will be stored in ‘all_source’, ‘all_object’, ‘dba_object’, ‘user_source’ tables.
➢ Components of package
1.specification
Syntax
Create or replace package pack1
Is/as
[public variable declaration]
[sub program bodied]
End;
2.Body
Syntax
Create or replace package body pack1
Is/as
[public variable declaration]
[sub program bodied]
End;
Example
1st step
Create or replace package pack1
Is
Procedure p1;
End pack1;
2nd step
Create or replace package body pack1
Is end;
Error: - in 2nd step we must use the procedure p1 in the package body.
Correct 2nd step
Create or replace package body pack1
Is
Procedure p1
43 | P a g e
Is
Begin
Null;
End p1;
End pack1;
Invoking package construct
execute packagename.procedure name(parameter list);
Model 1: - Execute pack1.p1(arg1, arg2….);
Model 2: - declare
Aa number;
Begin
Aa:=pack1.p1(arg1,arg2….);
End;
➢ Write a pl/sql package to display total of two numbers by procedure and multiplication of two numbers by
function?
1st create package specification
CREATE OR REPLACE package pack_pf
as
procedure add_num(m in number,n in number);
function mul_num(a in number,b in number)
return number;
result number; --global variable or public variable
end pack_pf;
2nd create package body
CREATE OR REPLACE package body pack_pf
as
procedure add_num(m in number,n in number)
is
begin
result :=m+n;
display('The sum of m,n is : '||result);
end add_num;
function mul_num(a in number,b in number)
return number
is
begin
result :=a*b;
display('The multiplication of a,b is : '||result);
end mul_num;
end pack_pf;
to call this
exec pack_pf.add_num(10,15);
declare
aa number;
begin
aa:=pack_pf.mul_num(10,2);
end;
➢ Write a pl/sql package to display gross sal to one function entered basic and display the experience in
years of entered joining date to another function?
1st create package specification
create or replace package pack_ge
44 | P a g e
as
function gross(pbasic in number)
return number;
function exp(pdoj date)
return number;
end pack_ge;
2nd create package body
create or replace package body pack_ge
as
function gross(pbasic number)
return number
is
begin
return(pbasic+pbasic*0.35+pbasic*0.45-pbasic*0.15);
end gross;
function exp(pdoj date)
return number
is
begin
return(round(months_between(sysdate,pdoj)/12));
end exp;
end pack_ge;
to call this
select pack_ge.gross(1000) gross,pack_ge.exp('01-jan-2000') experience from dual;
by using this package display the employee having more than 30 years of exp along with gross salary?
Select ename,sal,hiredate, pack_ge.gross(sal) gross,pack_ge.exp(hiredate) experience from emp where
pack_ge.exp(hiredate)>30;
➢ Remove or drop package
Drop package <package name>;
➢ Function overloading
Same function name with different signature used in a package is called function overloading.
Example 1
1st step: - CREATE OR REPLACE package pack_fo
as
function fo(psal in number,pcomm in number)
return number;
function fo(pname in varchar2,pjob in varchar2)
return varchar2;
end pack_fo;
2nd step: - CREATE OR REPLACE package body pack_fo
as
function fo(psal in number,pcomm in number)
return number
is
begin
return(psal+nvl(pcomm,0));
end fo;
function fo(pname in varchar2,pjob in varchar2)
return varchar2
is
begin
45 | P a g e
return(pname||' '||'job is '||pjob);
end fo;
end pack_fo;
to call this
select PACK_FO.FO(ename,job) from emp;
select PACK_FO.FO(sal,comm) from emp;
example 2
1st step: - CREATE OR REPLACE package pack_bt
as
procedure upd_bal(paccno in kcb_acc_tab.accno%type,
pttype in kcp_tran2_tab.ttype%type,
pamt in kcp_tran2_tab.amt%type
);
function chkk_bal(paccno in kcb_acc_tab.accno%type,
pamt in kcp_tran2_tab.amt%type
)
return boolean;
function fnow (paccno in kcb_acc_tab.accno%type
)
return number;
function fnot (paccno in kcb_acc_tab.accno%type
)
return number;
cbal kcb_acc_tab.bal%type;
end pack_bt;
2nd step: - CREATE OR REPLACE package body pack_bt
as
procedure upd_bal(paccno in kcb_acc_tab.accno%type,
pttype in kcp_tran2_tab.ttype%type,
pamt in kcp_tran2_tab.amt%type)
is
begin
select bal into cbal from kcb_acc_tab where accno=paccno;
if upper(pttype)='D' then
cbal:=cbal+pamt;
elsif upper(pttype)='W' then
cbal:=cbal-pamt;
end if;
update kcb_acc_tab set bal=cbal where accno=paccno;
commit;
end upd_bal;
function chkk_bal(paccno in kcb_acc_tab.accno%type,
pamt in kcp_tran2_tab.amt%type)
return boolean
is
vacctype kcb_acc_tab.acctype%type;
begin
select bal,acctype into cbaL,vacctype from kcb_acc_tab where accno=paccno;
cbal:=cbal-pamt;
if vacctype='S' and cbal<5000 then
return false;
46 | P a g e
elsif vacctype='C' and cbal<10000 then
return false;
end if;
end chkk_bal;
function fnow (paccno in kcb_acc_tab.accno%type)
return number
is
vnot number;
begin
select count(*) into vnot from kcp_tran2_tab where accno=paccno
and ttype='W'
and to_date(dot)=to_date(sysdate)
and exists (select 1 from kcb_acc_tab where accno=paccno and acctype='S');
return vnot;
end fnow;
function fnot (paccno in kcb_acc_tab.accno%type)
return number
is
vtotal_amt number;
begin
select sum(amt) into vtotal_amt from kcp_tran2_tab where accno=paccno
and ttype='W'
and to_date(dot)=to_date(sysdate)
and exists (select 1 from kcb_acc_tab where accno=paccno and acctype='s');
if vtotal_amt is null then
vtotal_amt :=0;
end if;
return vtotal_amt;
end fnot;
end pack_bt;
Important notes
Procedure Function
It may or mat not return a value. It must be return a value.
Procedure can’t call with select statement. Function can call with select statement.
Procedure do the action. Function do the calculation.
Procedure is used to store images. Function can’t used for images.
Procedure allows DML operations. It can’t perform DML operations.
Procedure is called as expression in another pl/sql Function value must be assign for a variable.
program.

Procedure Trigger
It is called explicitly. It is called implicitly against an event.
It accepts parameters. It is not accepting parameter.
It returns a value. It can’t return a value.
It can be nested. It can’t be nested.
It can create without table or view. It must be created on table or view.
It can’t execute specification and body separately. It is possible in trigger.

Note: - we can create max 12 triggers out of that 6 row level triggers and 6 table level triggers.

47 | P a g e
Dynamic SQL
→ In pl/sql we can’t perform DDL and DCL directly, we need dynamic sql for that situation.
→ Execute immediate: - this statement prepares an immediately executes a dynamic sql statement or
anonymous pl/sql block.
→ Syntax
Execute immediate dynamic_string
[into define variables] | record
[using [in/out/in out] bid_arguments]
→ Write a pl/sql procedure to drop the table which is passed to the parameter to a procedure?
CREATE OR REPLACE procedure drop_tab(tab_name in varchar2)
as
begin
execute immediate 'drop table '||tab_name||' purge';
end;
to invoke this
exec drop_tab(‘emp’);
note: - purge means permanently
→ Write a pl/sql program to give grant permission on selected table name?
begin
for i in (select 'grant select on '||table_name||' to public' cmd from user_tables
where table_name='emp')
loop
execute immediate i.cmd;
end loop;
exception when others then
display('error'||substr(sqlerrm,1,250));
end;
UTL Packages

➢ UTL package is outbound interface it means the data is transfer from oracle to outside.
➢ UTL_FILE: - It is one of the package and it is used to perform outbound interface.
Note: - UTL_FILE may not be recommended for inbound interface because
▪ It is low performance.
▪ You may not perform validation.
▪ In flash file data is very huge so the process will be very slow. That’s because we can use sql*loader
for inbound interface.
UTL_FILE contains three functions
1.UTL_FILE.FOPEN(): - It is used to open file to place the table data. If the file is already existing it will place
the data. If the file is not existing then create a file and place the data.
2.UTL_FILE.PUT_LINE(): - It is used to place the data into open file.
3.UTL_FILE.FCLOSE(): - It is used to close the file after putting the data.
➢ Steps to use UTL Packages
Step1: - create a directory of a database with reference of the operating system.
To check the UTL Directories
select * From v$parameter where name like ‘utl_file_dir’;
Step2: - connect to system/user;
Step3: - create a directory
Create directory NIT_UTL as ‘E:\\ORACLE\UTL’;
Step4: - all the database directories are stored in ‘dba_directories’.
Select * from DBA_DIRECTORIES;

48 | P a g e
Step5: - write a procedure
CREATE OR REPLACE PROCEDURE OUTBOUND
as
cursor c1 is
select empno,ename,job,hiredate,sal,deptno from emp;
id UTL_FILE.FILE_TYPE;
BEGIN
ID:=UTL_FILE.FOPEN('NIT_UTL','EMP.txt','W');
for i in c1
loop
UTL_FILE.PUT_LINE(id,i.empno||' '||i.ename||' '||i.job||i.hiredate||' '||i.sal||' '||i.deptno);
end loop;
UTL_FILE.FCLOSE(id);
END outbound;
Step6: - execute this
Exec outbound;

Flashback Query
→ If once the table is drop that is stored in the recycle bin. We will use the flash back query to get the drop
table back without using backup.
→ The flashback is introduced from oracle 10g.
→ It provides point in time, recovery without require a backup to restore.
→ If table is dropped ‘purge’ command we can’t get back the table because table permanently dropped.
→ We can flashback the table which is drop without ‘purge’ command. As soon as drop the table temporary
object will be available in the recycle bin.
→ Example
1st drop table
Drop table <table name>;
2nd flashback
Flashback table <table name> to before drop;

49 | P a g e

You might also like