Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

PLSQL

Download as doc, pdf, or txt
Download as doc, pdf, or txt
You are on page 1of 166

ORACLE

APPLICATIONS 11i & R12

SQL PLSQL

ORACLE APPS REPORTS XML PUBLISHER


REPORTS
INTERFACES CONVERSIONS

BI PUBLISHER FORM PERSONALIZATION


REPORTS

WORK FLOW DISCOVERER


REPORTS

TECHNICAL DOCUMENT PREPARATION

RESUME PREPARATION

MOCK INTERVIES

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

1
PLSQL STUDY MATERIAL

INDEX
S.NO NAME OF THE TOPIC PAGE NO.
1 INTRODUCTION OF PL/SQL 3-7
2 CONDITIONAL STATEMENTS 7-12
3 LOOP STATEMENTS 12-18
4 CURSOR 19-34
5 EXCEPTIONS 34-42
6 PROCEDURE 42-48
7 FUNCTIONS 49-65
8 PACKAGES 65-84
9 TRIGGERS 84-110
10 COLLECTIONS 110-137
11 ADVANCED PLSQL 137-160

INTRODUCTION OF PL/SQL

PL/SQL features ---


 PL/SQL is an extension of SQL
 It is an application development language containing procedural statements
and commands along with SQL commands
 It bridges the gap between database technology and procedural programming
languages
 It allows you to process data using flow control statements like iterative loops
and conditional branching
 Uses procedural techniques of control, looping and branching

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

2
 Supports SQL i.e. cursor operations, exceptions, functions and transactional
commands
 Variables and constants, robust error handling and functions
 Adds functionality to non-procedural tools such as SQL*Forms
 Developers using SQL*Forms can enter an entire PL/SQL block using a
single trigger

Structure of PL/SQL
 Standard PL/SQL code segment is called a Block
 A block consists of three parts or sections
 Declaration Part
 Executable Part
 Exception Handling Part

 Declaration Part
o optional part where variables are defined
 Executable Part
o mandatory part which consists of executable statements
 Exception Handling Part
o optional part which consists of code for handling errors
(runtime)

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

3
Variables :
 Used to store results of a query for later processing, or to calculate values to
be inserted into database tables
 Can be used anywhere in an expression, either in SQL or PL/SQL
statements
 Must be declared before referencing it in other statements, including other
declarative statements
 Are declared by specifying the name along with the datatype
 Can be declared to be of any datatype native to Oracle
 Examples

oldfare NUMBER(5);
m_name VARCHAR(15);

(Note – Set Serveroutput On has to be given when a session starts for displaying the
output statements_)
declare
x number;
begin
x := 67;
dbms_output.put_line(x);
dbms_output.put_line('The value of x is '|| x);
end;
Declaring variable in declare block:
 Assigning value in in begin block using := .
 Output statement is dbms_output.put_line
 Concatenation operator is ||
 Command terminator is ; after end

Declaring and initializing variables together


declare
y number := 100;
begin
dbms_output.put_line('The value of y is '|| y);
end;

Taking value from the user using &


declare
z number;
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

4
a varchar2(10);
begin
z := &z;
a := '&a';
dbms_output.put_line('Z is '|| z);
dbms_output.put_line('A is '|| a);
end;

/*Cannot declare or initialize more than one variable simultaneously*/


declare
a number;
b number;
c number;
begin
a := 67; b := 90; c := 87;
dbms_output.put_line(a);
dbms_output.put_line(b);
end;

A constant number has to declared and initialized in the declare block only
using
CONSTANT keyword. Value cannot be changed

declare
r CONSTANT number :=100;
begin
/* r := r + 100; Not possible*/
dbms_output.put_line(r);
end;

/*Assigning value to variable from a column of a table using select into clause*/
declare
x number;
begin

Select sal Into x from emp


where ename = 'SMITH';
dbms_output.put_line('Salary of Smith is '|| x);
end;
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

5
/* Selecting ename,sal from emp
Use of more than one columns value with Into clause*/
declare
n varchar2(50);
s number;
begin
select ename, sal Into n, s
from emp
where ename = 'SMITH';
dbms_output.put_line(n);
dbms_output.put_line(s);
end;

% Type Attribute –
 Provides datatype of a variable or column
 Useful when declaring a variable that refers to a column in a database
o exact datatype of column need not be known
o if column definition changes, variable datatype changes accordingly at
runtime
 Example
oldfare fare.first_fare%TYPE;
newfare oldfare%TYPE;

declare
a emp.ename%type;
b emp.sal%type;
c emp.deptno%type;
/*Using %TYPE attribute for variable data type*/
begin
select ename,sal,deptno
into a,b,c
from emp
where ename = 'KING';
dbms_output.put_line(a ||'-'|| b ||'-' || c);
end;

%RowType Attribute –

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

6
 Useful when declaring a record variable having same structure as a row in a
table or view, or as a row fetched from a cursor
 Fields in the record have same names and datatypes as the columns in the
table/view
 Example
 emp_rec employee%ROWTYPE;
 A specific field can be referenced using
 emp_rec.emp_num;

declare
E emp%rowtype;
/*rowtype attribute holds the datatype of the columns of the
entire row*/
begin
select * INTO E
from emp
where ename = 'MARTIN';
dbms_output.put_line(E.sal);
dbms_output.put_line(E.ename);
dbms_output.put_line(e.deptno);
end;

Conditional Statements – IF
 The selection structure tests a condition, then executes one sequence of statements
instead of another, depending on the condition
 There are three forms of statements
o IF-THEN
o IF-THEN-ELSE
o IF-THEN-ELSIF
 Sequence of statements is executed only if the condition evaluates to TRUE
 If condition evaluates to FALSE or NULL, it does nothing
 In either case control passes to next statement after the IF-THEN structure

IF <condition> THEN
statements;
END IF;
 Sequence of statements in the ELSE clause is executed only if the condition
evaluates to FALSE or NULL
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

7
IF <condition> THEN
statements;
ELSE
statements;
END IF;
--------------------------------------------------------------------------------
declare
/*Simple if condition */
x number;
begin
x := &x;
if x >= 35 then
dbms_output.put_line('Passed');
else
dbms_output.put_line('Failed');
end if;
end;
-----------------------------------------------------
IF-THEN-ELSIF Structure

 This construct allows selection of action from several mutually exclusive


alternatives
 The IF statement can have any number of ELSIF clauses
 The final ELSE is optional
 Conditions are evaluated one by one from top to bottom

Syntax
IF <condition1> THEN
statements;
ELSIF <condition2> THEN
statements;
ELSIF <condition3> THEN
statements;
ELSE
statements;
END IF;
Example 1 –
Declare
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

8
y number;
/*Multiple ifs */
Begin
y := &y;

if y >= 70 then
dbms_output.put_line('Distinction');
elsif y >= 60 then
dbms_output.put_line('First class');
elsif y >= 50 then
dbms_output.put_line('Second class');
elsif y >= 35 then
dbms_output.put_line('Passed');
else
dbms_output.put_line('Failed');
end if;
end;

Example 2
create table adm
(Name varchar2(30),
Marks number(3),
College varchar2(30),
Fees number(5));

/*Use of multiple if's


Accept name and marks from user.
Depending upon marks entered the college and fees should be decided
and the record should be entered in the adm table.*/

Declare
n adm.name%type;
m adm.marks%type;
c adm.college%type;
f adm.fees%type;

Begin
n := '&n';
m := &m;
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

9
if m >= 95 then
c := 'COEP';
f := 10000;
elsif m >= 90 then
c := 'MIT';
f := 15000;
elsif m >= 85 then
c := 'VIT';
f := 22000;
elsif m >= 80 then
c := 'D Y Patil';
f := 27000;
elsif m >= 75 then
c := 'Pune Vidyarthi';
f := 33000;
else
dbms_output.put_line('Cannot get admission');
end if;

if c is not null and f is not null then


dbms_output.put_line('Your College is '|| c || ' and fees are ' || f);
Insert into adm
values(n,m,c,f);
commit;
end if;

end;

Nested Blocks

declare
x number;

begin
x := 80;
dbms_output.put_line(‘abc’);
declare
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

10
y number;
begin
y := 90;
dbms_output.put_line('Inner Block variable value ' || y);
end;

dbms_output.put_line('Outer Block variable value ' || x);


end;

Scope of variables

A variable declared in the outer block is accessible in the inner block. But a variable
declared in the inner block is accessible only in the inner block.

declare
outer number;
begin
outer := 80;
declare
inner number;
begin
inner := 90;
dbms_output.put_line('Inner Block variable value ' || inner);
dbms_output.put_line('Outer block variable is accessible in the inner
block’);
dbms_output.put_line('Outer block variable value ' || outer);
end;

dbms_output.put_line('Outer Block variable value ' || outer);


dbms_output.put_line('Inner Block variable value ' || inner);
end;
/

Labels

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

11
If the variables names of the outer and inner blocks are same then labels have to be
used within the inner block to avoid ambiguity.

<<outer_block>>
declare
x number;
begin
<<inner_block>>
declare
x number := 100;
begin
dbms_output.put_line('Value of the inner block x is ' || x);
-- Giving value of x of the inner block to the outer block x
outer_block.x :=inner_block. x;
end;

x := x + 500;
dbms_output.put_line('Value of the outer block x is ' || x);
end;
/
LOOPS
 The ability to repeat or skip sections of a block can be achieved with the usage of
LOOP or GOTO statements
 There are three forms of the LOOP statement
– LOOP
– WHILE-LOOP
– FOR-LOOP
LOOP Statement
 LOOP repeats a sequence of statements
 Statements to be repeated are placed between keyword LOOP and END LOOP
 With each iteration of the loop, the sequence of statements is executed, then
control resumes at the top of the loop
LOOP
statements;
END LOOP;

EXIT Statement

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

12
 Used to complete a loop if further processing in a loop is undesirable or
impossible
 There are two forms of the EXIT statement
o EXIT
o EXIT-WHEN
 Forces a loop to complete unconditionally
 Must be placed inside a loop
LOOP
statements;
IF <condition> THEN
EXIT; -- exit loop immediately
END IF;
END LOOP;
-- control resumes here

Example of Loop –
/*To show 1 to 10 on screen*/

Declare
x number;
Begin
x := 1;
Loop
dbms_output.put_line(x);
x := x + 2;
exit when x > 10;
End Loop;
dbms_output.put_line(‘end’);
End;

create table five


(no number);
/*Inserting multiples of five in table five*/

Declare
x number;
Begin
x := 5;
Loop
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

13
Insert into five
values(x);
x := x + 5;
exit when x > 50;
End Loop;
End;

FOR LOOP
Advantages --
1) No need of declaring loop variable
2) No need of giving condition
3) No need of updation statement (increment or decrement )
4)Code becomes small and compact
Disadvantage --
Updation can be done by only one.

Syntax –
FOR <counter> IN [REVERSE]
lower_bound .. higher_bound LOOP
statements;
END LOOP

Example 1 of for loop


/*To show 1 to 10 on screen*/

begin
for x in 1..10
Loop
dbms_output.put_line(x);
End Loop;
end;

Example 2
/*Reverse for loop 10,9,8 … 1*/

Begin
for i in REVERSE 1 ..10
Loop
dbms_output.put_line(i);
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

14
End Loop;
end;

Example 3 –
Calculating compound interest for a principal of Rs.100 @10% for each year.
Values will be shown of the CI after each year.

create table CI_100


(year number(2),
total number(4));
----------------------------------
Declare
p number := 100;
tot number;
/*Calculation of compound interest.
Rs.100 is principal.
Rate of interest is 10%.
Period is 5 years.
*/
Begin
for y in 1..5
Loop
/* Tot variable is getting 10% more than p */
tot := p + p * 0.10;
Insert into CI_100
values(y,tot);
/*Since the next interest is based on the current interest
so the tot will be considered as p for the next year*/
p := tot;
End Loop;
end;

WHILE-LOOP Statement

 Associates a condition with a sequence of statements enclosed within LOOP-END


LOOP
 Condition evaluated before each iteration

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

15
 If condition evaluates to TRUE, sequence of statements is executed and control
resumes at the top of the loop
 If condition evaluates to FALSE or NULL, loop is bypassed and control passes to
next statement
 Number of iterations depends on the condition and is unknown until the loop
completes
WHILE <condition>
LOOP
statements;
END LOOP;

Example 1 of while loop to show 1 to 15

declare
x number;
Begin
x := 1;
while x <=15
Loop
dbms_output.put_line(x);
x := x + 1;
End Loop;
end;

Example 2 Forces a loop to complete unconditionally


declare
z number;
/*Using break after z reaches to 8*/
Begin
z := 1;
while z <=15
Loop
dbms_output.put_line(z);
z := z + 1;
exit when z = 8;
End Loop;
end;

While Loop v/s Basic Loop


REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

16
While Loop
declare
x number;
Begin
x := 1;
while x > 15
Loop
dbms_output.put_line(x);
x := x + 1;
End Loop;
dbms_output.put_line('End of program');
end;
/

The loop will never get executed since the condition is wrong from the start of the
iteration.

Basic Loop

Declare
x number;
Begin
x := 1;
Loop
dbms_output.put_line(x);
exit when x = 1;
x := x + 1;
End Loop;
dbms_output.put_line('End of program');
End;
/

The loop gets executed at least once.

Nested Loops

create table discount_details


REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

17
(quarter number(2),
month number(2),
discount varchar2(5));

Expected Output –

QUARTER MONTH DISCOUNT

1 1 12%
1 2 11%
1 3 10%
2 4 9%
2 5 8%
2 6 7%
3 7 6%
3 8 5%
3 9 4%
4 10 3%
4 11 2%
4 12 1%

12 rows selected.

declare
q number;
m number;
d number;
dis varchar2(10);
c number;

begin
q := 1;
m := 0;
d := 12;

loop
exit when q > 4;
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

18
c := 0;
loop
exit when c >= 3;
m := m + 1;
dis := d || '%';
insert into discount_details
values(q,m,dis);
d := d - 1;
c := c + 1;
end loop;
q := q + 1;
end loop;

end;

Cursors:

 To process a SQL statement, PL/SQL opens a work area called a context area.
 PL/SQL uses this area to execute SQL statements and store processing
information
 A PL/SQL construct called ‘Cursor’ allows you to name a context area, access its
information and in some cases, control its processing

Explicit Cursors
Defined by the user to keep track of which row is being processed, when a query returns
multiple rows

Defining a Cursor
 A cursor is defined in the declarative part of the PL/SQL block by naming it and
associating it with a query
CURSOR <cursorname> IS
<SELECT statement>;
 Example
CURSOR emp_cur IS
SELECT empno, ename, job, sal
FROM emp;

 A Cursor can be manipulated using

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

19
– OPEN
– FETCH
– CLOSE
 Cursor must be declared before it can be referenced using the OPEN, CLOSE or
FETCH statements

The OPEN Statement


 Initializes or opens a cursor
 Cursor must be opened before any rows are returned by the query
OPEN <cursorname>
Example --
OPEN emp_cur;

The FETCH Statement


 Can be executed repeatedly until all rows have been retrieved
FETCH <cursorname> INTO var1, …, varn;
OR
FETCH <cursorname> INTO record_variable;
 Example
FETCH emp_cur INTO mrec;

The CLOSE Statement


 Closes the cursor and makes the active set undefined
CLOSE <cursorname>;
 Example
CLOSE emp_cur;

 Once a cursor is closed, it can be reopened by using the OPEN statement

Attributes of Explicit Cursors

 Every cursor has four attributes that can be used to access the cursor’s context
area
– %NOTFOUND
– %FOUND
– %ROWCOUNT
– %ISOPEN
 To use these attributes, simple append them to the name of the cursor
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

20
 %NOTFOUND
– evaluates to TRUE if last FETCH failed because no more rows were
available
– evaluates to FALSE if last FETCH returned a row
 %FOUND
– evaluates to TRUE if last FETCH returned a row
– evaluates to FALSE if last FETCH failed because no more rows were
available
 %ROWCOUNT
– returns the number of rows FETCHed from the active set so far
 %ISOPEN
– evaluates to TRUE if an explicit cursor is open
– evaluates to FALSE if an explicit cursor is closed
Examples of Cursor –
1)
To transfer names and sal of employees from emp table where sal >= 2500 in table
try1
create table try1
(no number,
ename varchar2(50),
sal number);

Declare
Cursor cf is
select ename,sal
from emp
where sal >= 2500;
M cf%rowtype;
N number;
Begin
Open cf;
N := 0;
Loop
Fetch cf into M;
Exit when cf%notfound;
N := cf%rowcount;

Insert into try1


REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

21
values(N,M.ename,M.sal);
End Loop;

Close cf;
End;

2) Use of %FOUND attribute

Accepting the job from user and finally showing how many such jobs are there.

Declare
Cursor cf is
select *
from emp
where job ='&J';

M cf%rowtype;

N number;

J Emp.Job%type;

Begin
Open cf;
N := 0;
Loop
Fetch cf into M;
Exit when cf%notfound;

If cf%found then
N := N + 1;
End if;
End Loop;
Close cf;
If N > 0 then
dbms_output.put_line('Total number of job ' || J || ' is '|| N);
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

22
else
dbms_output.put_line('No such job');
End If;
End;
----------------------------------------------------------------------

3) Use of IsOpen attribute


Declare
Cursor cf is
select ename, deptno
from emp
where deptno = 20;
M cf%rowtype;
/*The cursor is not opened before Loop. So using IsOpen attribute to open the
cursor if it is not open.*/
Begin
/* Cursor is not opened!!! */
Loop
If cf%IsOpen then
Fetch cf into M;
else
Open cf;
dbms_output.put_line('Cursor is now opened');
End if;
exit when cf%notfound;
dbms_output.put_line(M.ename ||'--' || M.deptno);
End Loop;
End;
--------------------------------------------------------------------------------------
4) Transferring the first five records from emp table into another table FirstFive

create table firstfive


as
select empno,ename,sal,deptno
from emp
where 1=2;

Declare
Cursor cf is

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

23
Select *
from emp;
M cf%rowtype;
N number;
Begin
Open cf;
N := 1;
while N <= 5
Loop
Fetch cf into M;
Insert into firstfive
values(M.empno,M.ename,M.sal,M.deptno);
N := N +1;
End Loop;
End;

5) Displaying the 3rd record entered in the table emp –

Declare
Cursor cf is
select *
from emp;
M cf%rowtype;
Begin
Open cf;
Loop
fetch cf into M;
if cf%rowcount = 3 then
dbms_output.put_line(M.empno||'-'||M.ename||'-'||M.sal||'-'||M.deptno);
end if;
exit when cf%notfound;
End Loop;
End;

6) To see the first person( or first record entered) who has got salary > 2800
Declare
Cursor cf is
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

24
select *
from emp
where sal > 2800;
M cf%rowtype;
Begin
Open cf;
Loop
fetch cf into M;
if cf%rowcount = 1 then
dbms_output.put_line(M.empno||'-'||M.ename||'-'||M.sal||'-'||M.deptno);
exit;
end if;

End Loop;
End;

Cursor FOR Loop


 Implicitly declares its loop index as a record of %ROWTYPE,
 Implicitly opens the cursor
 Repeatedly fetches rows of values from the active set into fields in the record
 Implicitly closes the cursor when all rows have been processed or the loop is
exited
 The statements in the loop construct are executed once for each row that satisfies
the query associated with the cursor name
 Cursor FOR loop is used to simplify coding
 No need of --
1)Open cursor
2)Fetch
3)Exit
4)Close cursor

7) To show records where salary is > 3000


Declare
Cursor cf is
select *
from emp
where sal >= 3000;
Begin
For mrec in cf
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

25
Loop
dbms_output.put_line(mrec.ename||' '||mrec.sal||' '||mrec.deptno);
End Loop;
End;

For Loops using sub queries


No need of declaring cursor.

A private cursor within an anonymous block can be created.

To show names of employees who have job MANAGER.

begin
for MREC in (select * from emp)
Loop
if MREC.job = 'MANAGER' then
dbms_output.put_line('Name is ' ||MREC.ename);
end if;
END LOOP;
end;
Parameterized Cursor
The same cursor can be reopened and closed with different active sets.

declare
cursor cf(pjob emp.job%type)
is
select empno,ename,job,sal
from emp
where job = pjob;
M cf%rowtype;
begin
open cf('ANALYST');
LOOP
FETCH CF INTO M;
EXIT WHEN CF%NOTFOUND;
dbms_output.put_line(M.ename);
end loop;
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

26
close cf;
open cf('CLERK');
LOOP
FETCH CF INTO M;
EXIT WHEN CF%NOTFOUND;
dbms_output.put_line(M.ename);
end loop;
close cf;
open cf(‘MANAGER’);
LOOP
FETCH CF INTO M;
EXIT WHEN CF%NOTFOUND;
dbms_output.put_line(M.ename);
end loop;
close cf;

END;

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

27
Cursor FOR UPDATE OF and CURRENT OF
 CURRENT OF clause is used in an UPDATE or DELETE statement to refer to
the current row of the cursor
 The cursor must be declared with the FOR UPDATE OF clause and must be open
and positioned on a row
 If the cursor is not open, CURRENT OF clause results in an error
8) Example of Cursor FOR UPDATE OF and CURRENT OF

create table esal


(empno number,
sal number);

insert into esal


values(1,16000);
insert into esal
values(2,14000);
insert into esal
values(3,8000);
insert into esal
values(4,6500);
insert into esal
values(5,9000);
insert into esal
values(6,11000);
insert into esal
values(7,5500);
insert into esal
values(8,3500);
insert into esal
values(9,2200);
insert into esal
values(10,7000);

Multiple updations depending on the salary clause in one pl/sql block –

Declare
Cursor cf is
select * from esal

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

28
For Update of sal;
M cf%rowtype;

Begin
Open cf;
Loop
Fetch cf into M;
exit when cf%notfound;

If M.Sal >= 16000 Then


M.Sal := 20000;

ElsIf M.Sal >= 14000 Then


M.Sal := 18200;

ElsIf M.Sal >= 12000 Then


M.Sal := 16700;

ElsIf M.Sal >= 10000 Then


M.Sal := 13500;

ElsIf M.Sal >= 8000 Then


M.Sal := 11000;

ElsIf M.Sal >= 6000 Then


M.Sal := 9500;

ElsIf M.Sal >= 4000 Then


M.Sal := 7500;

Else
M.Sal := 5000;

End If;

Update esal
set sal = M.Sal
Where Current Of cf;
End Loop;

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

29
End;

Implicit Cursors
• Automatically defined and opened, by Oracle, to process each
SQL statement
• most recently opened context area is referred to as a ‘SQL%’
cursor

Attributes of Implicit Cursors

 Although OPEN, CLOSE and FETCH statements cannot be used to manipulate


the SQL% cursor, the attributes can be used to access its context area
 Attributes evaluate to NULL, before the cursor is opened automatically
 The following four cursor attributes can be used to access the SQL%
cursor’s context area
 SQL%NOTFOUND
 SQL%FOUND
 SQL%ROWCOUNT
 SQL%ISOPEN
 SQL%NOTFOUND
 evaluates to TRUE if an INSERT, UPDATE or DELETE statement
affected no rows, else it evaluates to FALSE
 SQL%FOUND
 logical opposite of SQL%NOTFOUND
 evaluates to TRUE if an INSERT, UPDATE or DELETE affected one or
more rows, else it evaluates to FALSE

 SQL%ROWCOUNT
– returns the number of rows affected by an INSERT, UPDATE or DELETE
statement
 SQL%ISOPEN
– Oracle automatically closes an implicit cursor after executing its
associated SQL statement
– For an implicit cursor SQL%ISOPEN always evaluates to FALSE

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

30
9) Example of Implicit Cursors
Begin

Delete from emp


where ename = '&name';

If SQL%Found Then
dbms_output.put_line('Record found and it is deleted');
End If;

If SQL%NotFound Then
dbms_output.put_line('No record is present of the given name.');
End If;

End;

10) Implicit Cursor for rowcount

Declare
C number; := 0;
Begin
Update Emp
set sal = sal + 500
where deptno = &deptno;

/*If no record is updated since the deptno supplied is wrong then giving
the customised error message.*/
If SQL%Rowcount = 0 then
dbms_output.put_line('No records are updated since the department number entered
is not in the table.');
End if;

/*To prevent sal to be updated where deptno is > 3 */


If SQL%RowCount > 3 then
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

31
Rollback;
dbms_output.put_line('Cannot update since there are more than 3 deptnos');
End If;

If SQL%RowCount Between 1 and 3 then


c := SQL%RowCount;
dbms_output.put_line(c || ' records updated.');
End If;
End;

REF CURSORS
Limitations of a normal cursors are --
1) A PL/SQL program cannot pass a cursor as a parameter to another program.
2) A PL/SQL program can only open the cursor and process the information within
the program itself.

To overcome these limitations there is a concept of REF CURSOR.

Features of REF CURSOR --


1) There can be a TYPE of ref cursor. The variable of this TYPE can be used to
pass the parameters to a program and return value from the cursor.
2) The variable of REF CURSOR type returns the same data type as the cursor
variable.
3) The cursor variable is passed as a parameter to a procedure.
4) The cursor variable takes all the rows from the specified table.
5) These rows are given to the bind variable.
So the parameter passed should satisfy two conditions --
a) The parameter should be taken from the TYPE of Ref Cursor.
b) It should be of IN OUT mode.
6) Finally the data retrieved by the cursor variable can be seen through the bind
variable. For this the data type of the bind variable should be REFCURSOR.
7) While executing the procedure bind variable should be directly given. And then by
print statement the data is displayed.
8) The cursor variable's data structure and the procedure block's data structure should
be same.

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

32
Advantage of REF CURSOR--

Actually we can get the view of the entire data of the table with simplicity using
REF CURSOR.
Without using ref cursor if we have to achieve this then, the parameter passed will
be of variable type
and then the user has to manual loop using cursor to fetch all the records. Here in
REF CURSOR there is no need of looping.
Example of REF CURSOR

Package Specification

create or replace package PRC as

TYPE EmpRC IS REF CURSOR RETURN emp%rowtype;


TYPE DeptRC IS REF CURSOR RETURN dept%rowtype;

Procedure EmpDetails(ve IN OUT EmpRC);


Procedure DeptDetails(vd IN OUT DeptRC);

End PRC;
Package Body –

create or replace package Body PRC as

Procedure EmpDetails(ve IN OUT EmpRC)


is
Begin
Open ve FOR select * from emp;
End EmpDetails;

Procedure DeptDetails(vd IN OUT DeptRC)


is
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

33
Begin
Open vd FOR select * from dept;

End DeptDetails;

End PRC;

For executing the procdure –


1) SQL > variable E REFCURSOR
SQL > variable D REFCURSOR

2) To see the data from the bind variable --


SQL > Set AutoPrint ON

3) SQL > Execute PRC.EmpDetails(:E);


4) SQL > Execute PRC.DeptDetails(:D);

EXCEPTIONS

Introduction to Exceptions

 An error condition is called an Exception


 When an error occurs, an exception is raised i.e. normal execution stops and
control transfers to the exception handling part of the PL/SQL block or
subprogram
 To handle raised exceptions, separate routines called exception handlers are
written

 There are two types of exceptions


o Pre-defined exceptions (Internal Exceptions)
o User-defined exceptions
 You cannot declare an exception twice in the same block, but can declare the
same exception in two different blocks
 Exceptions declared in a block are local to that block and global to all its sub-
blocks
 Enclosing blocks cannot reference exceptions declared in a sub-block because
blocks can only reference local or global exceptions
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

34
Predefined Exceptions
 Are implicitly raised whenever a PL/SQL block violates an Oracle rule or exceeds
a system-dependent limit
 Every Oracle error has a number, but exceptions must be handled by name
 PL/SQL predefines some common Oracle errors as exceptions
 These predefined exceptions are declared globally by PL/SQL
 Some Pre-defined Exceptions
o CURSOR_ALREADY_OPEN
o NO_DATA_FOUND
o TOO_MANY_ROWS
o VALUE_ERROR
o ZERO_DIVIDE

 More than one exception can be handled in a single exception handler by


separating them with the keyword OR
EXCEPTION
WHEN NO_DATA_FOUND OR TOO_MANY_ROWS THEN
statements;
WHEN OTHERS THEN
statements;
END;

Examples of Exception handling –


1) NO_DATA_FOUND error (Variable is not having any value.)

declare
n emp.ename%type;
s emp.sal%type;
begin
select sal into s
from emp
where ename = '&n';
dbms_output.put_line('Salary is '|| s);

/* Exception
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

35
When NO_DATA_FOUND then
dbms_output.put_line('No record'); */
end;

2) TOO_MANY_ROWS error (Variable is having more than one value)

declare
s emp.sal%type;
begin
select sal into s
from emp;
dbms_output.put_line('The salary is '|| s );
Exception
When TOO_MANY_ROWS then
dbms_output.put_line('Variable can hold only one value at a time');
dbms_output.put_line('Please specify the name of person for getting the
salary');
end;

3) ZERO_DIVIDE error (A number divided by zero)


declare
x number;
y number;
z number;
begin
x := &x;
y := &y;
z := x/y;
dbms_output.put_line('The answer is ' || z);

Exception
When ZERO_DIVIDE then
dbms_output.put_line('Cannot divide by zero!!!');
end;

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

36
4) DUP_VAL_ON_INDEX error (When a duplicate value is entered in a column
having Unique constraint)
declare
e emp.empno%type;
begin
e := &e;
insert into emp (empno )
values(e);
dbms_output.put_line('Successful');
Exception
When DUP_VAL_ON_INDEX then
dbms_output.put_line('Value already exists');
end;

5) VALUE_ERROR (Error in conversion of string to number)

declare
n number;
begin
n := '&n';
dbms_output.put_line(n);
Exception
When VALUE_ERROR then
dbms_output.put_line('Please enter number only');
end;

6) OTHERS (If no error handler works then at least OTHERS will work)

declare
x number;
y number;
z number;
begin
x := &x;
y := &y;
z := x/y;
dbms_output.put_line('The answer is ' || z);
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

37
Exception
When too_many_rows then
dbms_output.put_line('More than one value');
When no_data_found then
dbms_output.put_line('No value');
/*When OTHERS then
dbms_output.put_line('Some run time error has occurred');
dbms_output.put_line('Please execute the program again with proper values.');
rollback;*/
end;

Pragma Exception

create table dept1(deptno number primary key, dname varchar2(10));


create table emp1(empno number, ename varchar2(10),
deptno number references dept1(deptno));
insert into dept1 values(10,'Acc');
insert into emp1 values(1,'abc',10);

PRAGMA  PRAGMA EXCEPTION_INIT tells the compiler to associate an


exception name with an Oracle error number. That allows you to refer to any
internal exception by name and to write a specific handler for it.

declare
referential_integrity EXCEPTION;
PRAGMA EXCEPTION_INIT( referential_integrity, -2292);
begin
Delete from dept1
where deptno = &deptno;
commit;
exception
when referential_integrity then
dbms_output.put_line('The record cannot be deleted, because related record found in
emp1 table');
end;
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

38
SQLCODE AND SQLERRM
SQLCODE  Returns the numeric value for the error code.
SQLERRM  Returns the message associated with the error number.

create table error_log(error_number number, error_message varchar2(255));

declare
s emp.sal%type;
v_error_code number;
v_error_message varchar2(255);
begin
select sal into s from emp;
exception
when others then
v_error_code := SQLCODE;
v_error_message := SQLERRM;
Insert into error_log values(v_error_code, v_error_message);
commit;
end;

Exception Handlers in nested block to continue after run time error comes

declare
loan_amt number;
no_of_months number;
installment_rate number;
roi number;
tot_amt number;
begin
loan_amt := &loan_amt;
no_of_months := & no_of_months;
begin
installment_rate := loan_amt / no_of_months;
exception
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

39
when zero_divide then
no_of_months := 3;
installment_rate := loan_amt / no_of_months;
end;
/* In any case the last 3 lines will get executed */

roi := installment_rate * 0.2; -- 20% roi


tot_amt := roi + loan_amt;
dbms_output.put_line('The total amount to be paid is '|| tot_amt);
end;

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

40
User-defined Exceptions

 User-defined exceptions need to be defined in the declarative part of a PL/SQL


block, subprogram or database trigger
 Declared by naming the exception and defining it as datatype EXCEPTION
 Example
DECLARE
past_due EXCEPTION;
zero_error EXCEPTION;

 Like variables, user-defined exceptions must be given names


 Unlike variables, user-defined exceptions cannot be assigned values and cannot be
used in SQL statements
 They need to be raised explicitly using the RAISE statement

 A block should RAISE an exception only when an error makes it impossible or


impractical to finish processing
 RAISE statement for a given expression can be coded anywhere within the scope
of that expression
IF mrec.ss_fare <= 0 THEN
RAISE zero_error;
END IF;

 An exception raised inside a handler immediately propagates to the enclosing


block, which is searched to find a handler for the newly raised exception
 From there on, the exception propagates normally
 To re-raise an exception place a RAISE statement in its local handler

Example of Exception variable using Raise key word


declare
p number;
n number := 6;
si number;
r number := 10.5;
EX exception;

Begin

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

41
p := &p;
if p < 100 then
raise EX;
else
si := (p * n * r) / 100;
dbms_output.put_line('The Simple Interest is '|| si);
end if;
Exception
When EX then
dbms_output.put_line('The principle amt should be greater than or equal to
100.');
end;
--------------------------------------------------------------------------------------

RAISE_application_error

This can be used to create user defined error message, which can be more
descriptive than named exceptions.

Syntax - :
Raise_application_error(error number,error message);
where error number is any parameter between -20,000 and -20,999.Error message
is text that is associated with this error. The message parameter must be less than 512
characters.

Example of Raise_application_error
declare
maths number;
Begin
maths := &maths;

if maths < 35 then


raise_application_error(-20001,'Failed');
else
dbms_output.put_line('Passed');
end if;
end;
---------------------------------------------------------------------------------------------------

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

42
Example of Raise_application_error and error handling together –

declare
x number;
begin
x := '&x';
if x < 0 then
raise_application_error(-20009,'ty');
end if;
exception
when value_error then
dbms_output.put_line('ff');
end;

Procedures:

1. What is a Procedure?
A Procedure is a PL/SQL sub program used to perform an action (transaction) which
takes parameters as input and returns out put.

2. What does a procedure consists?


Procedure consists is PL/SQL block (code) which consists a declarative part, an
executable part, and an optional exception-handling part.

A procedure is compiled and stored in the database as a schema object. Procedures


promote reusability and maintainability. When validated, they can be used in any number
of applications. If the requirements change, only the procedure needs to be updated.

Oracle Procedures has the following


 Declarative part,
 Executable part,
 Exception-handling part.

The declarative part contains the following and these items are local and cease to exist
when you exit the subprogram.
 Declarations of types,

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

43
 Cursors ( Names Control Structures)
 Constants,
 Variables
 Exceptions
 Nested subprograms.

The executable part contains


 Statements that assign values
 Control execution
 Manipulate Oracle data.

Exception-handling part
The exception-handling part contains exception handlers, which deal with exceptions
raised during execution.

3. What is the Syntax of the PROCEDURE?

PROCEDURE name [ ( parameter [, parameter ... ] ) ]


IS
[declaration statements]

BEGIN
executable-statements

[ EXCEPTION
exception handler statements]

END [ name ];
where each component is used in the following ways:
name
The name of the procedure comes directly after the keyword PROCEDURE.
parameters
An optional list of parameters that you define to both pass information into the procedure
and send information out of the procedure, back to the calling program.
declaration statements
The declarations of local identifiers for that procedure. If you do not have any
declarations, then there will not be any statements between the IS and BEGIN statements.
executable statements

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

44
The statements that the procedure executes when it is called. You must have at least one
executable statement after the BEGIN and before the END or EXCEPTION keywords.
exception handler statements
The optional exception handlers for the procedure. If you do not explicitly handle any
exceptions, then you can leave out the EXCEPTION keyword and simply terminate the
execution section with the END keyword.
Below figure shows the apply_discount procedure, which contains all four sections of the
named PL/SQL block, as well as a parameter list.
The apply_discount procedure

Calling a Procedure
A procedure is called as an executable PL/SQL statement. In other words, a call to a
procedure must end with a semicolon (;) and be executed before and after other SQL or
PL/SQL statements.
The following executable statement runs the apply_discount procedure:
apply_discount( new_company_id, 0.15 ); -- 15% discount

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

45
If the procedure does not have any parameters, then you must call the procedure without
any parentheses:
display_store_summary;
Procedure Header
The portion of the procedure definition that comes before the IS keyword is called the
procedure header. The header provides all the information a programmer needs to call
that procedure, namely:
 The procedure name
 The parameter list, if any
A programmer does not need to know about the inside of the procedure in order to be
able to call it properly from another program.
The header for the apply_discount procedure discussed above is:
PROCEDURE apply_discount
(company_id_in IN company.company_id%TYPE,
discount_in IN NUMBER)
It consists of the module type, the name, and a list of two parameters.
Procedure Body
The body of the procedure is the code required to implement the procedure. It consists of
the declaration, execution, and exception sections of the function. Everything after the IS
keyword in the procedure makes up that procedure's body.
Once again, the declaration and exception sections are optional. If you have no exception
handlers, you will leave off the EXCEPTION keyword and simply enter the END
statement to terminate the procedure.
If you do not have any declarations, the BEGIN statement simply follows immediately
after the IS keyword (see the do_nothing procedure below for an example of this
structure.).
You must supply at least one executable statement in a procedure. Here is my candidate
for the procedure in PL/SQL with the smallest possible body:
PROCEDURE do_nothing IS
BEGIN
NULL;
END;
Does the do_nothing procedure seem silly? A procedure that doesn't do anything can, in
fact, be very useful when you are creating stubs for modules in a top-down design effort.
I have also used this kind of procedure when building templates. My do_nothing
procedure acts initially as a placeholder in my code, but then also provides a mechanism
for customization of the templates.

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

46
The END Label
You can append the name of the procedure directly after the END keyword when you
complete your procedure, as shown below:
PROCEDURE display_stores (region_in IN VARCHAR2) IS
BEGIN
...
END display_stores;
This name serves as a label that explicitly links up the end of the program with its
beginning. You should as a matter of habit use an END label. It is especially important to
do so when you have a procedure that spans more than a single page, or is one in a series
of procedures and functions in a package body.

4. What is meant by Forward Declaration?

PL/SQL requires that you declare an identifier before using it. Therefore, you must
declare a subprogram before calling it. In Forward declaration an identifier is declared
before it is used. Therefore a subprogram is declared before calling it.

Although the formal parameter list appears in the forward declaration, it must also appear
in the subprogram body. You can place the subprogram body anywhere after the forward
declaration, but they must appear in the same program unit

For example, the following declaration of procedure calc_rating is illegal because


award_bonus calls procedure calc_rating.

DECLARE
PROCEDURE calc_rating (...); -- forward declaration
...
/* Define subprograms in alphabetical order. */
PROCEDURE award_bonus (...) IS
BEGIN
calc_rating( ... );
...
END;
PROCEDURE calc_rating (...) IS
BEGIN
...
END;

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

47
What are the Parameter Modes in Procedure?

5. There are three procedural parameter modes

 IN (the default),
 OUT Parameter

 IN OUT Parameter

6. IN Mode

An IN parameter lets you pass values to the subprogram being called. Inside the
subprogram, an IN parameter acts like a constant. Therefore, it cannot be assigned a
value.

PROCEDURE validate_input(l_input_rec IN INPUT_REC_TYPE,

v_return_status OUT VARCHAR2 ,


v_return_message OUT VARCHAR2
)
IS
v_source_system VARCHAR2(150);
v_source_system_identifier VARCHAR2(150);
v_notes VARCHAR2(2000);
v_status VARCHAR2(30) ;
v_service_request_number VARCHAR2(64) ;
v_input_type VARCHAR2(30) ;
v_attribute_name VARCHAR2(30) ;

7. OUT Mode

An OUT parameter lets you return values to the caller of a subprogram. Inside the
subprogram, an OUT parameter acts like a variable. That means you can use an OUT
formal parameter as if it were a local variable. You can change its value or reference the
value in any way, as the following example shows:

PROCEDURE validate_input (l_input_rec IN INPUT_REC_TYPE,

v_return_status OUT VARCHAR2 ,


REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

48
v_return_message OUT VARCHAR2
)
IS
v_source_system VARCHAR2(150);
v_source_system_identifier VARCHAR2(150);
v_notes VARCHAR2(2000);
v_status VARCHAR2(30) ;
v_service_request_number VARCHAR2(64) ;

8. IN OUT Mode

Criteria OUT IN OUT

Default Must be Specified Must be Specified

Passes values to a Returns values to the caller Passes initial values to a


subprogram subprogram and returns
updated values to the caller

Formal parameter acts like a Formal parameter acts like a Formal parameter acts like
constant variable an initialized variable

Formal parameter cannot be Formal parameter must be Formal parameter should be


assigned a value assigned a value assigned a value

Actual parameter can be a Actual parameter must be a Actual parameter must be a


constant, initialized variable variable
variable, literal, or
expression

Actual parameter is passed Actual parameter is passed Actual parameter is passed


by reference (a pointer to by value (a copy of the by value (a copy of the
the value is passed in) value is passed out) unless value is passed in and out)
NO COPY is specified unless NO COPY is
specified

9. How to ALTER a PROCEDURE


REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

49
Using the ALTER PROCEDURE statement we can explicitly recompile a standalone
stored procedure. Explicit recompilation eliminates the need for implicit run-time
recompilation and prevents associated run-time compilation errors and performance
overhead.

The pre-requisite is the Procedure must be in your own schema or one must have the
ALTER ANY PROCEDURE system Privilege.

Function
1. What is a Function?
A Function is a PL/SQL sub program (block) used to compute values by accepting
parameters.

2. What does a Function consists?


A function is a named PL/SQL block that can accept parameters and be invoked. Using
functions we compute a value. A function must return a value to the calling environment
from where it has been invoked. A function must have a RETURN clause in the header
and at least one RETURN statement in the executable section.

3. What are the components of Function?

 Header,
 Declarative part,
 Executable part,
 Optional exception-handling part.

Functions promote reusability and maintainability. When validated they can be used in
any number of applications. If the processing requirements change, only the function
needs to be updated. Function is called as part of a SQL expression or as part of a
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

50
PL/SQL expression. In a SQL expression, a function must obey specific rules to control
side effects. In a PL/SQL expression, the function identifier acts like a variable whose
value depends on the parameters passed to it.

Functions can be stored in the database as a schema object for repeated execution. A
function stored in the database is referred to as a stored function. Functions can also be
created at client side applications

4. What is the syntax of the Function?

FUNCTION name [ ( parameter [, parameter ... ] ) ]


RETURN return_datatype
IS
[ declaration statements ]
BEGIN
executable statements
[ EXCEPTION
exception handler statements ]
END [ name ];
Where each component is used in the following ways:

name
The name of the procedure comes directly after the keyword FUNCTION.

parameters
An optional list of parameters that you define to both pass information into the procedure
and send information out of the procedure, back to the calling program.

return_datatype
The datatype of the value returned by the function. This is required in the function header
and is explained in more detail in the next section.

declaration statements
The declarations of local identifiers for that function. If you do not have any declarations,
then there will not be any statements between the IS and BEGIN statements.

executable statements
The statements the function executes when it is called. You must have at least one
executable statement after the BEGIN and before the END or EXCEPTION keywords.

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

51
exception handler statements
The optional exception handlers for the function. If you do not explicitly handle any
exceptions, then you can leave out the EXCEPTION keyword and simply terminate the
execution section with the END keyword.
The below figure illustrates the PL/SQL function and its different sections. Notice that
the tot_sales function does not have an exception section.

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

52
Parameter Description
function_name Name of the function
parameter Name of a PL/SQL variable whose value is
passed into the function
Mode The type of the parameter; only IN
parameters should be declared
data type Data type of the Parameter
RETURN datatype Data type of the RETURN value that must
be output by the function
PL/SQL block Procedural body that defines the action
performed by the function

Table-1. Function Parameter names its description.

Returning a Value
A function must have at least one RETURN statement in its execution section of
statements. It can have more than one RETURN, but only one of those statements is
executed each time the function is called. The RETURN statement that is executed by the
function determines the value that is returned by that function. When a RETURN
statement is processed, the function terminates immediately and returns control to the
calling PL/SQL block.
The RETURN clause in the header of the function is different from the RETURN
statement in the execution section of the body of the function. While the RETURN clause
indicates the datatype of the return or result value of the function, the RETURN
statement specifies the actual value that is returned. You have to specify the RETURN
datatype in the header, but then also include at least one RETURN statement in the
function.

Multiple RETURNs
In the tot_sales function shown in Figure 15.10, I used two different RETURN statements
to handle different situations in the function, as follows:
IF sales_cur%NOTFOUND
THEN
CLOSE sales_cur;
RETURN NULL;
ELSE
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

53
CLOSE sales_cur;
RETURN return_value;
END IF;
In other words, if I could not obtain sales information from the cursor, I will return NULL
(which is different from zero). If I do get a value from the cursor, I return it to the calling
program. In both of these cases the RETURN statement passes back a value; in one case
the NULL value, and in the other the return_value variable.

RETURN any valid expression


The RETURN statement can accept any expression for evaluation and return. This
expression can be composed of calls to other functions, complex calculations, and even
data conversions. All of the following usages of RETURN are valid:
RETURN 'buy me lunch';
RETURN POWER (max_salary, 5);
RETURN (100 - pct_of_total_salary (employee_id));
RETURN TO_DATE ('01' || earliest_month || initial_year, 'DDMMYY');
An expression in the RETURN statement is evaluated when the RETURN is executed.
When control is passed back to the calling form, the result of the evaluated expression is
passed along, too.

No RETURN is executed
What happens when you include one or any number of RETURN statements in your
functions but none of them is executed? PL/SQL raises an error.
The following function:
FUNCTION company_type (type_code_in IN VARCHAR2)
RETURN VARCHAR2 IS
BEGIN
IF type_code_in = 'S'
THEN
RETURN 'SUBSIDIARY';
ELSIF type_code_in = 'P'
THEN
RETURN 'PARTNER';
END IF;
END;
is then called in this executable statement:
type_description := company_type ('R');

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

54
Because the RETURN statements are executed only when the type code is `S' or `P', the
function never hits a RETURN. It does, however, execute to the end of the function and
then raise an error, as follows:
ORA-6503: PL/SQL: Function returned without value
You can avoid this kind of problem (which you may never encounter in testing since you
always pass a sensible value to the function) by restructuring your use of the RETURN
statement.

RETURN as last executable statement


Generally, the best way to make sure that your function always returns a value is to make
the last executable statement in the function your RETURN statement. Declare a variable
named return_value, which clearly indicates that it will contain the return value for the
function, write all the code to come up with that value, and then at the very end of the
function RETURN the return_value:
FUNCTION do_it_all (parameter_list) RETURN NUMBER
IS
return_value NUMBER;
BEGIN

... lots of executable statements ...

RETURN return_value;
END;
The company_type function, for example, can be converted easily to this structure:
FUNCTION company_type (type_code_in IN VARCHAR2)
RETURN VARCHAR2
IS
return_value VARCHAR2 (25) := NULL;
BEGIN
IF type_code_in = 'S'
THEN
return_value := 'SUBSIDIARY';

ELSIF type_code_in = 'P'


THEN
return_value := 'PARTNER';
END IF;

RETURN return_value;

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

55
END;
Notice that, because I provided the return_value variable with a default value of NULL, I
didn't have to code an ELSE clause in the IF statement to explicitly make that assignment
(though doing so would probably make the code more readable). If the type_code_in does
not match any of the values in the IF statement, there is no problem because each IF and
ELSIF no longer performs its own RETURN. Instead, they just assign a value and then
leave the RETURNing to the little RETURN section at the end of the function.

NOTE : - RETURN statement in a procedure


Believe it or not, RETURN statements can also be used in procedures. The procedure
version of the RETURN does not take an expression; it cannot, therefore, pass a value
back to the calling program unit. The RETURN simply halts execution of the procedure
and returns control to the calling code.
You do not (should not, in any case) see this usage of RETURN very often, and for good
reason. Use of the RETURN in a procedure usually leads to very unstructured code that is
hard to understand and maintain. Avoid using both RETURN and GOTO to bypass
proper control structures and process flow in your program units.

Parameters:

Procedures and functions can both use parameters to pass information back and forth
between the module and the calling PL/SQL block.

The parameters of a module are at least as important as the code that implements the
module (the module's body). Sure, you have to make certain that your module fulfills its
promise. But the whole point of creating a module is that it can be called, you hope by
more than one other module. If the parameter list is confusing or badly designed, it will
be very difficult for programmers to make use of the module. The result will be that few
people will use that module. And it doesn't much matter how well you implemented a
program that no one uses.

Many developers do not give enough attention to a module's set of parameters.


Considerations regarding parameters include:

 The number of parameters: Too few parameters can limit the reusability of your
program. Too many parameters and no one will want to reuse your program.
 The types of parameters: read-only (IN), write-only (OUT), or read-write (IN
OUT) parameters?

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

56
 The names of parameters: With proper naming convention their purpose in a
module is properly and easily understood.

 Default values for parameters: You can provide a default value for IN parameters.
If an IN parameter has a default value, you do not need to include that parameter
in the call to the program. You must, of course, include an actual parameter for
any IN OUT parameters, even if they have default values. A parameter's default
value is used by the program only if the call to that program does not include that
parameter in the list.

5. What are the Local Modules?

A local module is a procedure or function that is defined in the declaration section of a


PL/SQL block (anonymous or named). This module is considered local because it is only
defined within the parent PL/SQL block. It cannot be called by any other PL/SQL blocks
defined outside of that enclosing block.

The syntax for defining the procedure or function is exactly the same as that used for
creating standalone modules.
The following anonymous block, for example, declares a local procedure:

DECLARE
PROCEDURE show_date (date_in IN DATE) IS
BEGIN
DBMS_OUTPUT.PUT_LINE (TO_CHAR (date_in, 'Month DD, YYYY');
END;
BEGIN
...
END;
Local modules must be located after all of the other declaration statements in the
declaration section. You must declare your variables, cursors, exceptions, types, records,
tables, and so on, before you type in the first PROCEDURE or FUNCTION keyword.
You can define both procedures and functions in the declaration section of any kind of
PL/SQL block, be it anonymous, procedure, or function. You may not, however, define
anonymous blocks (how would you call them?) or packages (maybe in a future release) in
a declaration section.

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

57
The rest of this section explores the benefits of local modules and offers a number of
examples.

6. What are the Benefits of Local Modularization?

There are two central reasons to create local modules:


Reduce the size of the module by stripping it of repetitive code. This is the most common
motivation to create a local module. You can see the impact by the next example. The
code reduction leads to higher code quality because you have fewer lines to test and
fewer potential bugs. It takes less effort to maintain the code, because there is less to
maintain. When you do have to make a change, you make it in one place in the local
module and the effects are felt immediately throughout the parent module.
Improve the readability of your code. Even if you do not repeat sections of code within a
module, you still may want to pull out a set of related statements and package them into a
local module to make it easier to follow the logic of the main body of the parent module.

Reducing Code Volume


Let's take a look at an example. The calc_percentages procedure takes numeric values
from the sales package (sales_pkg), calculates the percentage of each sales amount
against the total sales provided as a parameter, and then formats the number for display in
a report or form. The example you see here has only three calculations, but I extracted it
from a production application that actually performed 23 of these computations!
PROCEDURE calc_percentages (tot_sales_in IN NUMBER)
IS
BEGIN
:profile.food_sales_stg :=
TO_CHAR ((sales_pkg.food_sales / tot_sales_in ) * 100,
'$999,999');
:profile.service_sales_stg :=
TO_CHAR ((sales_pkg.service_sales / tot_sales_in ) * 100,
'$999,999');
:profile.toy_sales_stg :=
TO_CHAR ((sales_pkg.toy_sales / tot_sales_in ) * 100,
'$999,999');
END;
This code took a long time (relatively speaking) to write, is larger in code size than
necessary, and is maintenance-intensive. What if I need to change the format to which I

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

58
convert the numbers? What if the calculation of the percentage changes? I have to change
each of the individual calculations.
With local modules, I can concentrate all the common, repeated code into a single
function, which is then called repeatedly in calc_percentages. The local module version
of this procedure is shown below:
PROCEDURE calc_percentages (tot_sales_in IN NUMBER)
IS
/* Define a function right inside the procedure! */
FUNCTION char_format (val_in IN NUMBER) RETURN VARCHAR2
IS
BEGIN
RETURN TO_CHAR ((val_in/tot_sales_in ) * 100, '$999,999');
END;
BEGIN
:profile.food_sales_stg := char_format (sales_pkg.food_sales);
:profile.service_sales_stg := char_format (sales_pkg.service_sales);
:profile.toy_sales_stg := char_format (sales_pkg.toy_sales);
END;
All the complexities of the calculation, from the division by tot_sales_in to the
multiplication by 100 to the formatting with TO_CHAR, have been transferred to the
function, pct_stg. This function is defined in the declaration section of the procedure. By
calling this function from within the body of calc_percentages, the executable statements
of the procedure are much more readable and maintainable. Now, if the formula for the
calculation changes in any way, I make the change just once in the function and it takes
effect in all the assignments.

Module Overloading
Two or more modules can, under certain conditions, have the same name with different
parameter lists. Such modules are said to be overloaded. The code in these overloaded
programs can be very similar or can be completely different. Here is an example of two
overloaded modules defined in the declaration section of an anonymous block (both are
local modules):
DECLARE
/* First version takes a DATE parameter. */
FUNCTION value_ok (date_in IN DATE) RETURN BOOLEAN
IS
BEGIN
RETURN date_in <= SYSDATE;

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

59
END;

/* Second version takes a NUMBER parameter. */


FUNCTION value_ok (number_in IN NUMBER) RETURN BOOLEAN
IS
BEGIN
RETURN number_in > 0;
END;
BEGIN
When the PL/SQL run-time engine encounters the following statement:
IF value_ok (SYSDATE) THEN ...
the compile compares the actual parameter against the different parameter lists for the
overloaded modules. It then executes the code in the body of the program with the
matching header.

7. What are the Benefits of Overloading in Function?

Overloading can greatly simplify your life and the lives of other developers. This
technique consolidates the call interfaces for many similar programs into a single module
name. This process transfers the burden of knowledge from the developer to the software.
You do not have to try to remember, for instance, the six different names for programs
adding values (dates, strings, Booleans, numbers, etc.) to various PL/SQL tables. Instead,
you simply tell the compiler that you want to add and pass it the value you want added.
PL/SQL and your overloaded programs figure out what you want to do and they do it for
you.

When you build overloaded modules, you spend more time in design and implementation
than you might with separate, standalone modules. This additional up-front time will be
repaid handsomely down the line. You and others will find that it is easier and more
efficient to use your programs.

Where to Overload Modules


 There are only two places in PL/SQL programs where you can overload modules:
 Inside the declaration section of a PL/SQL block
 Inside a package

Restrictions on Overloading
There are several restrictions on how you can overload programs. When the PL/SQL
engine compiles and runs your program, it has to be able to distinguish between the
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

60
different overloaded versions of a program; after all, it can't run two different modules at
the same time. So when you compile your code, PL/SQL will reject any improperly
overloaded modules. It cannot distinguish between the modules by their name, because
by definition that is the same in all overloaded programs. Instead, PL/SQL uses the
parameter lists of these sibling programs to determine which one to execute. As a result,
the following restrictions apply to overloaded programs.

The datatype family of at least one of the parameters of overloaded programs must differ.
INTEGER, REAL, DECIMAL, FLOAT, etc., are NUMBER subtypes. CHAR,
VARCHAR2, and LONG are character subtypes. If the parameters differ only by
datatype within the supertype or family of datatypes, PL/SQL does not have enough
information with which to determine the appropriate program to execute. As a result, the
following programs cannot be overloaded:

8 . What are the Forward Declarations?

PL/SQL is rather fussy about its requirement that you declare a variable, cursor, or
module before you use it in your code. Otherwise, how can PL/SQL be sure that the way
you are using the object is appropriate? Since modules can call other modules, however,
you can encounter situations where it is completely impossible to define all modules
before any references to those modules are made. What if program A calls program B and
program B calls program A? PL/SQL supports mutual recursion, where two or more
programs directly or indirectly call each other.
If you do find yourself committed to mutual recursion, you will be very glad to hear that
PL/SQL supports the forward declaration of local modules, which declares a module in
advance of the actual definition of that program. This declaration makes that program
available to be called by other programs even before the program definition.
Remember that both procedures and functions have a header and a body. A forward
declaration consists simply of the program header, followed by a semicolon (;). This
construction is called the module header. This header, which must include the parameter
list (and RETURN clause if a function) is all the information PL/SQL needs about a
module in order to declare it and resolve any references to that module; a module should,
after all, be a little black box.
The following example will illustrate the technique. I define two mutually recursive
functions within a procedure. Consequently I have to declare just the header of my
second function, total_cost, before the full declaration of net_profit:

PROCEDURE perform_calcs (year_in IN INTEGER)


IS

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

61
/* Header only for total_cost function. */
FUNCTION total_cost (. . .) RETURN NUMBER;

/* The net_profit function uses total_cost. */


FUNCTION net_profit (. . .) RETURN NUMBER
IS
BEGIN
RETURN tot_sales (. . .) - total_cost (. . .);
END;

/* The total_cost function uses net_profit. */


FUNCTION total_cost (. . .) RETURN NUMBER
IS
BEGIN
IF net_profit (. . .) < 0
THEN
RETURN 0;
ELSE
RETURN . . .;
END IF;
END;
BEGIN
...
END;

Here are some rules to remember concerning forward declarations:


You cannot make forward declarations of a variable or cursor. This technique works only
with modules (procedures and functions).
The definition for a forwardly-declared program must be contained in the declaration
section of the same PL/SQL block (anonymous block, procedure, function, or package) in
which you code the forward declaration.
In some situations, you absolutely require forward declarations; in most situations, they
just help make your code more readable and presentable. As with every other advanced or
unusual feature of the PL/SQL language, use forward declarations only when you really
need the functionality. Otherwise, the declarations simply add to the clutter of your
program, which is the last thing you want.

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

62
Figure 2. Function Creation screen shot

9. How to invoke the Functions in SQL Expressions?

We invoke the SQL functions when activates are too complex, too awkward, or
unavailable with SQL.
By invoking functions we can increase efficiency when used in the WHERE clause to
filter data, as opposed to filtering the data in the application and also we can manipulate
character strings.

Advantages
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

63
• Permits calculations that are too complex, awkward, or unavailable with SQL.
• Increases data independence by processing complex data analysis within the Oracle
server,
rather than by retrieving the data into an application
• Increases efficiency of queries by performing functions in the query rather than in the
application
• Manipulates new types of data (for example, latitude and longitude) by encoding
character
strings and using functions to operate on the strings.

CREATE OR REPLACE FUNCTION tax(p_value IN NUMBER)


RETURN NUMBER IS
BEGIN
RETURN (p_value * 0.08);
END tax;
/

SELECT employee_id, last_name, salary, tax(salary)


FROM employees WHERE department_id = 100;

10. What are the restrictions on calling Functions from SQL Expressions?

To be callable from SQL expressions, a user-defined PL/SQL function must meet certain
requirements.

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

64
• Parameters to a PL/SQL function called from a SQL statement must use positional
notation.
Named notation is not supported.

• Stored PL/SQL functions cannot be called from the CHECK constraint clause of a
CREATE or
ALTER TABLE command or be used to specify a default value for a column.

• User must have the EXECUTE privilege on the function to call it from a SQL
statement.

• The functions must return data types that are valid SQL data types. They cannot be
PL/SQL specific
data types such as BOOLEAN, RECORD, or TABLE. The same restriction applies to
parameters of the function.

Note: Only stored functions are callable from SQL statements. Stored procedures cannot
be called.
The ability to use a user-defined PL/SQL function in a SQL expression is available with
PL/SQL 2.1
and later. Tools using earlier versions of PL/SQL do not support this functionality. Prior
to Oracle9i,
user-defined functions can be only single-row functions. Starting with Oracle9i, user-
defined functions
can also be defined as aggregate functions.

Note: Functions that are callable from SQL expressions cannot contain OUT and IN
OUT parameters.

Other functions can contain parameters with these modes, but it is not recommended.

11. How to ALTER FUNCTION?

Alter function is used to recompile a stand-alone stored function.

SYNTAX: ALTER FUNCTION [schema.] function COMPILE

Schema
is the schema containing the function. If you omit schema, Oracle

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

65
assumes the function is in your own schema.

Function
is the name of the function to be recompiled.

COMPILE
Causes Oracle to recompile the function. The COMPILE keyword is required.

PREREQUISITES:
The function must be in your own schema or you must have ALTER ANY
PROCEDURE system privilege.

If you are using Trusted Oracle in DBMS MAC mode, your DBMS label must match
the function's creation label or you must satisfy one of these criteria:

* If the function's creation label is higher than your DBMS label, you must have
READUP and WRITEUP system privileges.

* If the function's creation label is lower than your DBMS label, you must have
WRITEDOWN system privilege.

* If the function's creation label and your DBMS label are non-comparable, you must
have READUP, WRITEUP, and WRITEDOWN system privileges.

Oracle Packages:
1.1 A Package is a collection of logically related data objects and the procedures that
manipulate them. A package is a schema object which includes definitions of variables,
constants, cursors, exceptions, exception handlers, composite data types, procedures, and
functions, and is stored in the database as a single object. Variables and cursors can be
declared global to all procedures in a package and they maintain their values throughout
the session.

A Package is a group of procedures, functions, variables and SQL statements created as a


single unit. It is used to store together related objects.

1.2 A package has two parts


REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

66
 Package Specification ( Called as spec in short) or package header
 Package Body.

1.3 Package Specification acts as an interface to the package and contains the following.
Package specification does not contain any code.

 Declaration of types
 Variables

 Constants

 Exceptions

 Cursors

 Subprograms

1.4 Use of Packages:


Package body is used to provide implementation for the subprograms, queries for the
cursors declared in the package specification or spec. PL/SQL stored packages allow
you to define a functional structure well beyond what can be accomplished with
alternative systems. A package can include definitions of variables, constants, cursors,
exceptions, exception handlers, composite data types, procedures, and functions, and is
stored in the database as a single object. Variables and cursors can be declared global to
all procedures in a package and they maintain their values throughout the session.

In other implementations, variables lose all state between calls. Thus, you can define
various packages of self-contained, reusable functionality. For example, you can define
an inventory package containing commonly used routines for shipping products or
reordering parts, an accounting package containing routines for tracking expenses and
budgets, and a human resources package for hiring and promoting employees and
tracking their progress.

The specification of a package (i.e., the procedure names and parameter lists) can be
separate from its actual implementation. This enables you to specify an entire application
on up-front, yet write and test the procedures one part at a time.

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

67
Package objects can be made public (accessible to other packages), or private (accessible
to only its own package). This allows you to hide implementation details of your own
system from the public and provides security.

If changing the implementation of a package does not require changing its specification,
then any procedures that call routines in this package do not need to be recompiled. This
avoids a chain reaction where the modification of one package sets off hundreds of
automatic recompilation throughout the system, and frees database resources for other
useful work.

The following are some of the uses of packages

The Packages allows a PL/SQL block to group together related items, types and
subprograms as a module. When a procedure in a package is called entire package is
loaded, though it happens to be expensive first time the response is faster for
subsequent calls (Making one time compilation and calling the package when ever
necessary through) .
 Package allows us to create types, variable and subprograms that are private or
public as per requirement.
 Package contains all related code in a single object.

 All related code loaded into memory simultaneously of a package when it is


created.

 As a Package body Single object compilation is performed.

 For a given package variables defined and which persist for term of session.

 Fewer objects to manage and grant/revoke privileges.

1.5 Advantages of Packages

Packages offer several advantages:

 Modularity
 Easier Application Design
 Easier Debug process
 Information hiding
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

68
 Added functionality
 Better performance.

Modularity

Packages let you encapsulate logically related types, items, and subprograms in a
named PL/SQL module. Each package is easy to understand, and the interfaces
between packages are simple, clear, and well defined. This aids application
development.

Easier Application Design

When designing an application, all you need initially is the interface information in
the package specs. You can code and compile a spec without its body. Then, stored
subprograms that reference the package can be compiled as well. You need not define
the package bodies fully until you are ready to complete the application.

Information Hiding

With packages, you can specify which types, items, and subprograms are public
(visible and accessible) or private (hidden and inaccessible). For example, if a
package contains four subprograms, three might be public and one private. The
package hides the definition of the private subprogram so that only the package (not
your application) is affected if the definition changes. This simplifies maintenance
and enhancement. Also, by hiding implementation details from users, you protect the
integrity of the package.

Added Functionality

Packaged public variables and cursors persist for the duration of a session. So, they
can be shared by all subprograms that execute in the environment. Also, they allow
you to maintain data across transactions without having to store it in the database.

Better Performance

When a package is called with subprogram for the first time, the whole package is
loaded into memory. So, later calls to related subprograms in the package require no
disk I/O. Also, packages stop cascading dependencies and thereby avoid unnecessary
recompiling. For example, if you change the definition of a packaged function, Oracle
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

69
need not recompile the calling subprograms because they do not depend on the
package body.

Syntax of the PACKAGE.


CREATE [OR REPLACE] PACKAGE package_name
[AUTHID {CURRENT_USER | DEFINER}] {IS | AS}
[type_definition [type_definition] ...]
[cursor_spec [cursor_spec] ...]
[item_declaration [item_declaration] ...]
[{subprogram_spec | call_spec} [{subprogram_spec | call_spec}]...]
END [package_name];

1.6 The Package Specification.


The package spec contains public declarations. The scope of these declarations is local to
your database schema and global to the package. So, the declared items are accessible
from your application and from anywhere in the package.

Diagram-1.1 How schema is Package body and Package specifications are


connected.

Always create and compile specifications of the Package and Package body separately.

Package syntax

The general syntax for the package body is shown below:

CREATE OR REPLACE PACKAGE package_name

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

70
IS
PROCEDURE procdure_name1;
PROCEDURE procdure_name2;
PROCEDURE procdure_name3;

END PACK1;
/
1.8 Package body syntax

The general syntax for the package body is shown below:

PACKAGE BODY package_name


IS
[ declarations of variables and types ]
[ header and SELECT statement of cursors ]
[ header and body of modules ]
[ BEGIN
executable statements ]
[ EXCEPTION
exception handlers ]
END [package_name];

In the body you can declare other variables, but you do not repeat the declarations in the
specification. The body contains the full implementation of cursors and modules. In the
case of a cursor, the package body contains both the header and the SQL statement for the
cursor. In the case of a module, the package body contains both the header and body of
the module.

The BEGIN keyword indicates the presence of an execution or initialization section for
the package. This section can also optionally include an exception section.

As with a procedure, function, and package specification, you can add the name of the
package, as a label, after the END keyword in both the specification and package.

PACKAGE BODY Syntax.

CREATE [OR REPLACE] PACKAGE BODY package_name {IS | AS}


[type_definition [type_definition] ...]
[cursor_body [cursor_body] ...]

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

71
[item_declaration [item_declaration] ...]
[{subprogram_spec | call_spec} [{subprogram_spec | call_spec}]...]
[BEGIN sequence_of_statements]
END [package_name];

Package Body with Procedures


CREATE OR REPLACE PACKAGE <package_name> AS
PROCEDURE <procedure_name1> (<parameters>);
PROCEDURE <procedure_name2> (<parameters>);
PROCEDURE <procedure_name3> (<parameters>);
END <package_name>;

Forward Declaration in Packages


In a package you can declare a group of logical subprograms which are logically related
in a package. The subprogram specs go in the package spec, and the subprogram bodies
go in the package body, where they are invisible to applications. With this packages allow
you to hide implementation details.

/* Here is the syntax of the Package and Procedure called Package_Name and Package
body and three sample Procedures are declared and it has the three procedures called
Package1, Package2, Package3*/

Syntax of PACKAGE

CREATE PACKAGE <Package_Name> AS -- package spec


PROCEDURE Procedure1 (emp_id INTGER, name VARCHAR2 .......);
PROCEDURE Procedure2 (emp_id INTEGER, amount REAL);
PROCEDURE Procedure3 (emp_id INTEGER);
...
END <Package_Name>;

Syntax of PACKAGE BODY

CREATE PACKAGE BODY <Package_Body> AS -- package body


PROCEDURE Procedure1 (Paramter1 INTGER, Paramter2 VARCHAR2......) IS
BEGIN
...
INSERT INTO <Table1> VALUES (v1, v2,.....);

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

72
END Procedure1;

PROCEDURE Procedure2 (Paramter1 INTEGER, Paramter2 REAL) IS


salary REAL;
BEGIN
SELECT Parameter1 INTO salary FROM emp
WHERE < Condition>;
...
END Procedure2;

PROCEDURE Procedure3 (Paramter1 INTEGER) IS


BEGIN
DELETE FROM < TABLE1>
WHERE < Condition>;
END Procedure3;
...
END <Package_Body>;

/* This Package body where Procedure called main_p and ‘validate_input’ and
get_api_input_parameters procedures */

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

73
Figure.1 Creation of the Package

1.9 The following list offers a summary of the best practices for packages covered in this
chapter:

 Use a consistent and effective coding style. Use consistent indentation to reveal
the logical flow of the program and to delineate the different sections of the
PL/SQL program structure. Generally, this means that all executable statements
are indented in from the BEGIN keyword, the body of a loop is indented within
the LOOP and END LOOP keywords, and so on. Within a package, all
specification declarations are indented between the IS and END keywords.

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

74
Code all reserved words in the PL/SQL language in upper-case. Use lower-case for
all application-specific identifiers. Generally, this is accomplished with hard-coded
literals and the use of UPPER and LOWER.

Use comments to add value to the code. Don't bother with comments that simply
repeat what the code clearly states.

The style elements found valuable particularly for packages include the following:

Use banners (specially formatted comment lines) to mark clearly the different
groupings of package elements.

Use end labels for the package and for all program units defined in the package body.

Example: A Generated Package Template


SQL> exec PLVgen.pkg('emp_maint');
1 CREATE OR REPLACE PACKAGE emp_maint
2 /*
3 || Program: emp_maint
4 || Author: Steven Feuerstein
5 || File: emp_maint.SQL
6 || Created: APR 13, 1996 18:56:59
7 */
8 /*HELP
9 Add help text here...
10 HELP*/
11
12 /*EXAMPLES
13 Add help text here...
14 EXAMPLES*/
15
16 IS
17 /* Public Data Structures */
18
19 /* Public Programs */
20
21 PROCEDURE help (context_in IN VARCHAR2 := NULL);
22
23 END emp_maint;

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

75
24 /
25
26 CREATE OR REPLACE PACKAGE BODY emp_maint
27 IS
28 /* Private Data Structures */
29
30 /* Private Programs */
31
32 /* Public Programs */
33
34 PROCEDURE help (context_in IN VARCHAR2 := NULL)
35 IS
36 BEGIN
37 PLVhlp.show ('s:emp_maint', context_in);
38 END help;
39 END emp_maint;
40 /

Below are the features to highlight in the above package template:

Lines Significance

2-7 A standard header for the package, showing the author, filename, and date created.

8-14 Stubs for help text. These comment blocks provide both inline code documentation
and help text to users.

17-19 Banners to identify the two main kinds of elements that can appear in a package
specification: data structures and program units.

21 Header for a procedure that delivers online help for this package. Of course, this
should only be included if the online help package is being used.

23 The END statement with the package name appended.

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

76
Lines Significance

28-32 Banners to identify the three kinds of elements that can appear in a package body:
private data structures, program units, and the implementation of the public
program units.

34-38 The implementation of the help procedure. Notice that the procedure uses an end
label with the program name and is also indented in multiple steps from the overall
package.

 Selecting Package Names:


o Choose appropriate and accurate names
 There are two aspects to coming up with the right names for your
code elements:
 The structure of the name should match the role that element
plays in your code.
 The name should reflect what the element does in your code.
o Avoiding Redundancy
 To reference a package element outside of the package you must
use dot notation (package.element). As a result, you will want to
avoid redundancy in your package and element names. For
example, suppose I have a package named emp_maint for
employee maintenance. One of the procedures in the package sets
the employee salary.

 Construct the optimal interface to your package.


o Design your package so that it is easy -- and a pleasure -- to use. When
you build packages for reuse, other PL/SQL developers become your
users of it. Treat them with respect. Make the parameters in your
programs case-insensitive. Don't require users to know about and pass
literal values.

o Make the programs case-insensitive


REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

77
Make sure users don't trip over senseless obstacles on the path to using
your programs. A common source of frustration is the requirement that
arguments to a program be in one case or another (usually upper or
lower).

Consider the following program:

CREATE OR REPLACE FUNCTION twice


(string_in IN VARCHAR2, action_in IN VARCHAR2)
RETURN VARCHAR2
IS
BEGIN
IF action_in = 'UL'
THEN
RETURN (UPPER (string_in) || LOWER (string_in));

ELSIF action_in = 'LU'


THEN
RETURN (LOWER (string_in) || UPPER (string_in));

ELSIF action_in = 'N'


THEN
RETURN string_in || string_in;
END IF;
END twice;
/

 Build flexibility directly into your packages.


o If a program is going to be widely reusable, it should be able to adapt to
different circumstances to meet different needs. There are two basic ways
to be flexible when writing programs for others to use:

 Offer lots of parameters in the parameter lists of the package's


functions and procedures. This is the traditional, well-worn path.

 Provide toggles or on-off switches, distinct from the main


programs of the package, which modify the behavior of those
programs. This approach takes advantage of the package structure
to offer a new way of doing things.

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

78
 One of the most exciting benefits of package toggles is that they
allow a user of the package to modify the behavior of the package
without changing any application code that calls the package
element.

 You didn't have to change your program and you didn't have to
modify the state of your database. From outside the package, you
call the toggle program to reach inside the package and change the
way the package will behave. This ability to leave your own code
intact comes in particularly handy not only for special exceptions
but also for testing as below:

A common debug and test cycle in PL/SQL shops goes like this:

1. You identify incorrect behavior in your program.


2. Unable to understand the cause of the behavior, you place numerous calls to
DBMS_OUTPUT.PUT_LINE (or, with your purchase of this book, PL/Vision's
much more friendly p.l procedure) and other kinds of tracing lines of code so that
you can see what is going on.

3. You analyze the output, track down the problem, and fix it.

4. You finally decide that all the bugs are gone.

5. You notify your manager that the application is ready to go. Excitement mounts.
Other organizations are told to start moving the code from test to production.
Suddenly, you break out in a cold sweat and tell your bewildered manager to
"hold off a minute."

6. You forgot about all that debugging code you littered into your application. It can't
go into production like that. You have to go back into the program to comment out
or outright remove all that trace code. No problem, you tell yourself. Easy to
do...but there could be a problem. After all, any time you touch the code, you can
break it. After any changes of any kind to your code, you really should retest.

7. So you have to go back to your manager and ask for more time to make sure
everything really is all right. Not a pleasant situation in which to find yourself.

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

79
If, on the other hand, you used packages with toggles to trace your debugging activity,
you would not have to worry about any of that. You could keep your code intact and
simply issue a call to the appropriate package toggle to turn off any superfluous activity,
as in:

SQL> exec pkg.turn_off

 Overload for smart packages.


o One of the most powerful aspects of the package is the ability to overload
program units. When you overload, you define more than one program
with the same name. These programs will differ in other ways (usually the
number and types of parameters) so that at runtime the PL/SQL engine can
figure out which of the programs to execute. You can take advantage of
the overloading feature of packages to make your package-based features
as accessible as possible.

o Does overloading sound unfamiliar or strange? Well, have you ever used
the TO_CHAR function? If so, then you have already been enjoying the
creature comforts of overloading. TO_CHAR converts both numbers and
dates to strings. Have you ever wondered why you don't have to call
functions with names like TO_CHAR_FROM_DATE or
TO_CHAR_FROM_NUMBER? Probably not. You probably just took
TO_CHAR for granted, and that is how it should be.

o In reality, there are two different TO_CHAR functions (both defined in the
STANDARD package): one to convert dates and another to convert
numbers. The reason that you don't have to care about such details and can
simply execute TO_CHAR is that the PL/SQL runtime engine examines
the kind of data you pass to TO_CHAR and then automatically figures out
which of the two functions (with the same name) to execute. It's like
magic, only it's better than magic: it's intelligent software!

o When you build overloaded modules, you spend more time in design and
implementation than you might with separate, standalone modules. This
additional up-front time will be repaid handsomely down the line in
program productivity and ease of use.

o You will not have to try to remember the different names of the modules
and their specific arguments. Properly constructed, overloaded modules
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

80
will have anticipated the different variations, hidden them behind a single
name, and liberated your brain for other, more important matters.

When to overload a package:

o When you overload, you take the first step towards providing a declarative
interface to PL/SQL-based functionality. With a declarative approach, a
developer does not write a program to obtain the necessary functionality.
Instead, she describes what she wants and lets the underlying code handle
the details (this follows the approach used by the SQL language). The
process of overloading involves abstracting out from separate programs
into a single action.
o You want to display a date? You want to display a number? You want to
display a string and a number? Hold on a minute. The common element is
that you want to display something -- lots of somethings, in fact. So don't
create display_date, display_string, etc. procedures. Instead, offer a single
display procedure, which is in fact many overloaded display procedures.

o With the overloading in place, your user must only remember this: when I
want to display something, I simply ask the display program to take care
of it for me. What do I pass to it? Whatever I want it to display. I will not
(and do not have to) worry about the how of the display mechanism. Those
details are hidden from me.

o Here are some of the circumstances that cause the PL/SQL fairy to
whisper in my ear "Overload, overload...:

 Apply the same action to different kinds or combinations of data.

 Allow developers to use a program in the most natural and


intuitive fashion; you use overloading to fit your program to the
needs of the user.

 Make it easy for developers to specify, unambiguously and simply,


the kind of action desired.

Package Name Description

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

81
DBMS_OUTPUT Displays output from PL/SQL programs to
the terminal. The "lowest common
denominator" debugger mechanism for
PL/SQL code.

UTL_FILE Allows PL/SQL programs to read from and


write to operating system files.

DBMS_JOB Used to submit and manage regularly


scheduled jobs for execution inside the
database.

DBMS_LOCK Allows users to create their own locks


using the Oracle Lock Management (OLM)
services in the database.

DBMS_MAIL Offers an interface to Oracle Office


(previously known as Oracle Mail).

DBMS_ALERT Provides support for notification of


database events on an asynchronous basis.
Registers a process with an alert and then
waits for a signal from that alert.

DBMS_PIPE Allows communication between different


Oracle sessions through a pipe in the
RDBM’s shared memory. One of the few
ways to share memory-resident data
between Oracle sessions.

DBMS_SESSION Provides a programmatic interface to


several SQL ALTER SESSION commands
and other session-level commands.

DBMS_SNAPSHOT A programmatic interface through which


you can manage snapshots and purge
snapshot logs. You might use modules in
this package to build scripts to automate
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

82
maintenance of snapshots.

DBMS_SQL Full support for dynamic SQL within


PL/SQL. Dynamic SQL means SQL
statements that are not prewritten into your
programs. They are, instead, constructed at
runtime as character strings and then
passed to the SQL Engine for execution.
(PL/SQL Release 2.1 only)

DBMS_TRANSACTION A programmatic interface to a number of


the SQL transaction statements, such as the
SET TRANSACTION command.

DBMS_UTILITY The "miscellaneous" package. Contains


various useful utilities, such as
GET_TIME, which calculates elapsed time
to the hundredth of a second, and
FORMAT_CALL_STACK, which returns
the current execution stack in the PL/SQL
runtime engine.

DBMS_ALERT Provides support for notification of


database events on an asynchronous basis.
Registers a process with an alert and then
waits for a signal from that alert.
Figure2. Some of the Built-in Packages Stored in the Oracle Database

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

83
Figure3. Package creation at SQL PLUS prompt.
2.0 More about the UTL_FILE
The UTL_FILE package lets your PL/SQL programs read and write operating system
(OS) text files. It provides a restricted version of standard OS stream file input/output
(I/O).

The file I/O capabilities are similar to those of the standard operating system stream file
I/O (OPEN, GET, PUT, CLOSE), with some limitations. For example, call the FOPEN
function to return a file handle, which you then use in subsequent calls to GET_LINE or
PUT to perform stream I/O to a file. When you are done performing I/O on the file, call
FCLOSE to complete any output and to free any resources associated with the file.

The following are UNIX Specific.

UTL_FILE_DIR=/appl/gl/log
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

84
UTL_FILE_DIR=/appl/gl/out

Then, the following file locations and filenames are valid:

FILE LOCATION FILENAME


/appl/gl/log L10324.log
/appl/gl/out O10324.out

But, the following file locations and filename are invalid:

FILE LOCATION FILENAME


/appl/gl/log/backup L10324.log # subdirectory
/APPL/gl/log L10324.log # uppercase
/appl/gl/log backup/L10324.log # dir in name
/usr/tmp T10324.tmp # not in INIT.ORA

Types

TYPE file_type IS RECORD (id BINARY_INTEGER);

The contents of FILE_TYPE are private to the UTL_FILE package. Users of the package
should not reference or change components of this record.

Exceptions in UTL_FILE Package Exceptions

Exception
Description
INVALID_PATH
File location or filename was invalid.
INVALID_MODE
The open_mode parameter in FOPEN was
invalid.
INVALID_FILEHANDLE
File handle was invalid.
INVALID_OPERATION
File could not be opened or operated on as
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

85
requested.
READ_ERROR
Operating system error occurred during the
read operation.
WRITE_ERROR
Operating system error occurred during the
write operation.
INTERNAL_ERROR
Unspecified PL/SQL error.
INVALID_PATH
File location or filename was invalid.

Subprograms in the UTL_FILE Package

Description
Subprogram
FOPEN function
Opens a file for input or output with the
default line size.
IS_OPEN function
Determines if a file handle refers to an
open file.
FCLOSE procedure
Closes a file.
FCLOSE_ALL procedure
Closes all open file handles.
GET_LINE procedure
Reads a line of text from an open file.
PUT procedure
Writes a line to a file. This does not append
a line terminator.
NEW_LINE procedure
Writes one or more OS-specific line
terminators to a file.
PUT_LINE procedure
Writes a line to a file. This appends an OS-
specific line terminator.

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

86
PUTF procedure
A PUT procedure with formatting.
FFLUSH procedure
Physically writes all pending output to a
file.
FOPEN function
Opens a file with the maximum line size
specified.
FOPEN function
Opens a file for input or output with the
default line size.

2.1 ALTER PACKAGE.

ALTER PACKAGE command

PURPOSE: To recompile a stored package.

SYNTAX: ALTER PACKAGE [schema.]package


COMPILE [PACKAGE | BODY]

Schema : The schema contains the package. If you omit schema, Oracle
assumes the package is in your own schema.

Package : The name of the package to be recompiled.

COMPILE : Recompiles the package specification or body. The COMPILE keyword


is required.

PACKAGE : Recompiles the package body and specification.

BODY : Recompiles only the package body.

The default option is PACKAGE.

PREREQUISITES: The package must be in your own schema or you must have
ALTER ANY PROCEDURE system privilege.

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

87
Triggers :
1. What is a Trigger?

A database trigger is a stored procedure associated with a database table, view, or event.
The trigger can be called once, when some event occurs, or many times, once for each
row affected by an INSERT, UPDATE, or DELETE statement. The trigger can be called
after the event, to record it, or take some follow-up action. The trigger can be called
before the event, to prevent erroneous operations or fix new data so that it conforms to
business rules. The executable part of a trigger can contain procedural statements and
SQL data manipulation statements

2. When you need a trigger?


You can write triggers that fire whenever one of the following operations occurs:

 DML( Data Manipulation Language) statements (INSERT, UPDATE, DELETE)


on a particular table or view, issued by any user
 DDL (Data Definition Language) statements (CREATE or ALTER primarily)
issued either by a particular schema/user or by any schema/user in the database

 Database events, such as logon/logoff, errors, or startup/shutdown, also issued


either by a particular schema/user or by any schema/user in the database

Triggers are similar to stored procedures. A trigger stored in the database can include
SQL and PL/SQL or Java statements to run as a unit and can invoke stored procedures.
However, procedures and triggers differ in the way that they are invoked. A procedure is
explicitly run by a user, application, or trigger. Triggers are implicitly fired by Oracle
when a triggering event occurs, no matter which user is connected or which application is
being used.

3. How Triggers Are Used?


Triggers supplement the standard capabilities of Oracle to provide a highly customized
database management system. For example, a trigger can restrict DML operations against
a table to those issued during regular business hours. You can also use triggers to:

 Automatically generate derived column values


 Prevent invalid transactions

 Enforce complex security authorizations


REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

88
 Enforce referential integrity across nodes in a distributed database

 Enforce complex business rules

 Provide transparent event logging

 Provide auditing

 Maintain synchronous table replicates

 Gather statistics on table access

 Modify table data when DML statements are issued against views

 Publish information about database events, user events, and SQL statements to
subscribing applications

4. What does trigger Consists?

A trigger has three basic parts:

 A triggering event or statement


 A trigger restriction

 A trigger action

Triggering event or statement

A triggering event or statement is the SQL statement, database event, or user event that
causes a trigger to fire. A triggering event can be one or more of the following:

 An INSERT, UPDATE, or DELETE statement on a specific table (or view, in


some cases)
 A CREATE, ALTER, or DROP statement on any schema object
 A database startup or instance shutdown
 A specific error message or any error message
 A user logon or logoff

Trigger Restriction
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

89
A trigger restriction specifies a Boolean expression that must be true for the trigger to
fire. The trigger action is not run if the trigger restriction evaluates to false or unknown.
In the example, the trigger restriction is:

new.parts_on_hand < new.reorder_point

Consequently, the trigger does not fire unless the number of available parts is less than a
present reorder amount.

Trigger Action

A trigger action is the procedure (PL/SQL block, Java program, or C callout) that
contains the SQL statements and code to be run when the following events occur:

 A triggering statement is issued.


 The trigger restriction evaluates to true.

Like stored procedures, a trigger action can:

 Contain SQL, PL/SQL, or Java statements


 Define PL/SQL language constructs such as variables, constants, cursors,
exceptions

 Define Java language constructs

 Call stored procedures

If the triggers are row triggers, the statements in a trigger action have access to column
values of the row being processed by the trigger. Correlation names provide access to the
old and new values for each column.

Basic Trigger Syntax


Below is the syntax for creating a trigger in Oracle (which differs slightly from standard
SQL syntax):

CREATE [OR REPLACE] TRIGGER <trigger_name>


{BEFORE|AFTER} {INSERT|DELETE|UPDATE} ON <table_name>
[REFERENCING [NEW AS <new_row_name>] [OLD AS <old_row_name>]]
[FOR EACH ROW [WHEN (<trigger_condition>)]] <trigger_body>
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

90
Some important points to note on Triggers:
 You can create only BEFORE and AFTER triggers for tables. (INSTEAD OF
triggers are only available for views; typically they are used to implement view
updates.)

 You may specify up to three triggering events using the keyword OR.
Furthermore, UPDATE can be optionally followed by the keyword OF and a list
of attribute(s) in <table_name>. If present, the OF clause defines the event to be
only an update of the attribute(s) listed after OF. Here are some examples:
 ... INSERT ON R ...

 ... INSERT OR DELETE OR UPDATE ON R ...



... UPDATE OF A, B OR INSERT ON R ...
 If FOR EACH ROW option is specified, the trigger is row-level; otherwise, the
trigger is statement-level.

 Only for row-level triggers:


o The special variables NEW and OLD are available to refer to new and old
tuples respectively. Note: In the trigger body, NEW and OLD must be
preceded by a colon (":"), but in the WHEN clause, they do not have a
preceding colon! See example below.
o The REFERENCING clause can be used to assign aliases to the variables
NEW and OLD.
o A trigger restriction can be specified in the WHEN clause, enclosed by
parentheses. The trigger restriction is a SQL condition that must be
satisfied in order for Oracle to fire the trigger. This condition cannot
contain subqueries. Without the WHEN clause, the trigger is fired for each
row.

 <trigger_body> is a PL/SQL block, rather than sequence of SQL statements. Oracle


has placed certain restrictions on what you can do in <trigger_body>, in order to
avoid situations where one trigger performs an action that triggers a second trigger,
which then triggers a third, and so on, which could potentially create an infinite
loop.
 The restrictions on <trigger_body> include:
o You cannot modify the same relation whose modification is the event
triggering the trigger.
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

91
o You cannot modify a relation connected to the triggering relation by
another constraint such as a foreign-key constrain

5. What are the types of trigger?

Insert Triggers

 Before Insert trigger

A BEFORE INSERT Trigger means that Oracle will fire this trigger before the INSERT
operation is executed.

The syntax for the BEFORE INSERT Trigger is:

CREATE or REPLACE TRIGGER trigger_name


BEFORE INSERT
ON table_name
[ FOR EACH ROW ]
DECLARE
-- variable declarations
BEGIN
-- trigger code
EXCEPTION
WHEN ...
-- exception handling
END;

Trigger_name is the name of the trigger to create.

Restrictions:

 You can not create a BEFORE trigger on a view.


 You can update the : NEW values.
 You can not update the : OLD values.

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

92
 After Insert trigger

An AFTER INSERT Trigger means that Oracle will fire this trigger after the INSERT
operation is executed.

The syntax for an AFTER INSERT Trigger is:

CREATE or REPLACE TRIGGER trigger_name


AFTER INSERT
ON table_name
[ FOR EACH ROW ]
DECLARE
-- variable declarations
BEGIN
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

93
-- trigger code
EXCEPTION
WHEN ...
-- exception handling
END;

For example: For the table order2

CREATE TABLE Orders2


(order_id number(5),
quantity number(4),
cost_per_item number (6,2),
totoal_cost number(8,2));

We could then create an AFTER INSERT trigger as follows:

CREATE OR REPLACE TRIGGER orders_after_insert


AFTER INSERT
ON orders2
FOR EACH ROW
DECLARE
v_username varchar2(10);
BEGIN
-- Find username of person performing the INSERT into the table
SELECT user INTO v_username
FROM dual;
-- Insert record into audit table
INSERT INTO orders_audit
( order_id,
quantity,
cost_per_item,
total_cost,
username )
VALUES
( :new.order_id,
:new.quantity,
:new.cost_per_item,
:new.total_cost,
v_username );

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

94
END;

Update Triggers

 Before update Trigger

A BEFORE UPDATE Trigger means that Oracle will fire this trigger before the UPDATE
operation is executed.

The syntax for BEFORE UPDATE Trigger is:

CREATE or REPLACE TRIGGER trigger_name


BEFORE UPDATE
ON table_name
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

95
[ FOR EACH ROW ]
DECLARE
-- variable declarations
BEGIN
-- trigger code
EXCEPTION
WHEN ...
-- exception handling
END;

Restrictions:

 You can not create a BEFORE trigger on a view.


 You can update the :NEW values.
 You can not update the :OLD values.

Example: - Create a table as follows:

Create table Orders2


( order-id number(5),
quantity number(4),
cost_per_item number(6,2),
total_cost number(8,2),
updated_date date,
updated_by varchar2(10));

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

96
Screen shot showing the table has been created.

We could then create a BEFORE UPDATE trigger as follows:

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

97
CREATE OR REPLACE TRIGGER orders_before_update
BEFORE UPDATE
ON orders
FOR EACH ROW
DECLARE
v_username varchar2(10);
BEGIN
-- Find username of person performing UPDATE on the table
SELECT user INTO v_username
FROM dual;
-- Update updated_date field to current system date
:new.updated_date := sysdate;
-- Update updated_by field to the username of the person performing the UPDATE
:new.updated_by := v_username;
END;

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

98
 After update Trigger

An AFTER UPDATE Trigger means that Oracle will fire this trigger after the UPDATE
operation is executed.

The syntax for an AFTER UPDATE Trigger is:

CREATE or REPLACE TRIGGER trigger_name


AFTER UPDATE
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

99
ON table_name
[FOR EACH ROW ]
DECLARE
-- variable declarations
BEGIN
-- trigger code
EXCEPTION
WHEN ...
-- exception handling
END;

Trigger name is name of the trigger

Restrictions:

 You can not create an AFTER trigger on a view.


 You can not update the : NEW values.
 You can not update the : OLD values.

For example:

If you had a table created as follows:

Create table Orders2


( order_id number(5),
quantity number (4),
cost_per_item number(6,2),
total_cost number(8,2));

We could then create an AFTER UPDATE trigger as follows:

CREATE OR REPLACE TRIGGER orders_after_update


AFTER UPDATE ON orders2 FOR EACH ROW
DECLARE
v_username varchar2(10);
BEGIN
SELECT user INTO v_username
FROM dual;

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

100
-- Insert record into audit table
INSERT INTO orders_audit
( order_id,
quantity_before,
quantity_after,
username )
VALUES
( :new.order_id,
:old.quantity,
:new.quantity,
v_username );
END;

Delete Triggers
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

101
 Before Delete Trigger

A BEFORE DELETE Trigger means that Oracle will fire this trigger before the DELETE
operation is executed.

The syntax for a BEFORE DELETE Trigger is:

CREATE or REPLACE TRIGGER trigger_name


BEFORE DELETE
ON table_name
[ FOR EACH ROW ]
DECLARE
-- variable declarations
BEGIN
-- trigger code
EXCEPTION
WHEN ...
-- exception handling
END;

trigger_name is the name of the trigger to create.

Restrictions:

 You can not create a BEFORE trigger on a view.


 You can update the : NEW values.
 You can not update the : OLD values.

For example:

If you had a table created as follows:

Create table Orders2


( order_id number(5),
quantity number (4),
cost_per_item number(6,2),
total_cost number(8,2));

We could then create a BEFORE DELETE trigger as follows:


REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

102
CREATE OR REPLACE TRIGGER orders_before_delete
BEFORE DELETE
ON orders
FOR EACH ROW

DECLARE
v_username varchar2 (10);

BEGIN

-- Find username of person performing the DELETE on the table


SELECT user INTO v_username
FROM dual;

-- Insert record into audit table


INSERT INTO orders_audit
( order_id,
quantity,
cost_per_item,
total_cost,
delete_date,
deleted_by )
VALUES
( :old.order_id,
:old.quantity,
:old.cost_per_item,
:old.total_cost,
sysdate,
v_username );

END;

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

103
 After Delete Trigger

An AFTER DELETE Trigger means that Oracle will fire this trigger after the DELETE
operation is executed.

The syntax for an AFTER DELETE Trigger is:

CREATE or REPLACE TRIGGER trigger_name


AFTER DELETE
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

104
ON table_name
[ FOR EACH ROW ]
DECLARE
-- variable declarations
BEGIN
-- trigger code
EXCEPTION
WHEN ...
-- exception handling
END;

Trigger_name is the name of the trigger to create.

Restrictions:

 You can not create an AFTER trigger on a view.


 You can not update the : NEW values.

You can not update the: OLD values.

For example:

If you had a table created as follows:

Create table Orders


( order_id number(5),
quantity number(4),
cost_per_item number(6,2),
total_cost number (8,2));

A DELETE UPDATE trigger can be create as follows:

CREATE OR REPLACE TRIGGER orders_after_delete


AFTER DELETE
ON orders
FOR EACH ROW
DECLARE
v_username varchar2 (10);
BEGIN

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

105
-- Find username of person performing the DELETE on the table
SELECT user INTO v_username
FROM dual;
-- Insert record into audit table
INSERT INTO orders_audit
( order_id,
quantity,
cost_per_item,
total_cost,
delete_date,
deleted_by)
VALUES
( :old.order_id,
:old.quantity,
:old.cost_per_item,
:old.total_cost,
sysdate,
v_username );
END;

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

106
Drop Triggers
 Drop a Trigger

The syntax for a dropping a Trigger is:

DROP TRIGGER trigger_name;

Mutating Error

The Mutating table error is a well-known problem encountered in development; most


developers have come across this error.

ORA-04091: table <tablename> is mutating,


trigger/function may not see it
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

107
The basic reason for this error is the way Oracle manages a read consistent view of data.
The error is encountered when a row-level trigger accesses the same table on which it is
based, while executing. The table is said to be mutating. Mutation will not occur if a
single record is inserted in the table (using VALUES clause). If bulk insertion is done or
data is inserted from another table mutation will occur.

The mutating error is not only encountered during queries, but also for insert, updates and
deletes present in the trigger. Below is a table that explains the various transaction
scenarios that involves a trigger and whether it is prone to generate the mutating error.
The OPERATION column explains the DML activity being performed and the TYPE
column lists the type of trigger created and the execution level.

Case 1: When Trigger on table refers the same table:


-----------------------------------------------------------------
OPERATION TYPE MUTATING?
-----------------------------------------------------------------
insert before/statement-level No
insert after/statement-level No
update before/statement-level No
update after/statement-level No
delete before/statement-level No
delete after/statement-level No

insert before/row-level Single row Multi-row


No Yes
insert after/row-level Yes
update before/row-level Yes
update after/row-level Yes
delete before/row-level Yes
delete after/row-level Yes
-----------------------------------------------------------------

A very simple example is given below.

SQL> create table am27


2 (col1 number,
3 col2 varchar2(30));

Table created.

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

108
SQL> create or replace trigger am27_trg
2 before insert or update or delete
3 on am27
4 for each row
5 declare
6 l_chk pls_integer;
7 begin
8 select count(1)
9 into l_chk
10 from am27;
11 -- more processing...
12 end;

Trigger created.

SQL> insert into am27 values (1, 'testing');

1 row created.

SQL> update am27


2 set col1 = 2;
update am27
*
ERROR at line 1:
ORA-04091: table SYSTEM.AM27 is mutating, trigger/function may not see it
ORA-06512: at "SYSTEM.AM27_TRG", line 4
ORA-04088: error during execution of trigger 'SYSTEM.AM27_TRG'

In the above example, as table AM27 is being queried in the trigger AM27_TRG that is
based on the same table, a mutating error is received.

It is also possible for ORA-4091 to be encountered when querying a table other than the
table on which the trigger is based! This happens when a foreign key reference is present
with an on-delete-cascade option. A row level trigger on the master table will mutate if
the detail table is being referred to in the trigger, for a delete transaction. This will only
happen if the foreign key on the detail table is created with the on delete cascade option.
No mutation occurs if the master table is being referred in a trigger on the detail table.

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

109
There is one odd case where mutation may occur when some other table in the trigger is
referred to; below is an example of such a condition.

AM10 is a master table. AM10_DTL is the detail table that is related to the master table
with the on-delete-cascade option. AM10_BEF_TRG is created on the master table that
queries the detail table for some information. Issuing a delete on the master table results
in the mutation error.

SQL> create table am10


2 (col1 number, col2 varchar2(10));

Table created.

SQL> create table am10_dtl


2 (col1 number,
3 col2 varchar2(10));

Table created.

SQL> alter table am10 add primary key (col1);

Table altered.

SQL> alter table am10_dtl add foreign key (col1) references am10(col1) on delete
cascade;

Table altered.

SQL> create or replace trigger am10_bef_trg


2 before insert or update or delete on am10
3 for each row
4 declare
5 l_chk pls_integer;
6 begin
7 select 1
8 into l_chk
9 from am10_dtl
10 where col1 = :new.col1;
11 dbms_output.put_line('ok');

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

110
12 exception
13 when no_data_found then
14 dbms_output.put_line('no dtl recs');
15 end;
16 /

Trigger created.

SQL> insert into am10 values (1, 'amar');


err

1 row created.

SQL> insert into am10 values (2, 'chk');


err

1 row created.

SQL> insert into am10_dtl values(1, 'cooler');

1 row created.

SQL> insert into am10_dtl values (2, 'validator');

1 row created.

SQL> delete from am10 where col1= 1;


delete from am10 where col1= 1
*
ERROR at line 1:
ORA-04091: table SYSTEM.AM10_DTL is mutating, trigger/function may not see it
ORA-06512: at "SYSTEM.AM10_BEF_TRG", line 4
ORA-04088: error during execution of trigger 'SYSTEM.AM10_BEF_TRG'

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

111
Solutions for Mutating Error
Here is a technical paper for Oracle Mutating Error.
http://www.procaseconsulting.com/learning/papers/200004%20mutating
%20table.pdf
Trigger Cascading

Triggers supplement the standard capabilities of Oracle to provide a highly customized


database management system. For example, a trigger can restrict DML operations against
a table to those issued during regular business hours. You can also use triggers to:

 Automatically generate derived column values


 Prevent invalid transactions
 Enforce complex security authorizations
 Enforce referential integrity across nodes in a distributed database
 Enforce complex business rules
 Provide transparent event logging
 Provide auditing
 Maintain synchronous table replicates
 Gather statistics on table access
 Modify table data when DML statements are issued against views
 Publish information about database events, user events, and SQL statements to
subscribing applications

Although triggers are useful for customizing a database, use them only when necessary.
Excessive use of triggers can result in complex interdependencies, which can be difficult
to maintain in a large application. For example, when a trigger fires, a SQL statement
within its trigger action potentially can fire other triggers, resulting in cascading
triggers.

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

112
Figure showing the Cascading Triggers….

Database Triggers.
Database trigger are defined at database or schema level and can be fired at certain level
database and DDL events. In particular these events occur at database-wide
events occur. The DDL events incldue CREATE, DROP and ALTER
The following are the database events include as follows.
 STARTUP : - Fires when the database is opened.
 SHUTDOWN :- Fires when the database is shutdown normally.
 SERVERERROR :- Fires when an Oracle error is raised.
 LOGON :- Fires when an Oracle Session begins.
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

113
 LOGOFF. :- Fires when an Oracle Session terminates normally.

The database trigger of intrest here is the 'BEFORE LOFFOFF' trigger. It used to collect
summrized session-level wait event data and CPU statistics from the following
Views V$SESSION and V$SESSTAT view when sessions log o

CREATE OR REPLACE TRIGGER trigger name


{BEFORE | AFTER } { datbase event} ON {DATBASE |SCHEMA }
DECLARE
varible declarations
BEGIN
/* Save code here */
END
Syntax of Database Trigger

Conclusion

Maintaining a consistent view of the data is an important feature of Oracle. The mutating
error conflicts with maintaining a consistent view, therefore, care should be taken to write
proper code and avoid such triggers. It is for the developers to write proper logic so that
such complications do not arise.

If there is a requirement to update the base table from the row-level trigger, then split the
logic across multiple triggers. The required information can be stored in a temporary
table, PL/SQL table or package variables when the row-level trigger is executed. A
statement-level trigger can then be used to pickup the stored information and apply it to
the table.

Collections:
A PL/SQL record is a collection of basic types of data and can be accessed as a single
unit.PL/SQL records are similar in structure to a row in a database table.A record consists
of components of any scalar, PL/SQL record, or PL/SQL table type.

It makes your life easier by transferring the entire row into a record, rather than
transferring each column into a variable separately.

PL/SQL supports three kinds of records:


REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

114
 table-based,

 cursor-based, and

 programmer-defined

Both cursor-based records in a collective assignment must be based on the same


cursor.Both table-based records in a collective assignment must be based on the same
table.Both programmer-defined records in a collective assignment must be based on the
same TYPE...RECORD statement.

PL/SQL Table Based Records:


You define and declare records either in the declaration section of a PL/SQL block, or
globally, .via a package specification. A table-based record is one whose structure is
drawn from the list of columns in the table.
A table-based record is drawn from a particular table structure.
%TYPE and %ROWTYPE

%TYPE is used to declare a variable that is of the same type as a specified table’s
column.
Emp_number emp.empno%type;
%ROWTYPE is used to declare a record i.e. a variable that represents the entire row of a
table.Emp_record emp%rowtype

PL/SQL Cursor Based Records :

Cursor-Based record has fields that match in name, datatype, and order to the final list of
columns in
the cursor’s SELECT statement.

Example 1 of Cursor Based Records


Cursor emp_cur is

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

115
Select ename, eno. , hiredate

From emp;
emp_rec emp_cur%ROWTYPE ;

Example 2 of Cursor Based Records


CURSOR c IS
SELECT beer, price

FROM Sells
WHERE bar = 'Joe''s bar';
Bp1 c%ROWTYPE;

PL/SQL Programmer Defined Records:


These are records in which you, the programmer, define a record type.
Example 1 of Programmer Defined Records:
Type my_first_record is record (
Name varchar2(20);
Age number;
Salary number;);

Var_of_myfirstrecord my_first_record;

Example 2 of Programmer Defined Records :


DECLARE
TYPE employee_rectype IS RECORD (
emp_id NUMBER(10) NOT NULL
,dept_no dept.deptno%TYPE
,nаme empnаme_rectype
,hire_dаte DATE := SYSDATE);
new_emp_rec employee_rectype;

Example for Programmer Defined Records:


DECLARE
TYPE time_rec_type IS RECORD
(curr_date DATE,

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

116
curr_day VARCHAR2(12),
curr_time VARCHAR2(8) := '00:00:00');

time_rec TIME_REC_TYPE;
BEGIN
SELECT sysdate
INTO time_rec.curr_date
FROM dual;

time_rec.curr_day := TO_CHAR(time_rec.curr_date, 'DAY');


time_rec.curr_time :=
TO_CHAR(time_rec.curr_date, 'HH24:MI:SS');

DBMS_OUTPUT.PUT_LINE ('Date: '||time_rec.curr_date);


DBMS_OUTPUT.PUT_LINE ('Day: '||time_rec.curr_day);
DBMS_OUTPUT.PUT_LINE ('Time: '||time_rec.curr_time);
END;

Example for Table Based ,Cursor Based and User Defined Record:
DECLARE
CURSOR emp_cur
IS
SELECT empno
,ename
FROM emp
WHERE empno = '7369';

TYPE emp_rec IS RECORD(


empno NUMBER
,ename VARCHAR2(20)
);

tab_rec emp%ROWTYPE;
-----Table Based Record Type Declaration
cur_rec emp_cur%ROWTYPE;
-----Cursor Based Record Type Declaration
user_rec emp_rec;
-----User Defined Based Record Type Declaration
BEGIN

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

117
/* Assingnment for User Defined Record type values */
user_rec.empno := '11';
user_rec.ename := 'Raj';
DBMS_OUTPUT.put_line('User Defined Record Based Values :');
DBMS_OUTPUT.put_line( 'Empno:'
|| user_rec.empno
|| ' '
|| 'Ename:'
|| user_rec.ename
);

/* Assingnment for Table Based Record type values */


SELECT *
INTO tab_rec
FROM emp
WHERE empno = '7499';

DBMS_OUTPUT.put_line('Table Defined Record Based Values :');


DBMS_OUTPUT.put_line( 'Empno:'
|| tab_rec.empno
|| ' '
|| 'Ename:'
|| tab_rec.ename
);

/* Assingnment for Cursor Based Record type values */


OPEN emp_cur;

LOOP
FETCH emp_cur
INTO cur_rec;

EXIT WHEN emp_cur%NOTFOUND;


END LOOP;

DBMS_OUTPUT.put_line('Cursor Defined Record Based Values :');


DBMS_OUTPUT.put_line( 'Empno:'
|| cur_rec.empno
|| ' '

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

118
|| 'Ename:'
|| cur_rec.ename
);
END;

PL/SQL Collections:

A collection is a data structure that acts like an array. A collection is defined as an ordered
group of elements, all of the same type. Individual element in a collection can be
accessed by using index like an array in C. There are three types of collections in oracle

Index by tables :
Objects of the TABLE type are called INDEX BY tables. they are modeled as database
tables.
INDEX BY tables use a primary key to provide u with array like access to rows.

an index by table is similar to an array and must contain 2 components

 a primary key of data type BINARY_INTEGER that INDEX BY table.


 A column of a scalar or record data type,which stored the INDEX BY table
elements.

Index by index can increase dynamically because it is uncontrained. INDEX BY tables


can have one column and unique indentifier to that one column,neither of which be
named.The column can belong to any scalar or record data type,but the primary key must
belong to type BINARY_INTEGER.

The magnitude range of a BINARY_INTEGER is -2147483647 to 2147483647,so the


primary key value can be negative.indexing does not start with 1.

Index-by tables cannot be stored in database tables, so they are non-persistent.


DELETE and TRIM methods cannot be used with index-by tablesObjects of type TABLE
are known as PL/SQL tables.PL/SQL tables use a primary key to give you array-like
access to rows. The number of rows in a PL/SQL table can increase dynamically. The
PL/SQL table grows as new rows are added. PL/SQL tables can have one column and a
primary key, neither of which can be named. The column can belong to any scalar type,
but the primary key must belong to type BINARY_INTEGER.
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

119
A PL/SQL table can consist of one simple datatype or be defined as a type of record and
is sometimes referred to as an Index by table.Rows in a PL/SQL table do not have to be
contiguous.
Tables with simple datatypes can be populated as:
<variable>(<integer>) := <value>;
Tables with complex datatypes will need the columns populated individually as:
<variable>(<integer>).<column_name> := <value>;
Or from a cursor:
fetch <cursor_name> into <variable>(<integer>);
Syntax :
TYPE type_name IS TABLE OF element_type [NOT NULL]
INDEX BY [BINARY_INTEGER | PLS_INTEGER | VARCHAR2(size_limit)];
INDEX BY key_type;

The key_type can be numeric, either BINARY_INTEGER or PLS_INTEGER(9i).


It can also be VARCHAR2 or one of its subtypes VARCHAR, STRING, or LONG. You
must specify the length of a VARCHAR2-based key, except for LONG which is
equivalent to declaring a key type of VARCHAR2(32760).

The types RAW, LONG RAW, ROWID, CHAR, and CHARACTER are not allowed as
keys for an associative array.

Example1:
Declare
TYPE TYP_TAB IS TABLE OF NUMBER INDEX BY PLS_INTEGER ;
my_tab TYP_TAB ;
Begin
my_tab(1) := 5 ;
my_tab(2) := 10 ;
my_tab(3) := 15 ;
dbms_output.put_line(my_tab(1));
dbms_output.put_line(my_tab(2));
dbms_output.put_line(my_tab(3));
End ;

Example2:
DECLARE

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

120
TYPE typ_tab IS TABLE OF NUMBER;

my_tab typ_tab := typ_tab(1, 2, 3, 4, 5);


BEGIN
FOR i IN my_tab.FIRST .. my_tab.LAST
LOOP
DBMS_OUTPUT.put_line( 'my_tab('|| LTRIM(TO_CHAR(i))|| ') = '||
TO_CHAR(my_tab(i)));
END LOOP;
END;

Example3:
declare
type emp_tab is table of emp%rowtype index by binary_integer;
emptab emp_tab;
begin
select * into emptab(7788) from emp where empno='7788';
dbms_output.put_line('Empno:'||emptab(7788).empno );
dbms_output.put_line('Ename:'||emptab(7788).ename );
dbms_output.put_line('Sal:'||emptab(7788).sal );
dbms_output.put_line('Depetno:'||emptab(7788).deptno );
end;

Example 4:
DECLARE
TYPE my_dept_table IS TABLE OF VARCHAR2(20)
INDEX BY BINARY_INTEGER;

var_of_dept my_dept_table;
index_value NUMBER;
BEGIN
FOR dept_rec IN (SELECT *
FROM dept)
LOOP
var_of_dept(dept_rec.deptno) := dept_rec.dname;
END LOOP;

index_value := var_of_dept.FIRST;

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

121
LOOP
EXIT WHEN index_value IS NULL;
DBMS_OUTPUT.put_line(index_value || ' ' || var_of_dept(index_value));
index_value := var_of_dept.NEXT(index_value);
END LOOP;
END;

Example5:
DECLARE
TYPE typ_tab IS TABLE OF dept%ROWTYPE
INDEX BY PLS_INTEGER;
tb_dept typ_tab;
rec dept%ROWTYPE;
CURSOR cdept
IS
SELECT *
FROM dept;
BEGIN
OPEN cdept;
LOOP
FETCH cdept
INTO rec;
EXIT WHEN cdept%NOTFOUND;
tb_dept(cdept%ROWCOUNT) := rec;
END LOOP;
DBMS_OUTPUT.put_line('Department'|| ' - ' || 'Location');
FOR i IN tb_dept.FIRST .. tb_dept.LAST
LOOP
DBMS_OUTPUT.put_line(tb_dept(i).dname || ' - ' || tb_dept(i).loc);
END LOOP;
END;

Example 6:

DECLARE
CURSOR ename_cur
IS
SELECT ename

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

122
FROM emp;
TYPE ename_type IS TABLE OF emp.ename%TYPE
INDEX BY BINARY_INTEGER;

ename_tab ename_type;
v_counter INTEGER := 0;
BEGIN
FOR name_rec IN ename_cur
LOOP
v_counter := v_counter + 1;
ename_tab(v_counter) := name_rec.ename;
DBMS_OUTPUT.put_line('ename(' || v_counter || '): '
|| ename_tab(v_counter)
);
END LOOP;
END;

Nested Tables :

An ordered group of items of type TABLE are called nested tables. Nested tables can
contain multiple columns and can be used as variables, parameters, results, attributes, and
columns. They can be thought of as one column database tables. Rows of a nested table
are not stored in any particular order.

The size of a nested table can increase dynamically, i.e., nested tables are unbounded.
Elements in a nested table initially have consecutive subscripts, but as elements are
deleted, they can have non-consecutive subscripts.

Nested tables can be fully manipulated using SQL, Pro*C, OCI, and PL/SQL. The range
of values for nested table subscripts is 1..2147483647. To extend a nested table, the built-
in procedure EXTEND must be used. To delete elements, the built-in procedure DELETE
must be used.

An uninitialized nested table is atomically null, so the IS NULL comparison operator can
be used to see if a nested table is null. Oracle8 provides new operators such as CAST,
THE, and MULTISET for manipulating nested tables.

Examples of Nested Tables

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

123
Example 1:

The following example illustrates how a simple nested table is created.

a) First, define a Object type as follows:


Code: sql
SQL> CREATE TYPE ELEMENTS AS OBJECT (
2> ELEM_ID NUMBER(6),
3> PRICE NUMBER(7,2));
4> /
b) Next, create a table type ELEMENTS_TAB which stores ELEMENTS objects:

Code: sql
SQL> CREATE TYPE ELEMENTS_TAB AS TABLE OF ELEMENTS;
2> /
c) Finally, create a database table STORAGE having type ELEMENTS_TAB as one of its
columns:
Code: sql
SQL> CREATE TABLE STORAGE (
2> SALESMAN NUMBER(4),
3) ELEM_ID NUMBER(6),
4) ORDERED DATE,
5) ITEMS ELEMENTS_TAB)
6) NESTED TABLE ITEMS STORE AS ITEMS_TAB;

Example 2:
----------

This example demonstrates how to populate the STORAGE table with a single row:
Code: sql
SQL> INSERT INTO STORAGE
2> VALUES (100,123456,SYSDATE,
3> ELEMENTS_TAB(ELEMENTS(175692,120.12),
4> ELEMENTS(167295,130.45),
5> ELEMENTS(127569,99.99)));

Example 3:

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

124
----------

The following example demonstrates how to use the operator THE which is used in a
SELECT statement to identify a nested table:
Code: sql
SQL> INSERT INTO
2> THE
3> (SELECT ITEMS FROM STORAGE WHERE ELEM_ID = 123456)
4> VALUES (125762, 101.99);

Example 4:
----------

The following example shows how to update the STORAGE table row where salesman
column has value 100:
Code: sql
SQL> UPDATE STORAGE
2> SET ITEMS = ELEMENTS_TAB(ELEMENTS(192512, 199.99))
3> WHERE SALESMAN = 100;

Varrays :

Varrays are ordered groups of items of type VARRAY. Varrays can be used to associate a
single identifier with an entire collection. This allows manipulation of the collection as a
whole and easy reference of individual elements.

The maximum size of a varray needs to be specified in its type definition. The range of
values for the index of a varray is from 1 to the maximum specified in its type definition.
If no elements are in the array, then the array is atomically null. The main use of a varray
is to group small or uniform-sized collections of objects.

Elements of a varray cannot be accessed individually through SQL, although they can be
accessed in PL/SQL, OCI, or Pro*C using the array style subscript. The type of the
element of a VARRAY can be any PL/SQL type except the following:
Code: sql
BOOLEAN

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

125
TABLE
VARRAY
object types WITH TABLE OR VARRAY attributes
REF CURSOR
NCHAR
NCLOB
NVARCHAR2

Varrays can be used to retrieve an entire collection as a value. Varray data is stored in-
line, in the same tablespace as the other data in its row.

When a varray is declared, a constructor with the same name as the varray is implicitly
defined. The constructor creates a varray from the elements passed to it. You can use a
constructor wherever you can use a function call, including the SELECT, VALUES, and
SET clauses.

A varray can be assigned to another varray, provided the datatypes are the exact same
type. For example, suppose you declared two PL/SQL types:
Code: sql
TYPE My_Varray1 IS VARRAY(10) OF My_Type;
TYPE My_Varray2 IS VARRAY(10) OF My_Type;

An object of type My_Varray1 can be assigned to another object of type My_Varray1


because they are the exact same type. However, an object of type My_Varray2 cannot be
assigned to an object of type My_Varray1 because they are not the exact same type, even
though they have the same element type.

Varrays can be atomically null, so the IS NULL comparison operator can be used to see if
a varray is null. Varrays cannot be compared for equality or inequality.

Examples for Varrays

Example 5:
---------

The following shows how to create a simple VARRAY:

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

126
a) First, define a object type ELEMENTS as follows:
Code: sql
SQL> CREATE TYPE MEDICINES AS OBJECT (
2> MED_ID NUMBER(6),
3> MED_NAME VARCHAR2(14),
4> MANF_DATE DATE);
5> /

b) Next, define a VARRAY type MEDICINE_ARR which stores MEDICINES objects:

Code: sql
SQL> CREATE TYPE MEDICINE_ARR AS VARRAY(40) OF MEDICINES;
2> /

c) Finally, create a relational table MED_STORE which has MEDICINE_ARR as a


column type:
Code: sql
SQL> CREATE TABLE MED_STORE (
2> LOCATION VARCHAR2(15),
3> STORE_SIZE NUMBER(7),
4> EMPLOYEES NUMBER(6),
5> MED_ITEMS MEDICINE_ARR);

Example 6:
----------

The following example shows how to insert two rows into the MED_STORE table:

Code: sql
SQL> INSERT INTO MED_STORE
2> VALUES ('BELMONT',1000,10,
3> MEDICINE_ARR(MEDICINES(11111,'STOPACHE',SYSDATE)));

SQL> INSERT INTO MED_STORE


2> VALUES ('REDWOOD CITY',700,5,
3> MEDICINE_ARR(MEDICINES(12345,'STRESS_BUST',SYSDATE)));

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

127
Example 7:
----------

The following example shows how to delete the second row we have inserted in example
6 above:
Code: sql
SQL> DELETE FROM MED_STORE
2> WHERE LOCATION = 'REDWOOD CITY';

Example 8:
----------

The following example shows how to update the MED_STORE table and add more
medicines to the Belmont store:

Code: sql
SQL> UPDATE MED_STORE
2> SET MED_ITEMS = MEDICINE_ARR (
3> MEDICINES(12346,'BUGKILL',SYSDATE),
4> MEDICINES(12347,'INHALER',SYSDATE),
5> MEDICINES(12348,'PAINKILL',SYSDATE));

Collection Methods :
A collection method is a built-in function or procedure that operates on collections and is
called using dot notation. The syntax follows:
collection_name.method_name[(parameters)]

 EXISTS
 COUNT
 LIMIT
 FIRST and LAST
 PRIOR and NEXT
 EXTEND
 TRIM
 DELETE

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

128
EXISTS(index):

Returns TRUE if the index element exists in the collection, else it returns FALSE.

Use this method to be sure you are doing a valid operation on the collection.
This method does not raise the SUBSCRIPT_OUTSIDE_LIMIT exception if used on an
element that does not exists in the collection.

If my_collection.EXISTS (10) Then


My_collection.DELETE(10) ;
End if ;

COUNT :

Returns the number of elements in a collection.

Declare
TYPE TYP_TAB IS TABLE OF NUMBER;
my_tab TYP_TAB := TYP_TAB( 1, 2, 3, 4, 5 );
Begin
Dbms_output.Put_line( 'COUNT = ' || To_Char( my_tab.COUNT ) ) ;
my_tab.DELETE(2) ;
Dbms_output.Put_line( 'COUNT = ' || To_Char( my_tab.COUNT ) ) ;
End ;

LIMIT:

Returns the maximum number of elements that a varray can contain.


Return NULL for Nested tables and Index-by tables

Declare
TYPE TYP_ARRAY IS ARRAY(30) OF NUMBER ;
my_array TYP_ARRAY := TYP_ARRAY( 1, 2, 3 ) ;
Begin
dbms_output.put_line( 'Max array size is ' || my_array.LIMIT ) ;
End;

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

129
FIRST and LAST :

Returns the first or last subscript of a collection.

If the collection is empty, FIRST and LAST return NULL

Declare
TYPE TYP_TAB IS TABLE OF NUMBER;
my_tab TYP_TAB := TYP_TAB( 1, 2, 3, 4, 5 );
Begin
For i IN my_tab.FIRST .. my_tab.LAST Loop
Dbms_output.Put_line( 'my_tab(' || Ltrim(To_Char(i)) || ') = ' || To_Char( my_tab(i) ) ) ;
End loop ;
End ;

Declare
TYPE TYP_TAB IS TABLE OF PLS_INTEGER INDEX BY VARCHAR2(1);
my_tab TYP_TAB;
Begin
For i in 65 .. 69 Loop
my_tab( Chr(i) ) := i ;
End loop ;
Dbms_Output.Put_Line( 'First= ' || my_tab.FIRST || ' Last= ' || my_tab.LAST ) ;
End ;

PRIOR(index) and NEXT(index) :

Returns the previous or next subscript of the index element.

If the index element has no predecessor, PRIOR(index) returns NULL. Likewise, if index
has no successor, NEXT(index) returns NULL.

Declare
TYPE TYP_TAB IS TABLE OF PLS_INTEGER INDEX BY VARCHAR2(1) ;
my_tab TYP_TAB ;
c Varchar2(1) ;
Begin
For i in 65 .. 69 Loop

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

130
my_tab( Chr(i) ) := i ;
End loop ;
c := my_tab.FIRST ; -- first element
Loop
Dbms_Output.Put_Line( 'my_tab(' || c || ') = ' || my_tab(c) ) ;
c := my_tab.NEXT(c) ; -- get the successor element
Exit When c IS NULL ; -- end of collection
End loop ;
End ;

NO DATA FOUND :
Declare
TYPE TYP_TAB IS TABLE OF PLS_INTEGER ;
my_tab TYP_TAB := TYP_TAB( 1, 2, 3, 4, 5 );
Begin
my_tab.DELETE(2) ; -- delete an element of the collection
For i in my_tab.FIRST .. my_tab.LAST Loop
Dbms_Output.Put_Line( 'my_tab(' || Ltrim(To_char(i)) || ') = ' || my_tab(i) ) ;
End loop ;
End ;

In this example, we get an error because one element of the collection was deleted.

One solution is to use the PRIOR()/NEXT() method:

Declare
TYPE TYP_TAB IS TABLE OF PLS_INTEGER ;
my_tab TYP_TAB := TYP_TAB( 1, 2, 3, 4, 5 );
v Pls_Integer ;
Begin
my_tab.DELETE(2) ;
v := my_tab.first ;
Loop
Dbms_Output.Put_Line( 'my_tab(' || Ltrim(To_char(v)) || ') = ' || my_tab(v) ) ;
v := my_tab.NEXT(v) ; -- get the next valid subscript
Exit When v IS NULL ;
End loop ;

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

131
End ;

Another solution is to test if the index exists before use it:

Declare
TYPE TYP_TAB IS TABLE OF PLS_INTEGER ;
my_tab TYP_TAB := TYP_TAB( 1, 2, 3, 4, 5 );
Begin
my_tab.DELETE(2) ;
For i IN my_tab.FIRST .. my_tab.LAST Loop
If my_tab.EXISTS(i) Then
Dbms_Output.Put_Line( 'my_tab(' || Ltrim(To_char(i)) || ') = ' || my_tab(i) ) ;
End if ;
End loop ;
End ;

EXTEND[(n[,i])] :

Used to extend a collection (add new elements)

EXTEND appends one null element to a collection.


EXTEND(n) appends n null elements to a collection.
EXTEND(n,i) appends n copies of the ith element to a collection.

Declare
TYPE TYP_NES_TAB is table of Varchar2(20) ;
tab1 TYP_NES_TAB ;
i Pls_Integer ;
Procedure Print( i in Pls_Integer ) IS
BEGIN Dbms_Output.Put_Line( 'tab1(' || ltrim(to_char(i)) ||') = ' || tab1(i) ) ; END ;
Procedure PrintAll IS
Begin
Dbms_Output.Put_Line( '* Print all collection *' ) ;
For i IN tab1.FIRST..tab1.LAST Loop
If tab1.EXISTS(i) Then
Dbms_Output.Put_Line( 'tab1(' || ltrim(to_char(i)) ||') = ' || tab1(i) ) ;

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

132
End if ;
End loop ;
End ;
Begin
tab1 := TYP_NES_TAB('One') ;
i := tab1.COUNT ;
Dbms_Output.Put_Line( 'tab1.COUNT = ' || i ) ;
Print(i) ;
-- the following line raise an error because the second index does not exists in the
collection
-- tab1(2) := 'Two' ;
-- Add one empty element --
tab1.EXTEND ;
i := tab1.COUNT ;
tab1(i) := 'Two' ; Printall ;
-- Add two empty elements --
tab1.EXTEND(2) ;
i := i + 1 ;
tab1(i) := 'Three' ;
i := i + 1 ;
tab1(i) := 'Four' ; Printall ;
-- Add three elements with the same value as element 4 --
tab1.EXTEND(3,1) ;
i := i + 3 ; Printall ;
End;

TRIM[(n)] :

Used to decrease the size of a collection

TRIM removes one element from the end of a collection.


TRIM(n) removes n elements from the end of a collection.

Declare
TYPE TYP_TAB is table of varchar2(100) ;
tab TYP_TAB ;
Begin
tab := TYP_TAB( 'One','Two','Three' ) ;

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

133
For i in tab.first..tab.last Loop
dbms_output.put_line( 'tab(' || ltrim( to_char( i ) ) || ') = ' || tab(i) ) ;
End loop ;
-- add 3 element with second element value --
dbms_output.put_line( '* add 3 elements *' ) ;
tab.EXTEND(3,2) ;
For i in tab.first..tab.last Loop
dbms_output.put_line( 'tab(' || ltrim( to_char( i ) ) || ') = ' || tab(i) ) ;
End loop ;
-- suppress the last element --
dbms_output.put_line( '* suppress the last element *' ) ;
tab.TRIM ;
For i in tab.first..tab.last Loop
dbms_output.put_line( 'tab(' || ltrim( to_char( i ) ) || ') = ' || tab(i) ) ;
End loop ;
End;

If you try to suppress more elements than the collection contents, you get a
SUBSCRIPT_BEYOND_COUNT exception.

DELETE[(n[,m])] :

DELETE removes all elements from a collection.


DELETE(n) removes the nth element from an associative array with a numeric key or a
nested table. If the associative array has a string key, the

element corresponding to the key value is deleted. If n is null, DELETE(n) does nothing.
DELETE(n,m) removes all elements in the range m..n from an associative array or nested
table. If m is larger than n or if m or n is null, DELETE(n,m)

does nothing

Caution :
LAST returns the greatest subscript of a collection and COUNT returns the number of
elements of a collection.
If you delete some elements, LAST != COUNT.

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

134
Suppression of all the elements

Declare
TYPE TYP_TAB is table of varchar2(100) ;
tab TYP_TAB ;
Begin
tab := TYP_TAB( 'One','Two','Three' ) ;
dbms_output.put_line( 'Suppression of all elements' ) ;
tab.DELETE ;
dbms_output.put_line( 'tab.COUNT = ' || tab.COUNT) ;
End;

Suppression of the second element

Declare
TYPE TYP_TAB is table of varchar2(100) ;
tab TYP_TAB ;
Begin
tab := TYP_TAB( 'One','Two','Three' ) ;
dbms_output.put_line( 'Suppression of the 2nd element' ) ;
DELETE(2) ;
dbms_output.put_line( 'tab.COUNT = ' || tab.COUNT) ;
dbms_output.put_line( 'tab.LAST = ' || tab.LAST) ;
For i IN tab.FIRST .. tab.LAST Loop
If tab.EXISTS(i) Then
dbms_output.put_line( tab(i) ) ;
End if ;
End loop ;
End;

The following list shows when a given exception is raised:

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

135
Collection Exception Raised when...

COLLECTION_IS_NULL you try to operate on an atomically null collection.

a subscript designates an element that was deleted,


NO_DATA_FOUND
or a nonexistent element of an associative array.

a subscript exceeds the number of elements in a


SUBSCRIPT_BEYOND_COUNT
collection.

SUBSCRIPT_OUTSIDE_LIMIT a subscript is outside the allowed range.

a subscript is null or not convertible to the key


type.
VALUE_ERROR This exception might occur if the key is defined as
a PLS_INTEGER range,
and the subscript is outside this range.

BULK COLLECT :

This keyword ask the SQL engine to return all the rows in one or several collections
before returning to the PL/SQL engine.So, there is one single roundtrip for all the rows
between SQL and PL/SQL engine.BULK COLLECT cannot be use on the client-side

(Select)(Fetch)(execute immediate) … BULK COLLECT Into collection_name


[,collection_name, …] [LIMIT max_lines] ;

LIMIT is used to limit the number of rows returned

Declare
TYPE TYP_TAB_EMP IS TABLE OF EMP.EMPNO%Type ;
Temp_no TYP_TAB_EMP ; -- collection of EMP.EMPNO%Type
Cursor C_EMP is Select empno From EMP ;

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

136
Pass Pls_integer := 1 ;
Begin
Open C_EMP ;
Loop
-- Fetch the table 3 by 3 --
Fetch C_EMP BULK COLLECT into Temp_no LIMIT 3 ;
Exit When C_EMP%NOTFOUND ;
For i In Temp_no.first..Temp_no.last Loop
dbms_output.put_line( 'Pass ' || to_char(Pass) || ' Empno= ' || Temp_no(i) ) ;
End loop ;
Pass := Pass + 1 ;
End Loop ;
End ;

Declare
TYPE TYP_TAB_EMP IS TABLE OF EMP.EMPNO%Type ;
Temp_no TYP_TAB_EMP ;
Cursor C_EMP is Select empno From EMP ;
max_lig Pls_Integer := 3 ;
Begin
Open C_EMP ;
Loop
Fetch C_EMP BULK COLLECT into Temp_no LIMIT max_lig ;
Forall i In Temp_no.first..Temp_no.last
Update EMP set SAL = Round(SAL * 1.1) Where empno = Temp_no(i) ;
Commit ; -- Commit every 3 rows
Temp_no.DELETE ;
Exit When C_EMP%NOTFOUND ;
End Loop ;
End ;

BULK COLLECT can also be used to retrieve the result of a DML statement that uses the
RETURNING INTO clause:

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

137
FORALL index IN min_index .. max_index [SAVE EXCEPTION] sql_orderThis
instruction allows to compute all the rows of a collection in a single pass.
FORALL cannot be use on the client-side and can proceed one and only one statement at
a time.

Declare
TYPE TYP_TAB_TEST IS TABLE OF TEST%ROWTYPE ;
tabrec TYP_TAB_TEST ;
CURSOR C_test is select A, B From TEST ;
Begin
-- Load the collection from the table --
Select A, B BULK COLLECT into tabrec From TEST ;
-- Insert into the table from the collection --
Forall i in tabrec.first..tabrec.last
Insert into TEST values tabrec(i) ;
-- Update the table from the collection --
For i in tabrec.first..tabrec.last Loop
tabrec(i).B := tabrec(i).B * 2 ;
End loop ;
-- Use of cursor --
Open C_test ;
Fetch C_test BULK COLLECT Into tabrec ;
Close C_test ;
End ;

Declare
TYPE TAB_EMPNO is table of EMP.EMPNO%TYPE ;
TYPE TAB_EMPNAME is table of EMP.ENAME%TYPE ;
no_tab TAB_EMPNO ;
na_tab TAB_EMPNAME ;
Cursor CEMP is Select EMPNO, ENAME From EMP ;
Begin
Open CEMP;
Fetch CEMP BULK COLLECT Into no_tab, na_tab ;
Close CEMP ;

Forall i in no_tab.first..no_tab.last
Update EMP set ENAME = na_tab(i) where EMPNO = no_tab(i) ;

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

138
End ;

Declare
TYPE TYP_TAB_TEST IS TABLE OF TEST%ROWTYPE ;
TYPE TYP_TAB_A IS TABLE OF TEST.A%TYPE ;
TYPE TYP_TAB_B IS TABLE OF TEST.B%TYPE ;
tabrec TYP_TAB_TEST ;
taba TYP_TAB_A ;
tabb TYP_TAB_B ;
total Pls_integer := 0 ;
CURSOR C_test is select A, B From TEST ;
begin
-- Load the collection from the table --
Select A, B BULK COLLECT into tabrec From TEST ;
-- Insert rows --
Forall i in tabrec.first..tabrec.last
insert into TEST values tabrec(i) ;
For i in tabrec.first..tabrec.last Loop
total := total + SQL%BULK_ROWCOUNT(i) ;
End loop ;
dbms_output.put_line('Total insert : ' || to_char( total) ) ;
total := 0 ;
-- Upadate rows --
For i in tabrec.first..tabrec.last loop
update TEST set row = tabrec(i) where A = tabrec(i).A ;
End loop ;
For i in tabrec.first..tabrec.last Loop
total := total + SQL%BULK_ROWCOUNT(i) ;
End loop ;
dbms_output.put_line('Total upfdate : ' || to_char( total) ) ;
End ;

Index-By Table Nested Table VARRAY


Dimensionality Single Single Single
Usable in SQL? No Yes Yes
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

139
Index-By Table Nested Table VARRAY
Usable as column No Yes; data stored "outYes; data stored "in
datatype in a table? of line" (in separateline" (in same table)
table)
Uninitialized state Empty (cannot be null);Atomically null;Atomically null;
elements undefined illegal to referenceillegal to reference
elements elements
Initialization Automatic, whenVia constructor, fetch,Via constructor,
declared assignment fetch, assignment
In PL/SQL, elements BINARY_INTEGER Positive integerPositive integer
referenced via (-2,147,483,647 ..between 1 andbetween 1 and
2,147,483,647) 2,147,483,647 2,147,483,647
Sparse? Yes Initially, no; afterNo
deletions, yes
Bounded? No Can be extended Yes
Can assign value to Yes No; may need toNo; may need to
any element at any EXTEND first EXTEND first, and
time? cannot EXTEND
past upper bound
Means of extending Assign value to elementUse built-in EXTENDEXTEND (or
with a new subscript procedure (or TRIMTRIM), but only up
to condense), with noto declared
predefined maximum maximum size
Can be compared for No No No
equality?
Retains ordering and N/A No Yes
subscripts when
stored in and
retrieved from
database?

Difference Between VARRAYs and Nested Tables

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

140
VARRAY Nested Tables
s  No maximum size
 Maximum size  Data is stored out-of-
specified at time of line in a store table
definition  Do not retain ordering
 Data is stored in-line and subscripts when
 Retain their ordering stored in database
and subscripts when
stored in database

When to use Nested Tables instead of VARRAYs

 When the order of the data elements is not


important
 When indexing is required on an attribute of the
nested table type
 When there is no set limit to the number of entries
for the data elements
 When the data elements need to be queried

Advanced PLSQL :

Autonomous transactions :
Autonomous transactions are independent transactions
that can be called from within another transaction.This
allows you to leave the calling transaction and do some
SQL operations, commit or rollback those operations, and
return to the calling transaction’s context and continue with
that transaction.Only committed data can be shared by both
transactions.

The following is a simple example to explain Autonomous


transactions.
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

141
Create a table using the following script.

CREATE TABLE mytable (NAME VARCHAR2(100), msg


VARCHAR2(500), ID NUMBER);

Now create a small procedure using the following


script.The procedure will be executed under an autonomous
transaction.(This transaction will be independent of the
parent transaction.)

CREATE OR REPLACE PROCEDURE


autonomous_example
IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
INSERT INTO mytable
(NAME, msg, ID
)
VALUES ('Abcd2', 'Inside Autonomous', 4
);

INSERT INTO mytable


(NAME, msg, ID
)
VALUES ('Abcd2', 'Inside Autonomous', 5
);
COMMIT;

END autonomous_example;

Here the keyword PRAGMA is a compiler directive.

Now executes the following TEST script

DECLARE
BEGIN
INSERT INTO mytable
(NAME, msg, ID
)

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

142
VALUES ('Abcd', 'Outside Autonomous', 1
);

autonomous_example ();
COMMIT;
END;

select *from mytable;

This will create 3 rows in MyTable.

Now remove the records from MyTable

delete from mytable;


3 rows deleted

SQL> commit;
Commit complete

DECLARE
BEGIN
INSERT INTO mytable
(NAME, msg, ID
)
VALUES ('Abcd', 'Outside Autonomous', 1
);

autonomous_example ();
ROLLBACK;
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

143
END;

See the above script,we have added a rollback statement


instead of COMMIT to rollback the current transaction.This
will not have any effect to the autonomous transaction in
procedure Autonomous_Example.

This will create only 2 rows in MyTable as seen below.

This is because the ROLLBACK performed in the script


(Main transaction) has no effect on the Autonomous
Transactions declared inside the procedure
Autonomous_Example.
There are no limits on how many levels of autonomous
transactions can be called in a chain.

The autonomous transaction can be declared in the


following ,
1.Stored procedure
2.Function
3.Package
4.Type method
5.Top-level anonymous block

RESTRICTIONS:-
Pragma can't be used to mark all subprograms in a package
as autonomous.Only individual routines can be marked
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

144
autonomous.It can be coded any where in the declaration
section of the sub program.
Once started, an autonomous transaction is fully
independent.It shares no locks,resources or commit
dependencies with the main transaction.

ADVANTAGES:-
Unlike regular triggers autonomous triggers can contain
COMMIT and ROLLBACK.

LIMITATIONS:-
Changes made by a-t become visible to other transaction
when the a-t commits.The changes also become visible to
the main transaction when it resumes.If a-t attempts to
access a resource held by th main transaction(which can't
resume until the a-t routine exits),a deallock can occur.In
that case,Oracle raises an exception in the a-t,If the user
tries to exit an a-t without COMMIT OR ROLLBACK
,ORACLE RAISES AN EXCEPTION,in both the cases the
transaction is rolled back if the exception goes unhandled.

DHYNAMIC SQL :
Dynamic SQL :
Dynamic SQL is an advanced programming technique that
adds flexibility and functionality to your applications. It is
required when either table name or the query logic is not
known before. Dynamically a query string can be
constructed and run using either EXECUTE IMMEDIATE
or by using REF CURSORS. The following example shows
how to run a dynamic select query and output the result to a
variable.

A Simple Dynamic Query

There are different ways of writing Dynamic SQL. The


easiest approach is to use EXECUTE IMMEDIATE in
PL/SQL block.Using REF CURSORS is another method.

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

145
TABLE CREATION :

BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE
STUDENT(SNO NUMBER,SNAME VARCHAR2(20))';
END;

ALTERING TABLE:

BEGIN
EXECUTE IMMEDIATE 'ALTER TABLE STUDENT
ADD(MARKS NUBER)';
END;

TABLE TRUNCATE:
BEGIN
EXECUTE IMMEDIATE 'TRUNCATE TABLE
STUDENT';
END;

TABLE DROP:
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE STUDENT';
END;

declare
ename varchar2(100);
begin
execute immediate 'select ENAME from emp where
empno=7369' INTO ename;
end;

declare
ename varchar2(100);
begin

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

146
execute immediate 'select ENAME from emp where
DEPTNO=10' INTO ename;
exception
WHEN NO_DATA_FOUND then
DBMS_output.put_line('No Data Available');
WHEN TOO_MANY_ROWS then
DBMS_output.put_line('More than one row returned');
end;

Using Bind Variables

It is possible to construct a query using bind variables.


When you bind in a value, the SQL string itself does not
contain the value; it contains only the placeholder name.
Therefore, you can bind different values to the same SQL
statement without changing the statement. Since it's the
same statement, your application is more likely to be able to
take advantage of the pre-parsed cursors that are cached in
the System Global Area (SGA) of the database. The binding
can be done as follows

declare
ename varchar2(100);
v_empid number := 100;
begin
execute immediate 'select ENAME from emp where
empno=:empid' INTO ename USING v_empid;
exception
WHEN NO_DATA_FOUND then
DBMS_output.put_line('No Data Available');
WHEN TOO_MANY_ROWS then
DBMS_output.put_line('More than one row returned');
end;

Using Collections

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

147
If the query fetches more than one row, then the output
should be redirected to a collection.

declare
TYPE varchartab is TABLE OF varchar2(100);
enametab varchartab;
begin
execute immediate 'select ENAME from emp where
DEPTNO=10' BULK COLLECT INTO enametab;
exception
WHEN NO_DATA_FOUND then
DBMS_output.put_line('No Data Available');
WHEN TOO_MANY_ROWS then
DBMS_output.put_line('More than one row returned');
end;

BULK COLLECT with BULK BIND :

create or replace package rec_cur_pkg as


TYPE refcurtype is REF CURSOR;
end;

create or replace TYPE NUMTAB as TABLE OF number;

declare
TYPE varchartab is TABLE OF varchar2(100);
enametab varchartab;
empidtab NUMTAB := NUMTAB();
rc1 rec_cur_pkg.refcurtype;
begin
empidtab.extend; empidtab(1) := 100;
empidtab.extend; empidtab(1) := 101;
empidtab.extend; empidtab(1) := 102;
OPEN rc1 for 'select ENAME from emp where emp
IN(select * from TABLE(:id))' USING empidtab;
fetch rc1 BULK COLLECT INTO enametab ;

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

148
close rc1;
exception
WHEN NO_DATA_FOUND then
DBMS_output.put_line('No Data Available');
WHEN TOO_MANY_ROWS then
DBMS_output.put_line('More than one row returned');
end;

BULK UPDATE with EXCEPTION Handling

The following example demonstrates how to collect the


exceptions in a collection.

declare
i1 number;
errors number;
TYPE varchartab is TABLE OF varchar2(100);
enametab varchartab;
empidtab NUMTAB := NUMTAB();
rc1 rec_cur_pkg.refcurtype;
begin
empidtab.extend; empidtab(1) := 100;
empidtab.extend; empidtab(2) := 101;
empidtab.extend; empidtab(3) := 102;
OPEN rc1 for 'select empno from emp where empno
IN(select * from TABLE(:id))' USING empidtab;
fetch rc1 BULK COLLECT INTO enametab ;
close rc1;
dbms_output.put_line(enametab.count);
FORALL i1 IN 1..enametab.COUNT SAVE EXCEPTIONS
update emp set sal=sal*1.05 where emp=enametab(i1);
exception
WHEN OTHERS THEN
errors := SQL%BULK_EXCEPTIONS.COUNT;
dbms_output.put_line('Number of UPDATE statements
that failed: ' || errors);
FOR i1 IN 1 .. errors
LOOP

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

149
dbms_output.put_line('Error #' || i1 || ' at '|| 'iteration#' ||
SQL%BULK_EXCEPTIONS(i1).ERROR_INDEX);
dbms_output.put_line('Error message is ' || SQLERRM(-
SQL%BULK_EXCEPTIONS(i1).ERROR_CODE));
END LOOP;
end;

Using bulk collect with execute immediate in Oracle :

create or replace type varchar_number as object (


v varchar2(10),
i number
)

create or replace type t_varchar_number as table of


varchar_number

create table vn (
v varchar2(10),
i number
);

insert into vn values ('uno',1);


insert into vn values ('due',2);
insert into vn values ('tre',3);

commit;

create or replace function fct_t return t_varchar_number as


ret t_varchar_number;
begin
execute immediate 'select varchar_number(v,i) from vn'
bulk collect into ret;
return ret;
end;

declare
x t_varchar_number;

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

150
begin
x := fct_t;
for r in (select * from table(cast(x as t_varchar_number)))
loop
dbms_output.put_line(r.v || ', ' || r.i);
end loop;
end;

Global Temporary Tables :

Applications often use some form of temporary data store


for processes that are to complicated to complete in a single
pass. Often, these temporary stores are defined as database
tables or PL/SQL tables. In Oracle 8i, the maintenance and
management of temporary tables can be delegated to the
server by using Global Temporary Tables.The data in a
global temporary table is private, such that data inserted by
a session can only be accessed by that session. The session-
specific rows in a global temporary table can be preserved
for the whole session, or just for the current transaction. The
ON COMMIT DELETE ROWS clause indicates that the
data should be deleted at the end of the transaction. Global
temporary tables are types of database tables which can
privately store data, persistently for a session or transaction.
The data flushes out at defined instant automatically. They
often find their application in the situations where data fetch
and passage is not possible in single stretch.

Examples :

CREATE GLOBAL TEMPORARY TABLE my_temp_table


(
column1 NUMBER,
column2 NUMBER
) ON COMMIT DELETE ROWS;

In contrast, the ON COMMIT PRESERVE ROWS clause


indicates that rows should be preserved until the end of the
session.

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

151
CREATE GLOBAL TEMPORARY TABLE my_temp_table
(
column1 NUMBER,
column2 NUMBER
) ON COMMIT PRESERVE ROWS;

Advantages :

 If the TRUNCATE statement is issued against a


temporary table, only the session specific data is
trucated. There is no affect on the data of other
sessions.
 Data in temporary tables is stored in temp segments
in the temp tablespace.
 Data in temporary tables is automatically deleted at
the end of the database session, even if it ends
abnormally.
 Indexes can be created on temporary tables. The
content of the index and the scope of the index is
that same as the database session.
 Views can be created against temporary tables and
combinations of temporary and permanent tables.
 Temporary tables can have triggers associated with
them.
 Export and Import utilities can be used to transfer
the table definitions, but no data rows are processed.
 There are a number of restrictions related to
temporary tables but these are version specific.

Note that only table data is session specific, but physically


table is available in all sessions.

Syntax

1 CREATE GLOBAL TEMPORARY TABLE <Table-name>


2(
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

152
3 [COLUMN DEFINTION]
4 ) ON COMMIT [DELETE | PRESERVE] ROWS;

The default create statement is the equivalent of adding the


clause ON COMMIT DELETE ROWS. An alternative is to
specify ON COMMIT PRESERVE ROWS.

ON COMMIT DELETE ROWS sets the life of the data


contained by the table to a single TRANSACTION. The
data is automatically flushed away after each
COMMIT/ROLLBACK is executed. These are Transaction-
specific Temporary tables.
On the other hand, ON COMMIT PRESERVE ROWS
restricts the life of the data to a single SESSION. Data is
preserved in the table for a session only. These are Session-
specific Temporary tables.

SQL> CREATE GLOBAL TEMPORARY TABLE


worktable (x NUMBER(3));

Table created.

He opened another session and was pleased to see


the table there. He then added a row in the first
session, committed it, and was planning to use the
other session to see if the data was there. But instead
he was in for a little surprise.

SQL> INSERT INTO worktable (x) VALUES (1);

1 row created.

SQL> SELECT * FROM worktable;

X
----------
1
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

153
SQL> commit;

Commit complete.

SQL> SELECT * FROM worktable;

no rows selected

SQL> CREATE GLOBAL TEMPORARY TABLE


worktable
2 (x NUMBER(3))
3 ON COMMIT PRESERVE ROWS;

Table created.

SQL> INSERT INTO worktable (x) VALUES (1);

1 row created.

SQL> SELECT * FROM worktable;

X
----------
1

SQL> commit;

Commit complete.

SQL> SELECT * FROM worktable;

X
----------
1

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

154
"That's better," he smiled. Now let's check the other
session.
SQL> SELECT * FROM worktable;

no rows selected

SQL> INSERT INTO worktable (x) VALUES (2)

1 row created.

SQL> commit;

Commit complete.

SQL> SELECT * FROM worktable;

X
----------
2

SQL> TRUNCATE TABLE worktable;

Table truncated.

SQL> SELECT * FROM worktable;

no rows selected

SQL> commit;

Commit complete.

SQL> SELECT * FROM worktable;

X
----------
1

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

155
Important points about GTT

 In Oracle temporary table and global temporary


table are synonymous. You cannot create a temp
table without the keyword “global”
 GTT data is private to a session. Although there is a
single table definition, each session uses a GTT as if
it was privately owned. Truncating data in a GTT
will not affect other users sessions.
 Depending on the table definition, data in a GTT
will either be removed or retained after a commit.
However it is always removed when the session
terminates even if the session ends abnormally.
 Indexes can be created on temporary tables. The
content of the index and the scope of the index is
that same as the database session.
 The table and any associated indexes are stored in
the users temporary tablespace. Starting with 11g
Oracle introduced the option to specify the temp
tablespace for a GTT (but not its indexes).
 Views can be created against temporary tables and
combinations of temporary and permanent tables.
 Foreign key constraints are not applicable in case of
Temporary tables
 Temporary tables can have triggers associated with
them.
 Export and Import utilities can be used to transfer
the table definitions, but no data rows are processed.
 Putting data in a temporary table is more efficient
than placing this data in a permanent table. This is
primarily due to less redo activity when a session is
applying DML to temporary tables. DML statements
on temporary tables do not generate redo logs for the
data changes. However, undo logs for the data and
redo logs for the undo logs are generated. Oracle
writes data for temporary tables into temporary
segments and thus doesn’t require redo log entries.
Oracle writes rollback data for the temporary table
into the rollback segments (also known as the undo
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

156
log). Even though redo log generation for temporary
tables will be lower than permanent tables, it’s not
entirely eliminated because Oracle must log the
changes made to these rollback segments. To
summarize – “log generation should be
approximately half of the log generation (or less) for
permanent tables.”
 Temporary tables cannot be partitioned.

RESTRICT_REFERENCES Pragma :

This pragma was used to assert to the PL/SQL compiler the


purity level of a packaged procedure or function. The
RESTRICT_REFERENCES pragma had to be included in
the package specification if you were to use that program
inside a SQL statement (directly or indirectly).

This pragma confirms to Oracle database that the function


as the specified side-effects or ensures that it lacks any such
side-effects.

Usage is as follows:

PRAGMA RESTRICT_REFERENCES(function_name,
WNDS [, WNPS] [, RNDS], [, RNPS])

 WNDS: Writes No Database State. States that the


function will not perform any DMLs.

 WNPS: Writes No Package State. States that the


function will not modify any Package variables.

 RNDS: Reads No Database State. Analogous to


Write. This pragma affirms that the function will not
read any database tables.

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

157
 RNPS: Reads No Package State. Analogous to
Write. This pragma affirms that the function will not
read any package variables.

You can declare the pragma RESTRICT_REFERENCES


only in a package spec or object type spec. You can specify
up to four constraints (RNDS, RNPS, WNDS, WNPS) in
any order. To call the function from parallel queries, you
must specify all four constraints. No constraint implies
another. For example, WNPS does not imply RNPS.

When you specify TRUST, the function body is not checked


for violations of the constraints listed in the pragma. The
function is trusted not to violate them.

If you specify DEFAULT instead of a function name, the


pragma applies to all functions in the package spec or object
type spec (including, in the latter case, the system-defined
constructor). You can still declare the pragma for individual
functions. Such pragmas override the default pragma.

A RESTRICT_REFERENCES pragma can apply to only


one function declaration. So, a pragma that references the
name of overloaded functions always applies to the nearest
foregoing function declaration.

Syntax :

PRAGMA RESTRICT_REFERENCES (
function_name, WNDS [, WNPS] [, RNDS] [, RNPS]
[, TRUST] );

CREATE PACKAGE showrec AS


FUNCTION isok (amount NUMBER) RETURN
BOOLEAN;
FUNCTION isok (net_time DATE) RETURN
BOOLEAN;
PRAGMA RESTRICT_REFERENCES (isok, WNDS);

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

158
...
END showrec;

SERIALLY_REUSABLE:

This pragma lets the PL/SQL engine know that package-


level data should not persist between reference to that data.

Package data (global variables in package specification etc.)


by default persists for an entire session (or until a package is
recompiled). Globally accessible data structures can cause
some side effects. For instance, what if a cursor is left open
in a package. In addition, a program can use up lots of real
memory (UGA) and then not release it if the data is stored
in a package-level structure.

In order to manage this, Oracle8i introduced the


SERIALLY_REUSABLE pragma. This pragma is used in
packages only and must be defined BOTH in specification
and in the body. A bodiless package can be marked as
serially reusable. If a package has a spec and body, you
must mark both. You cannot mark only the body.

The global memory for serially reusable packages is pooled


in the System Global Area (SGA), not allocated to
individual users in the User Global Area (UGA). That way,
the package work area can be reused. When the call to the
server ends, the memory is returned to the pool. Each time
the package is reused, its public variables are initialized to
their default values or to NULL.

The advantage is that based on the pragma, a package state


can be reduced to a single call of a program unit in the
package as opposed to the package being available for the
whole session.

Note :---Serially reusable packages cannot be accessed from


database triggers.

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

159
SAMPLE CODE OF PRAGMA SERIALLY_REUSABLE;

CREATE PACKAGE pkg1 IS


PRAGMA SERIALLY_REUSABLE;
num NUMBER := 0;
PROCEDURE init_pkg_state(n NUMBER);
PROCEDURE print_pkg_state;
END pkg1;

CREATE PACKAGE BODY pkg1 IS


PRAGMA SERIALLY_REUSABLE;
PROCEDURE init_pkg_state (n NUMBER) IS
BEGIN
pkg1.num := n;
END;

PROCEDURE print_pkg_state IS
BEGIN
dbms_output.put_line('Number: ' || pkg1.num);
END;
END pkg1;

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

160
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

161
Step 5 – A procedure will take file_id and filename from user and transfer data of that file
into the table mytable.

CREATE OR REPLACE PROCEDURE insertclob (p_file_id number, filename


VARCHAR2)
AS
v_clob CLOB;
v_bfile BFILE;
BEGIN
INSERT INTO mytable VALUES (p_file_id,empty_clob());
COMMIT;
v_bfile:=BFILENAME('EXTERNAL_FILE11',filename);

select file_data INTO v_clob FROM mytable WHERE file_id=p_file_id FOR


UPDATE;
DBMS_LOB.FILEOPEN(v_bfile);
DBMS_LOB.LOADFROMFILE(v_clob,v_bfile,DBMS_LOB.GETLENGTH(v_bfile)
);
DBMS_LOB.FILECLOSE(v_bfile);
END;
/

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

162
Now execute the procedure by providing file id and file name

exec insertclob(1,'mytextfile.txt');

The data of mytextfle.txt has been transferred in the file_data column

(Note – In a session, the number of BFILEs that can be opened in one session is limited
by the parameter session_max_open_files and total number of files that can be open is
limited by the parameter max_open_files. These parameters are to be setted in the
init.ora file
session_max_open_files=10
max_open_files=20)

The DBMS_LOB.READ Procedure


REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

163
 Reads data from LOB starting at specified offset
DBMS_LOB.READ(loc, num, offset, buff)

Where
loc is locator of the LOB
num is number of bytes/characters to be read
offset is offset in bytes/characters from the start of the LOB
buff is output buffer for the read operation

Example – To retrieve a part of data from the first record’s file_data column

declare
v_clob clob;
num number;
offset number;
vstore varchar2(20);
begin
num := 7;
offset :=1;
select file_data into v_clob
from mytable
where file_id = 1;
DBMS_LOB.READ(v_clob,num,offset,vstore);
dbms_output.put_line(vstore);
end;
/

The DBMS_LOB.GETLENGTH Function


 Gets the length of the LOB value
DBMS_LOB.GETLENGTH(loc)

Where
loc is locator of the LOB

Example – To get the length of the file_data

declare
loc clob;
len number;
Begin
select file_data into loc from mytable
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

164
where file_id = 1;
len := DBMS_LOB.GETLENGTH(loc);
dbms_output.put_line(len);
end;
/

The DBMS_LOB.WRITE Procedure

 Writes data to the LOB from specified offset


DBMS_LOB.WRITE(loc, num, offset, buff)

Where
loc is locator of the LOB
num is number of bytes/characters to write
offset is offset in bytes/characters from the start of the LOB for write operation
buff is input buffer for the write operation

Example of Write and getLength function –


--DBMS_LOB.Write and getLength Functions
-- To add some text to CLob.
-- It is going to update the original clob
--Syntax DBMS_LOB.Write(Source, Length of new text, From which character or point
to be added, New Text)

Declare
loc clob;
num number;
offset number;
vstore varchar2(80);
lenlob number;
vlen number;
Begin
-- In the Select statement For Update clause is must, so that the row gets locked.
select file_data into loc from mytable where file_id=1 for update;
-- To get the total number of characters in a lob.
-- Use getlength function of DBMS_LOB
lenlob := DBMS_LOB.getLength(loc);
-- vstore is having the additional text
vstore := 'This is new line';

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

165
-- Now the length of the new text to be added should also be known since that value is
one
vlen := Length(vstore); -- Length of the new text in vstore variable
offset := lenlob + 1; -- Due to +1 in offset the text starts from --one space next
DBMS_LOB.Write(loc,vlen,offset,vstore);
end;
/

exec insertclob(2,'mytextfile.txt');

Example1of Erase method –

DBMS_LOB.Erase

Syntax - DBMS_LOB.Erase(Source, No. of characters to erase, Position from where it


has to erase)

To remove some text from clob column


Removing the first 5 characters of file_data column for file_id 2

Declare
loc clob;
num number;
offset number;
Begin
num := 5;
offset := 1;

select file_data into loc from mytable


where file_id = 1;

DBMS_LOB.Erase(loc,num,offset);
End;

REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in

166

You might also like