PLSQL
PLSQL
PLSQL
SQL PLSQL
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
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
4
a varchar2(10);
begin
z := &z;
a := '&a';
dbms_output.put_line('Z is '|| z);
dbms_output.put_line('A is '|| a);
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
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
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));
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;
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;
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;
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;
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
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.
WHILE-LOOP Statement
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;
declare
x number;
Begin
x := 1;
while x <=15
Loop
dbms_output.put_line(x);
x := x + 1;
End Loop;
end;
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;
/
Nested Loops
17
(quarter number(2),
month number(2),
discount varchar2(5));
Expected Output –
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;
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
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;
21
values(N,M.ename,M.sal);
End Loop;
Close cf;
End;
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;
----------------------------------------------------------------------
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;
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;
25
Loop
dbms_output.put_line(mrec.ename||' '||mrec.sal||' '||mrec.deptno);
End Loop;
End;
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
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;
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
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
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;
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;
31
Rollback;
dbms_output.put_line('Cannot update since there are more than 3 deptnos');
End If;
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.
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
End PRC;
Package Body –
33
Begin
Open vd FOR select * from dept;
End DeptDetails;
End PRC;
EXCEPTIONS
Introduction to Exceptions
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
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;
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;
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;
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
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.
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 */
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in
40
User-defined Exceptions
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;
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.
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.
Exception-handling part
The exception-handling part contains exception handlers, which deal with exceptions
raised during execution.
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.
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
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?
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.
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:
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
Formal parameter acts like a Formal parameter acts like a Formal parameter acts like
constant variable an initialized variable
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.
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
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
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.
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 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';
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.
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.
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.
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.
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;
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.
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:
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:
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;
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in
62
Figure 2. Function Creation screen shot
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.
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.
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.
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
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 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.
For a given package variables defined and which persist for term of session.
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.
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.
Always create and compile specifications of the Package and Package body separately.
Package syntax
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
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.
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];
/* 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
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in
72
END Procedure1;
/* 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.
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 /
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.
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.
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).
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:
3. You analyze the output, track down the problem, and fix it.
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:
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.
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...:
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.
82
maintenance of snapshots.
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.
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
Types
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.
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.
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.
Schema : The schema contains the package. If you omit schema, Oracle
assumes the package is in your own schema.
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
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.
88
Enforce referential integrity across nodes in a distributed database
Provide auditing
Modify table data when DML statements are issued against views
Publish information about database events, user events, and SQL statements to
subscribing applications
A trigger action
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:
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:
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:
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.
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 ...
91
o You cannot modify a relation connected to the triggering relation by
another constraint such as a foreign-key constrain
Insert Triggers
A BEFORE INSERT Trigger means that Oracle will fire this trigger before the INSERT
operation is executed.
Restrictions:
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.
93
-- trigger code
EXCEPTION
WHEN ...
-- exception handling
END;
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in
94
END;
Update Triggers
A BEFORE UPDATE Trigger means that Oracle will fire this trigger before the UPDATE
operation is executed.
95
[ FOR EACH ROW ]
DECLARE
-- variable declarations
BEGIN
-- trigger code
EXCEPTION
WHEN ...
-- exception handling
END;
Restrictions:
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.
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.
99
ON table_name
[FOR EACH ROW ]
DECLARE
-- variable declarations
BEGIN
-- trigger code
EXCEPTION
WHEN ...
-- exception handling
END;
Restrictions:
For example:
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.
Restrictions:
For example:
102
CREATE OR REPLACE TRIGGER orders_before_delete
BEFORE DELETE
ON orders
FOR EACH ROW
DECLARE
v_username varchar2 (10);
BEGIN
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.
104
ON table_name
[ FOR EACH ROW ]
DECLARE
-- variable declarations
BEGIN
-- trigger code
EXCEPTION
WHEN ...
-- exception handling
END;
Restrictions:
For example:
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
Mutating Error
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.
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.
1 row created.
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.
Table created.
Table created.
Table altered.
SQL> alter table am10_dtl add foreign key (col1) references am10(col1) on delete
cascade;
Table altered.
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.
1 row created.
1 row created.
1 row created.
1 row created.
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
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
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.
114
table-based,
cursor-based, and
programmer-defined
%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
Cursor-Based record has fields that match in name, datatype, and order to the final list of
columns in
the cursor’s SELECT statement.
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 ;
FROM Sells
WHERE bar = 'Joe''s bar';
Bp1 c%ROWTYPE;
Var_of_myfirstrecord my_first_record;
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;
Example for Table Based ,Cursor Based and User Defined Record:
DECLARE
CURSOR emp_cur
IS
SELECT empno
,ename
FROM emp
WHERE empno = '7369';
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
);
LOOP
FETCH emp_cur
INTO cur_rec;
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.
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 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;
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.
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in
123
Example 1:
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;
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.
Example 5:
---------
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> /
Code: sql
SQL> CREATE TYPE MEDICINE_ARR AS VARRAY(40) OF MEDICINES;
2> /
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)));
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.
COUNT :
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:
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 :
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 ;
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.
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 ;
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])] :
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)] :
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])] :
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;
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;
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in
135
Collection Exception Raised when...
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
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 ;
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?
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
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.
141
Create a table using the following script.
END autonomous_example;
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;
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;
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.
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;
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;
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;
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;
create table vn (
v varchar2(10),
i number
);
commit;
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;
Examples :
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 :
Syntax
152
3 [COLUMN DEFINTION]
4 ) ON COMMIT [DELETE | PRESERVE] ROWS;
Table created.
1 row created.
X
----------
1
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in
153
SQL> commit;
Commit complete.
no rows selected
Table created.
1 row created.
X
----------
1
SQL> commit;
Commit complete.
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
1 row created.
SQL> commit;
Commit complete.
X
----------
2
Table truncated.
no rows selected
SQL> commit;
Commit complete.
X
----------
1
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in
155
Important points about GTT
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 :
Usage is as follows:
PRAGMA RESTRICT_REFERENCES(function_name,
WNDS [, WNPS] [, RNDS], [, RNPS])
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.
Syntax :
PRAGMA RESTRICT_REFERENCES (
function_name, WNDS [, WNPS] [, RNDS] [, RNPS]
[, TRUST] );
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in
158
...
END showrec;
SERIALLY_REUSABLE:
REF: #202, 2nd Floor, Ramakrishna Nivas, Near Almas Restarant, SR Nagar, Hyderabad.
:8125552893, :hr.vngtech@live.in
159
SAMPLE CODE OF PRAGMA SERIALLY_REUSABLE;
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.
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');
(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)
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;
/
Where
loc is locator of the LOB
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;
/
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
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');
DBMS_LOB.Erase
Declare
loc clob;
num number;
offset number;
Begin
num := 5;
offset := 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