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

PLSQL

PL/SQL is an extension of SQL that combines procedural programming with SQL commands, allowing for data processing through control statements and robust error handling. A standard PL/SQL block consists of a declaration part, an executable part, and an exception handling part, with the ability to declare variables and use loops and conditional statements. The document also covers the use of cursors for data manipulation and retrieval, demonstrating various examples of PL/SQL programming techniques.

Uploaded by

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

PLSQL

PL/SQL is an extension of SQL that combines procedural programming with SQL commands, allowing for data processing through control statements and robust error handling. A standard PL/SQL block consists of a declaration part, an executable part, and an exception handling part, with the ability to declare variables and use loops and conditional statements. The document also covers the use of cursors for data manipulation and retrieval, demonstrating various examples of PL/SQL programming techniques.

Uploaded by

Ankit Shukla
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 52

PL/SQL features ---

u PL/SQL is an extension of SQL


u It is an application development language containing procedural statements and
commands along with SQL commands
u It bridges the gap between database technology and procedural programming
languages
u It allows you to process data using flow control statements like iterative loops and
conditional branching
u Uses procedural techniques of control, looping and branching
u Supports SQL i.e. cursor operations, exceptions, functions and transactional
commands
u Variables and constants, robust error handling and functions
u Adds functionality to non-procedural tools such as SQL*Forms
u Developers using SQL*Forms can enter an entire PL/SQL block using a single trigger

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

DECLARE

Declarations
BEGIN

Executable Statements
EXCEPTION

Exception Handlers
END;

Sections of a PL/SQL Block

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

Pl/SQL Files -à
Ø PL/SQL programs can be written in any editor and saved as files with .sql extension
Ø Can also use “ED” command in SQL*Plus to create a PL/SQL program file
Ø Use the “@ <filename>” command to execute a PL/SQL program file

o Variables --
Ø Used to store results of a query for later processing, or to calculate values to be
inserted into database tables
Ø Can be used anywhere in an expression, either in SQL or PL/SQL statements
Ø Must be declared before referencing it in other statements, including other
declarative statements
Ø Are declared by specifying the name along with the datatype
Ø Can be declared to be of any datatype native to Oracle
Ø Examples
oldfare NUMBER(5);
m_name VARCHAR(15);

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

Declaring and initialising variables together


declare
y number := 100;
begin
dbms_output.put_line('The value of y is '|| y);
end;
-------------------------------------------------------------------------------
Taking value from the user using &

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

/*Cannot declare or initialise more than one variable simulataneously*/


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

A constant number has to declared and initialised 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 cloumn of a table using select into


clause*/
declare
x number;
begin

Select sal Into x from emp


where ename = 'SMITH';
dbms_output.put_line('Salary of Smith is '|| x);
end;

/* 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 –
u Provides datatype of a variable or column
u Useful when declaring a variable that refers to a column in a database
– exact datatype of column need not be known
– if column definition changes, variable datatype changes accordingly
at runtime
u 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 –
u 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
u Fields in the record have same names and datatypes as the columns in the
table/view
u Example
emp_rec employee%ROWTYPE;
u 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 ename,sal,deptno INTO E.ename,E.sal,E.deptno
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
u The selection structure tests a condition, then executes one sequence of statements
instead of another, depending on the condition
u There are three forms of statements
– IF-THEN
– IF-THEN-ELSE
– IF-THEN-ELSIF
u Sequence of statements is executed only if the condition evaluates to TRUE
u If condition evaluates to FALSE or NULL, it does nothing
u In either case control passes to next statement after the IF-THEN structure
IF <condition> THEN
statements;
END IF;
u Sequence of statements in the ELSE clause is executed only if the condition
evaluates to FALSE or NULL
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

u This construct allows selection of action from several mutually exclusive alternatives
u The IF statement can have any number of ELSIF clauses
u The final ELSE is optional
u Conditions are evaluated one by one from top to bottom

Syntax
IF <condition1> THEN
statements;
ELSIF <condition2> THEN
statements;
ELSIF <condition3> THEN
statements;
ELSE
statements;
END IF;
Example 1 –
Declare
y number;
/*Multiple ifs */
Begin

y := &y;

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

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

/*Use of multiple if's


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

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

Begin
n := '&n';
m := &m;

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

if c is not null and f is not null then


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

end;

=========================================================
===========================================
LOOPS
u The ability to repeat or skip sections of a block can be achieved with the usage of
LOOP or GOTO statements
u There are three forms of the LOOP statement
– LOOP
– WHILE-LOOP
– FOR-LOOP
LOOP Statement
u LOOP repeats a sequence of statements
u Statements to be repeated are placed between keyword LOOP and END LOOP
u 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
u Used to complete a loop if further processing in a loop is undesirable or impossible
u There are two forms of the EXIT statement
– EXIT
– EXIT-WHEN
u Forces a loop to complete unconditionally
u 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 + 1;
exit when x > 10;
End Loop;
End;

create table five


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

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

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

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

Example 1 of for loop


/*To show 1 to 10 on screen*/

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

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

Begin
for i in REVERSE 1 ..10
Loop
dbms_output.put_line(i);
End Loop;
end;

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

WHILE-LOOP Statement

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


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

Example 1 of while loop to show 1 to 15

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

Example 2 Forces a loop to complete unconditionally


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

==============================CURSORS=================
=======================
Example 1
To transfer names and sal of employees from emp table where sal >= 3500 in
table try1
create table try1
(no number,
ename varchar2(50),
sal number);

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

Insert into try1


values(N,M.ename,M.sal);
End Loop;
Close cf;
End;
Example 2
Displaying the 3rd record entered in the table emp –

Declare
Cursor cf is
select *
from emp;
M cf%rowtype;
Begin
Open cf;
Loop
fetch cf into M;
if cf%rowcount = 3 then

dbms_output.put_line(M.empno||'-'||M.ename||'-'||M.sal||'-'||M.deptno);
end if;
exit when cf%notfound;
End Loop;
End;

Example 3

Use of %FOUND attribute

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

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

M cf%rowtype;

N number;

J Emp.Job%type;

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

If cf%found then
N := N + 1;
End if;
End Loop;
Close cf;
If N > 0 then
dbms_output.put_line('Total number of job ' || J || ' is '|| N);
else
dbms_output.put_line('No such job');
End If;
End;

Example 4

Use of IsOpen attribute


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

Example 5) To see the first person( or first record entered) who has got salary
> 2800
Declare
Cursor cf is
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);
end if;
exit when cf%notfound;
End Loop;
End;
Cursor FOR Loop
u Implicitly declares its loop index as a record of %ROWTYPE,
u Implicitly opens the cursor
u Repeatedly fetches rows of values from the active set into fields in the record
u Implicitly closes the cursor when all rows have been processed or the loop is exited
u The statements in the loop construct are executed once for each row that satisfies
the query associated with the cursor name
u Cursor FOR loop is used to simplify coding
u No need of --
1)Open cursor
2)Fetch
3)Exit
4)Close cursor

Example -- To show records where salary is > 3000


Declare
Cursor cf is
select *
from emp
where sal >= 3000;
Begin
For mrec in cf
Loop
dbms_output.put_line(mrec.ename||' '||mrec.sal||'
'||mrec.deptno);
End Loop;
End;

Cursor FOR Loops Using Subqueries Cursor FOR Loops Using Subqueries

No need to declare the cursor.

begin
For cf in (Select empno,ename,sal from emp)
Loop
dbms_output.put_line(cf.empno || '-' || cf.ename || '-' ||cf.sal);
End Loop;
end;
Implicit Cursors
• Automatically defined and opened, by Oracle, to process each SQL
statement
• most recently opened context area is referred to as a ‘SQL%’ cursor

Attributes of Implicit Cursors

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

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

9) Example of Implicit Cursors


Begin
Delete from emp
where ename = '&name';

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

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

End;

Implicit Cursor for rowcount


Begin
Update Emp
set sal = sal + 500
where deptno = &deptno;

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

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


If SQL%RowCount > 3 then
Rollback;
dbms_output.put_line('Cannot update since there are more than 3 deptnos');
End If;

If SQL%RowCount Between 1 and 3 then


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

Cursor FOR UPDATE OF and CURRENT OF


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

Example of Cursor FOR UPDATE OF and CURRENT OF

create table esal


(empno number,
sal number);

insert into esal


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

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

Declare
Cursor cf is
select * from esal
For Update of sal;

M cf%rowtype;

Begin
Open cf;

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

If M.Sal >= 16000 Then


M.Sal := 20000;

ElsIf M.Sal >= 14000 Then


M.Sal := 18200;

ElsIf M.Sal >= 12000 Then


M.Sal := 16700;

ElsIf M.Sal >= 10000 Then


M.Sal := 13500;

ElsIf M.Sal >= 8000 Then


M.Sal := 11000;

ElsIf M.Sal >= 6000 Then


M.Sal := 9500;

ElsIf M.Sal >= 4000 Then


M.Sal := 7500;

Else
M.Sal := 5000;

End If;

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

1) Pass parameter values to a cursor when the cursor


is opened and the query is executed.

2) Open an explicit cursor several times with a


different active set each time.

OPEN cursor_name(parameter_value,.....) ;

Example of Parameterised Cursor


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;
close cf;
open cf('CLERK');
LOOP
FETCH CF INTO M;
EXIT WHEN CF%NOTFOUND;
dbms_output.put_line(M.ename);
end loop;
close cf;
END;

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

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

Features of REF CURSOR --


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

Advantage of REF CURSOR--


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

Package Specification –

create or replace package PRC as

TYPE EmpRC IS REF CURSOR RETURN emp%rowtype;


TYPE DeptRC IS REF CURSOR RETURN dept%rowtype;

Procedure EmpDetails(ve IN OUT EmpRC);


Procedure DeptDetails(vd IN OUT DeptRC);

End PRC;
Package Body –

create or replace package Body PRC as

Procedure EmpDetails(ve IN OUT EmpRC)


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

Procedure DeptDetails(vd IN OUT DeptRC)


is
Begin
Open vd FOR select * from dept;

End DeptDetails;

End PRC;

For executing the procdure –


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

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


SQL > Set AutoPrint ON

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


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

Introduction to Exceptions

u An error condition is called an Exception


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

u There are two types of exceptions


– Pre-defined exceptions (Internal Exceptions)
– User-defined exceptions
u You cannot declare an exception twice in the same block, but can declare the same
exception in two different blocks
u Exceptions declared in a block are local to that block and global to all its sub-blocks
u Enclosing blocks cannot reference exceptions declared in a sub-block because blocks
can only reference local or global exceptions
Predefined Exceptions
u Are implicitly raised whenever a PL/SQL block violates an Oracle rule or exceeds a
system-dependent limit
u Every Oracle error has a number, but exceptions must be handled by name
u PL/SQL predefines some common Oracle errors as exceptions
u These predefined exceptions are declared globally by PL/SQL
u Some Pre-defined Exceptions
u CURSOR_ALREADY_OPEN
u NO_DATA_FOUND
u TOO_MANY_ROWS
u VALUE_ERROR
u ZERO_DIVIDE

u More than one exception can be handled in a single exception handler by separating
them with the keyword OR
EXCEPTION
WHEN NO_DATA_FOUND OR TOO_MANY_ROWS THEN
statements;
WHEN OTHERS THEN
statements;
END;

Examples of Exception handling –


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

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

Exception
When NO_DATA_FOUND then
dbms_output.put_line('No record');
end;
User-defined Exceptions

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


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

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


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

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


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

u An exception raised inside a handler immediately propagates to the enclosing block,


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

Example of Exception variable using Raise key word


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

Begin
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 meaasge,which can be more
descriptive than named exceptions.

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

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

if maths < 35 then


raise_application_error(-20001,'Failed');
else
dbms_output.put_line('Passed');
end if;
end;
---------------------------------------------------------------------------------------------------
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;
SQLCODE and SQLERRM

SQLCODE: Returns the numeric value for the error code

SQLERRM: Returns the message associated with the error number

Example –

Create table errorlog


(Error_Number number,
error_Text varchar2(100);

--------------------------------------------------------

Declare
verr number;
vmsg varchar2(100);
vsal emp.sal%type;
Begin
select sal into vsal
from emp;
Exception
When Others Then
verr := SQLCODE;
vmsg := SQLERRM;
Insert into errorlog
Values(verr, vmsg);
End;
=========================================================
===========================================
Advantages of Subprograms
u Provide Extensibility
– PL/SQL language can be tailored to suit the needs of the application
u Promote reusability and maintainability
– Once validated, they can be used with confidence in any number of
applications
– Simplifies maintenance/enhancement, as subprogram is only affected if
definition changes
u Provide Modularity
– Program can be broken down into manageable, well-defined logical modules
– Supports top-down design and stepwise refinement approach to problem
solving
u Aid in abstraction
– Allow mental separation from particulars
– Stubs allow programmers to defer definition of procedures/functions until
main program is tested and debugged

Procedures

u Subprogram that performs specific action


u Stored in database and can be invoked or called by any anonymous block
u Can take parameters
u Datatype specifier in parameter declaration must be unconstrained

u Has two parts


– Specification
• begins with keyword PROCEDURE, ends with procedure name or
parameter list
– Body
• begins with keyword IS, ends with keyword END followed by optional
procedure name

CREATE [OR REPLACE] PROCEDURE <procedurename> [(parameter1, … parameterN)] IS


[local declarations]
BEGIN
executable statements;
[EXCEPTION
exception handlers]
END [<procedurename>];

parameter stands for


variablename [IN|OUT|IN OUT] datatype [{:= | DEFAULT} value]
u When a procedure is created, Oracle automatically performs these steps
– Compiles the procedure
– Stores the compiled code
– Stores the procedure in the database
u The PL/SQL compiler used to compile the code
u If an error occurs, the procedure is created but it is invalid

u Enforce Data Security


– Can grant users access to a procedure that queries a table, but not
grant access to the table itself
u Improve Database Performance
– Less amount of information sent over network
– Compilation not required to execute code
– Procedure present in shared pool so retrieval from disk not required
u Memory Savings
– Only one copy of procedure needs to be loaded in memory for
execution by multiple users
u Increase in Development Productivity
– Can avoid redundant coding and increase productivity, by writing a
single procedure
u Integrity
– Procedures need to be tested only once, to guarantee that it returns
accurate results

Calling a Stored Procedure

u Can call a procedure in a PL/SQL statement


– Example
branch_sum(‘NYK’);
u Can call a procedure from SQL*Plus
– Example
SQL> EXECUTE branch_sum(‘NYK’);
Parameter Modes for Procedures and Functions
u Used to define the behavior of formal parameters
u Can be used with any subprogram
u Three parameter modes
– IN (Default)
– OUT
– IN OUT
u IN
– allows values to be passed to the subprogram being called
– inside the subprogram it acts like a constant
– actual corresponding parameter can be a constant, literal, initialized variable
or expression
– can be initialized to default values

3) Giving default values to the parameters


Due to default value given the parameter becomes optional also.
But if any other value is given then it takes it.

create or replace procedure pr3 (Eno emp.empno%type,N emp.ename%type, S


emp.sal%type,dno emp.deptno%type DEFAULT 10)
is
Begin
Insert into emp (empno,ename,sal,deptno)
values(Eno,N,S,dno);
dbms_output.put_line('Record inserted');
End;

-- While executing
--exec (1,'o',800) -----> (No deptno parameter given!!!)

OUT parameter
– allows values to be returned to the caller of a subprogram
– inside the subprogram it acts like an uninitialized variable
– actual corresponding parameter must be a variable; it cannot be a
constant or expression
– its value cannot be assigned to another variable or reassigned to
itself

4) create or replace procedure pr5(Name IN varchar2, Salary OUT number)


Is
Begin
Select sal into Salary
from emp
where ename = Name;
End;
--Steps for displaying the OUT parameter
--1) Compiling the procedure.
--2) Declare the bind variable on SQL prompt as variable payment number
-- Bind variables are of SQL* plus environment which are used to hold the return
--value given by the procedure or function.
--3)Now execute the proc -- exec pr5('SMITH', :payment)
--4)To display the value of payment -- print payment
--5)Bind variables are session specific.Their existence is removed as the session --ends.

IN OUT parameter
– allows initial values to be passed and returns updated values to the
caller
– inside the subprogram it acts like an initialized variable
– actual corresponding parameter must be a variable; it cannot be a
constant or expression
– can be assigned a value and its value can be assigned to another
variable

5) create or replace procedure pr6(x IN OUT number)


Is
Begin

x := (x * x);

End;

Without AUTHID Current User


Step 1 (Log on as Train1)

create or replace procedure trial1(eno in emp.empno%type, es out emp.sal%type)


is
begin
select sal into es
from emp
where empno = eno;
end;

Step 2 (Log on as System)

CREATE USER GREEN1


IDENTIFIED BY GREEN1;

grant create session to green1;

Step 3 (Log on Train1)


grant execute on trial1 to green1;

Step 4 (Log on as Green1)

variable ss number
exec scott.trial1(7499,:ss);
With AUTHID Current User

Step 1 (Log on as Train1)

create or replace procedure trial2(eno in emp.empno%type, es out emp.sal%type)


AUTHID CURRENT_USER
is
begin
select sal into es
from emp
where empno = eno;
end;

Step 2 (Log on as System)

CREATE USER GREEN2


IDENTIFIED BY GREEN2;

grant create session to green2;

Step 3 (Log on as Train1)

grant execute on trial2 to green2;

Step 4 (Log on Green2)

variable ss number

exec scott.trial2(7499,:ss);

=====================================================
==============================

Functions
u Subprogram that returns a value
u Have a RETURN clause
u Stored in database and can be invoked or called by any anonymous block
u Generally take parameters
u Datatype specifier in parameter declaration must be unconstrained
u Has two parts
u Specification
u begins with keyword FUNCTION, ends with RETURN clause
u Body
u begins with keyword IS, ends with keyword END followed by optional
function name

Syntax –

CREATE [OR REPLACE] FUNCTION <functionname> [(argument1, … argumentN)] RETURN


datatype IS
[local declarations]
BEGIN
executable statements;
[EXCEPTION
exception handlers]
END [<functionname>];

argument stands for


variablename [IN|OUT|IN OUT] datatype [{:= | DEFAULT} value]

Format –

CREATE FUNCTION day_fn(mday NUMBER) RETURN CHAR IS


disp_day CHAR(15);
BEGIN
executable statements;
RETURN disp_day;
EXCEPTION
statements;
END day_fn;

Calling a Function

u Can call a function as a PL/SQL statement


– Example
chardays := day_fn(3);

u Can call a function as part of an expression


– Example
IF day_fn(3) = ‘TUESDAY’ THEN
statements;
END IF;

The RETURN Statement

u Immediately completes execution of subprogram and returns control to caller


u In procedures
– cannot contain an expression
– returns control to the caller before normal end of procedure is reached
u In functions
– must contain an expression, evaluated when it is executed

Examples of Functions –
1)
a)
create or replace function eo ( n number)
RETURN char is
disp char(30);
Begin
If Mod(n,2) = 0 Then
disp := 'Number is even';
else
disp := 'Number is odd';
End If;
dbms_output.put_line(disp);

RETURN disp;

End;

TRIGGERS
u It is a stored PL/SQL program unit associated with a specific database table
u Oracle executes (fires) the trigger automatically whenever a given SQL operation
affects the table
u They are invoked implicitly
u They are useful for customizing a database
u They should be used only when necessary
u Can automatically generate derived column values
u Can prevent invalid transactions
u Can enforce complex security authorizations
u Can enforce referential integrity across nodes in a distributed database
u Can enforce complex business rules
u Can provide transparent event logging
u Can provide sophisticated auditing
u Can maintain synchronous table replicates
u Can gather statistics on table access
u Can derive column values automatically
u Can restrict DML operations to regular business hours

Syntax --
CREATE [OR REPLACE] TRIGGER <triggername>
BEFORE|AFTER
INSERT|DELETE|UPDATE OF <columnnames> ON <tablename>
[FOR EACH ROW]
WHEN (<condition>)
<PL/SQL Block>

u Name in the ON clause identifies the database table associated with the trigger
u The trigger event specifies the SQL DML statement (INSERT, DELETE or UPDATE)
that affects the table
u AFTER specifies that the trigger fires after the manipulation is done
u BEFORE specifies that the trigger fires before the manipulation is done
u By default, a trigger fires once per table
u FOR EACH ROW specifies that the trigger fires once per row
u For the trigger to fire, the boolean expression in the WHEN clause must evaluate to
TRUE
u REPLACE can be added to the CREATE statement to drop and re-create the trigger
automatically
CREATE TRIGGER flight_update
AFTER INSERT ON reservation
FOR EACH ROW
BEGIN
IF :new.class = ‘F’ THEN
statements;
ELSIF :new.class = ‘B’ THEN
statements;
END IF;
END;

u Prefix :new is a correlation name that refers to the newly updated column value
u Within a trigger, the :new and :old values of changing rows can be referenced
u A single trigger can handle more than one operation
u Use conditional predicates to identify the type of statement used to invoke the
section of code
Instead Of Triggers

u Provides a transparent way of modifying views that cannot be modified directly


through INSERT, UPDATE or DELETE statements because underlying tables contain
joins
u It is called INSTEAD OF because Oracle fires the trigger instead of the triggering
statement(s)
u Users can be transparent to the trigger because they write normal DML statements
against the view and the INSTEAD OF trigger is used to take care of the
modifications
u It can be placed on Object Views to insert, update or delete data in the underlying
relational tables
CREATE TRIGGER emp_insert
INSTEAD OF INSERT ON emp_view
BEGIN
statements;
END;

1) Example on Instead of Update on View -

--Instead of triggers can be used only with views.


--Effective for joins which are based on equi join
-- To have an cascading effect of update on both the tables if columns are
--matching
--Also to update uncommon columns through equi join views
--Step 1 Creating tables s and r;
create table s
(rollno number,
name varchar2(20));
create table r
(rollno number,
marks number);

--Step 2 Inserting records in s and r.


insert into s
values(1,'a');
insert into s
values(2,'b');

insert into r
values(1,90);
insert into r
values(2,87);

--Step 3 Creating an Equijoin View on s and r

Create or replace view SR


as
select s.rollno,s.name,r.marks
from s,r
where s.rollno =r.rollno;
--Step 4 Now creating the Instead of Trigger for update on the view SR

Create or replace trigger tig12


Instead Of UPDATE on SR
For Each Row
Begin
/* Updating roll numbers from both the tables s and r */
Update s
set rollno = :new.rollno
where rollno = :old.rollno;
Update r
set rollno = :new.rollno
where rollno = :old.rollno;

/* Updating name column of s table through view.*/


Update s
set name = :new.name
where name = :old.name;

/*Updating marks column of r table through view.*/


Update r
set marks = :new.marks
where marks = :old.marks;
End;
--

Packages
u Database objects that group logically related PL/SQL types, objects and
subprograms
u They cannot be called, passed parameters to or nested
u There are two parts
– Specification
– Body

Advantages of Packages
u Modularity
– allows encapsulation of related types, objects and subprograms in a named
PL/SQL module
– easy to understand with simple, clear and well defined interfaces
– helps in application development
u Easier Application Design
– when designing applications, only interface information in package
specifications initially required
– can code and compile specification without body
– stored subprograms referencing the package can be compiled as well
– need not define package bodies until ready to complete the application
u Information Hiding
– can specify which types, items, and subprograms are public or private
– definition of private subprograms is hidden so that only the package (not the
application) is affected if the definition changes
– simplifies maintenance and enhancement and protects integrity of the
package
u Better performance
– when a packaged subprogram is called for the first time, the whole package is
loaded into memory
– later calls to related subprograms in the package require no disk I/O
Package Specification
u Is an interface to the applications
u Declares the types, variables, constants, exceptions, cursors and subprograms
available for use
u Holds public declarations, visible to the application
u Can be thought of as an operational interface
u Scope of the declarations are local to the database schema and global to the package
u Lists the package resources available to applications
u Created using CREATE PACKAGE command

Syntax for Package Specification –

CREATE [OR REPLACE] PACKAGE <packagename> AS


Global variables declaration;
Procedure specifications;
Function specifications;
Type Definitions;
Cursor Declarations
END [<packagename>];

Package Body

u Implements the package specification


u Fully defines cursors and subprograms
u Holds implementation details and private declarations, hidden from the application
u Can be thought of as a ‘black body’
u Can be replaced, enhanced or replaced without changing the interface
u Can be changed without recompiling calling programs
u Scope of the declarations are local to the package body
u Declared types and objects are inaccessible except from within the package body
u Initialization part of a package is run only once, the first time the package is
referenced

Syntax for Package Body –

CREATE [OR REPLACE] PACKAGE BODY <packagename> AS


Procedure Code;
Function Code;
Implementation of Types;
Use of Cursors;
Using Global variables in the members of the package.
END [<packagename>];

Referencing Package Objects

u Packaged objects and subprograms must be referenced using the dot notation
packagename.typename
packagename.objectname
packagename.subprogramname

E.g - DBMS_OUTPUT.PUT_LINE

Maintaining a Package

u Can drop a package using the DROP command


DROP PACKAGE <packagename>
u Example
DROP PACKAGE airlines;
u To drop just one construct, remove it from the package and then recompile the
package

Examples of Packages –

1) Creating a package of 3 procedures –

Package Specification –
create or replace package pk1 is
procedure x(a number);
procedure y(b number);
procedure z(c number);
end;

Package Body –
create or replace package body pk1
is
procedure x(a number)
is
Begin
dbms_output.put_line('Procedure p1');
End x;
procedure y(b number)
is
Begin
dbms_output.put_line('Procedure p2');
End y;
/*Suppose in the package body if all the procedures are not written then it will
give error.*/
procedure z(c number)
is
Begin
dbms_output.put_line('Procedure p3');
End z;

End pk1;
-------------------------------
Using the Package pk1—
SQL > Execute PK1.X(4);
2) Use of global variable in a function and procedure –

Package Specification –

create or replace package pk2


as
g number;
function m(a number) return number;
procedure n;
end pk2;

Package Body –

create or replace package body pk2


as
function m(a number) return number
is
Begin
g := a;
return g;
End m;

procedure n
is
Begin
if g >= 100 then
dbms_output.put_line('Discount is 20%');
else
dbms_output.put_line('Discount is 10%');
end if;
end n;
End pk2;

Using the package in a PL/SQL block –

Declare
x number;
Begin
x := pk2.m(700);
pk2.n;
End;

3)
Use of Type in a Procedure –

Package Specification –

create or replace package pk3 as


Type t1 is RECORD
(e1 Emp.Empno %Type,
e2 Emp.Ename%Type,
e3 Emp.Sal%Type);
Procedure p1;
end pk3;

Package Body –

create or replace package body pk3 as


procedure p1
is
v t1; /*Using the type of the package directly inside the procedure.*/
Begin
select empno,ename,sal into v
from emp
where ename = 'SMITH';
dbms_output.put_line(v.e1 || '-' || v.e2 || '-' || v.e3);
End;
End pk3;

4) Use of Cursor in Procedure –

Package Specification –

create or replace package pk4


as
cursor cf is select * from emp
where job = 'MANAGER';
m cf%rowtype;
procedure CP;
End pk4;
Package Body –

create or replace package body pk4 as


procedure CP
is
Begin
Open cf;
Loop
fetch cf into m;

/*Showing the first entry of manager*/


if cf%rowcount = 1 then
dbms_output.put_line(m.empno || '-' || m.ename || '-'
|| m.sal);
else
exit;
end if;
End Loop;
Close cf;
End CP;
End pk4;
Overloading
a)
create or replace package pk1
is
procedure p(a number,b number);
procedure p(x varchar2,y varchar2);
procedure p(z number);
procedure p;
end pk1;

b)
create or replace package body pk1
is
procedure p(a number, b number)
is
c number;
begin
c := a + b;
dbms_output.put_line(c);
end p;

procedure p(x varchar2, y varchar2)


is
begin
dbms_output.put_line(x ||y);
end p;
procedure p(z number)
is

begin
if z > 0 then
dbms_output.put_line('The number is positive');
else
dbms_output.put_line('The number is negative');
end if;
end p;

procedure p
is
begin
dbms_output.put_line('No parameter is passed');
end p;
end pk1;

Private Members

create or replace package prvconstructs


is
procedure pubproc;
end;
create or replace package body prvconstructs
is
/*Creating Private Procedure in the body*/
procedure priv
is
begin
dbms_output.put_line('This is the private member of the package body');
end priv;

procedure pubproc
is begin
priv;
end;

end;

Collections
u Collections are similar to arrays available in most 3GLs
u A collection is an object that contains other objects of similar type
u It is an ordered group of elements of the same type
u Each element is identified by a unique subscript that determines its position in the
collection

Step 1 – Creating the collection type.


CREATE TYPE Color_tab_t AS TABLE OF VARCHAR2(30);

Step 2 -
Type of a TABLE used as a data type of a column. This column is having nested
table.

CREATE TABLE cars(


name VARCHAR2(12),
colors Color_tab_t)
NESTED TABLE colors STORE AS color_model_colors_tab;

Colors is the column having Color_tab_t type. The colors column is having the nested table.

Step3 – Inserting records….

insert into cars


values ('Maruti', Color_tab_t('RED','GREEN','BLUE'));

insert into cars


values ('Indica',Color_tab_t('CYAN','YELLOW','MAGENTA','BLACK'));

Step 4 --
To retrieve color names through a PL/SQL block create a variable of Color_tab_t
type. Then fetch the nested table column into that variable for that row. Then
through loop show each color with the help of the variable.
To see all the colors available to Maruti car --
DECLARE
colorlist Color_tab_t;
BEGIN
SELECT colors INTO colorlist FROM cars
WHERE name = 'Maruti';
FOR i IN 1..colorlist.COUNT
LOOP
dbms_output.put_line( colorlist(i) );
END LOOP;
END;

VARRAY

u Also known as varying arrays


u It is an aggregation of values stored in a single column
u A single column in the database would point to a group of elements
u Can associate a single identifier with an entire collection
u Can reference the entire collection as a whole or access the elements individually
u To access individual elements, use standard subscripting syntax i.e.
array_name(subscript)
u Maximum size must be specified at time of definition
u Index has a fixed lower bound of 1 and an extensible upper bound

Steps for Creating VARRAYs


u Create a type which will hold information for a single line item
u Create an array of type known as Varray type, holding multiple values of a particular
type
u Create a table having one of the columns, known as varray column, based on the
Varray type

The SYNTAX for creating a VARRAY

CREATE TYPE <varray_type_name>


AS VARRAY(limit) OF <type>;

Example – In a factory table there are workers using different tools. Each worker is using
say 3 numbers of tools. Thus if a single worker is taking 3 tools then that worker’s name will
come thrice in the table. So there will be data redundancy. Varrays will repeat values that
change for a particular column which will save the storage space.

A set of rows is repeated in one column in varray.

Step 1— Create the type


create type tool_ty
as object
(toolname varchar2(25))

Step 2 – Now creating array of this type to hold multiple (3) values
create type tool_va as
Varray(3) of tool_ty
Step 3 - Finally create a table having one of the column as the varray
column based on the varray type.

create table factory


(name varchar2(20),
tools tool_va)

The SYNTAX for inserting records in a table having a column of a VARRAY

INSERT INTO <table_name> VALUES


(column_values, <varray_type_name> (<type_name>(attribute1_value,...),
<typename>(attribute2_value,...)));

insert into factory


values ('John', Tool_va(
Tool_ty('Hammer'),
Tool_ty('Drill'),
Tool_ty('Shaft')
)
);
insert into factory
values ('Smith', Tool_va(
Tool_ty('Hammer'),
Tool_ty('Keys'),
Tool_ty('Sledge')
)
);
insert into factory
values ('Roger', Tool_va(
Tool_ty('Vc'),
Tool_ty('Bolts'),
Tool_ty('Shaft')
)
);

Updating VARRAYs
u Individual elements cannot be updated
u Entire VARRAY has to be updated if one of the elements has to be changed
SYNTAX
UPDATE <table_name>
SET <varray_column> = <varray_type_name>
(<typename>(attribute1_value,...),
<typename>(attribute2_value,...))
WHERE <condition>;

To change the name of the tool of John from Drill to Drill-2.5mm


update factory
set tools = Tool_va
(tool_ty('Hammer'), tool_ty('Drill-2.5mm'), tool_ty('Shaft'))
where name = 'John';
Displaying data from the varray column –
declare
cursor cf is
select * from factory;
vcf cf%rowtype;
begin
for vcf in cf
loop
/*This loop is for the normal column name.*/
dbms_output.put_line('Contact Name '|| vcf.name);
for i in 1..vcf.tools.count
loop
/*This loop is for the number of tools for the
current row's name*/
dbms_output.put_line(vcf.tools(i).toolname);
end loop;
dbms_output.put_line('----------------------------------');
end loop;
end;
------------------------------------------------------------------------------------------------------
Dynamic SQL:
• Is a SQL statement that contains variables that can
change during runtime
• Is a SQL statement with placeholders and is stored
as a character string
• Enables general-purpose code to be written
• Enables data-definition, data-control, or sessioncontrol
statements to be written and executed
from PL/SQL
• Is written using either DBMS_SQL or native dynamic
SQL

Example of dropping a table –

CREATE OR REPLACE PROCEDURE drop_table


(p_tab_name IN VARCHAR2, vexec OUT NUMBER)
IS
cursor_name INTEGER;
BEGIN
cursor_name := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(cursor_name, 'DROP TABLE '||p_tab_name,
DBMS_SQL.NATIVE );
vexec := DBMS_SQL.EXECUTE (cursor_name);
DBMS_SQL.CLOSE_CURSOR(cursor_name);
END;

PL/SQL Records

u Objects of type RECORD are called PL/SQL records


u PL/SQL records have uniquely named fields, which can belong to different datatypes
u Define a RECORD type
TYPE <typename> IS RECORD
(fieldname1 <fieldtype>
:
fieldnameN <fieldtype> ;
(%TYPE and %ROWTYPE can be used to specify <fieldtype>]

Example 1 of Record Type –

Declare
TYPE empdetails IS RECORD
(eno Emp.Empno%type,
name Emp.Ename%type,
s Emp.Sal%type);
VE empdetails;
Begin

Select empno,ename,sal Into VE


from Emp
where ename = 'SMITH';

dbms_output.put_line(VE.eno || ' - ' || VE.name || '-' ||VE.s);


End;

Example 2 of Record Type –

Declare
TYPE si IS RECORD
(p number,
n number,
r number := 4.5);
/* r variable of si type has been given value. */
VSI si;
x number;
Begin
VSI.p := 5000;
VSI.n := 6;
x := (VSI.p * VSI.n * VSI.r) / 100;
dbms_output.put_line(x);
End;
PL/SQL Tables

Features of PL/SQL tables are as follows –


1) It is a composite data type.
2) They are modeled as similar to database tables, but they are not permanent tables.
So they can be created and manipulated only in a PL SQL block.
3) They can have only one column but any data type
4) It will have a primary key which is compulsory for the reference of values
5) There is no name to the column and primary key
6) The data type of the primary key is BINARY_INTEGER.
BINARY_INTEGER is a special data type which can be given only to the column of
PL/SQL table for it’s indexing purpose to store and retrieve values.
7) Size is unconstrained (Table size grows as the rows are added to the table).
8) Can visualize a Pl/SQL table as a single dimensional vertical array, which can
hold unlimited elements.
9) Suitable for storing and displaying the values of one column of a table given
by a cursor.

Example 1 –

SET SERVEROUTPUT ON

DECLARE
TYPE emp_table_type is table of
employees%ROWTYPE INDEX BY BINARY_INTEGER;
my_emp_table emp_table_type;
v_count NUMBER(3):= 104;
BEGIN
FOR i IN 100..v_count
LOOP
SELECT * INTO my_emp_table(i) FROM employees
WHERE employee_id = i;
END LOOP;
FOR i IN my_emp_table.FIRST..my_emp_table.LAST
LOOP
DBMS_OUTPUT.PUT_LINE(my_emp_table(i).last_name);
END LOOP;
END;

Example 2

declare
Type discount is TABLE OF number
INDEX By Binary_Integer;
d discount;
Begin
d(5) := 90;
d(2) := 50;
d(8) := 70;
d(11) := 67;
d(14) := 68;
d(1) := 1;
d(23) := 5;
d(23) := 51;
dbms_output.put_line('The value at 23 index number is ' || d(23));
/*dbms_output.put_line('The value at index number 6 is ' || d(6));
dbms_output.put_line('The value at index number 2 is ' || d(2));

if d.EXISTS(6) Then
dbms_output.put_line(d(6));
else
dbms_output.put_line('There is no element in the sixth row');
end if;

dbms_output.put_line('The total number of elements in d are '|| d.count);

dbms_output.put_line('The first index number is ' || d.FIRST);


dbms_output.put_line('The last index number is ' || d.LAST);

dbms_output.put_line('The index number after 2 is ' || d.next(2));


dbms_output.put_line('The index number before 8 is ' || d.prior(8));

d.delete(5);
dbms_output.put_line('The total number of elements in d are '|| d.count);
d.delete(11,14);
dbms_output.put_line('The total number of elements in d are '|| d.count);
d.delete;
dbms_output.put_line('The total number of elements in d are '|| d.count); */

end;

Dynamic SQL:
Dynamic SQL statements are stored in character strings built by your program at run time.
Such strings must contain the text of a valid SQL statement or PL/SQL block.

The Need for Dynamic SQL:


For following situations.

1) You want to execute a SQL data definition statement (such as CREATE), a data
control statement (such as GRANT), or a session control statement (such as ALTER
SESSION). In PL/SQL, such statements cannot be executed statically.
2) You want more flexibility. For example, you might want to defer your choice of
schema objects until run time. Or, you might want your program to build different
search conditions for the WHERE clause of a SELECT statement. A more complex
program might choose from various SQL operations, clauses, etc.
3) You use package DBMS_SQL to execute SQL statements dynamically, but you want
better performance, something easier to use, or functionality that DBMS_SQL lacks
such as support for objects and collections.
Using the EXECUTE IMMEDIATE statement:
EXECUTE IMMEDIATE dynamic_string
[INTO {define_variable[, define_variable]... | record}]
[USING [IN | OUT | IN OUT] bind_argument
[, [IN | OUT | IN OUT] bind_argument]...];

where dynamic_string is a string expression that represents a SQL statement or PL/SQL


block, define_variable is a variable that stores a SELECTed column value, record is a
user-defined or %ROWTYPE record that stores a SELECTed row, and bind_argument is an
expression whose value is passed to the dynamic SQL statement or PL/SQL block. (The
NOCOPY compiler hint is not allowed in an EXECUTE IMMEDIATE statement.)

Except for multi-row queries, the string can contain any SQL statement (without the
terminator) or any PL/SQL block (with the terminator). The string can also contain
placeholders for bind arguments. However, you cannot use bind arguments to pass the
names of schema objects to a dynamic SQL statement.

Caution: You can execute a dynamic SQL statement repeatedly using new values for the
bind arguments. However, you incur some overhead because EXECUTE IMMEDIATE
re-prepares the dynamic string before every execution.

Example:

DECLARE
sql_stmt VARCHAR2(100);
plsql_block VARCHAR2(200);
my_deptno NUMBER(2) := 50;
my_dname VARCHAR2(15) := 'PERSONNEL';
my_loc VARCHAR2(15) := 'DALLAS';
emp_rec emp%ROWTYPE;
BEGIN
sql_stmt := 'INSERT INTO dept VALUES (:1, :2, :3)';
EXECUTE IMMEDIATE sql_stmt USING my_deptno, my_dname, my_loc;

sql_stmt := 'SELECT * FROM emp WHERE empno = :id';


EXECUTE IMMEDIATE sql_stmt INTO emp_rec USING 7788;

EXECUTE IMMEDIATE 'DELETE FROM dept


WHERE deptno = :n' USING my_deptno;

plsql_block := 'BEGIN emp_stuff.raise_salary(:id, :amt); END;';


EXECUTE IMMEDIATE plsql_block USING 7788, 500;

EXECUTE IMMEDIATE 'CREATE TABLE bonus (id NUMBER, amt NUMBER)';

sql_stmt := 'ALTER SESSION SET SQL_TRACE TRUE';


EXECUTE IMMEDIATE sql_stmt;
END;
Static Vs Dynamic Sql.
With static sql, the compiler (or precompiler) is able to "see" the sql and do much more with
it. It knows what data types it uses, what inputs it has, what the outputs look like. It
knows the tables it is accessing and can make the security checks at compile time
(especially with respect to PLSQL this is true) and so on. In short, alot of work can be done
at compile time.

With dynamic sql, we have SQL that is not known until run time. the PLSQL engine does
not know how many columns might be fetched, what tables will be accessed, what inputs
are expected. You, the programmer, must do more work to deal with this.

Static code is always better.

You use dynamic sql only when there is quite simply NO WAY to do it statically.

Static sql has the advantages of

o speed
o ease of coding
o ease of maintenance
o automatic dependency tracking (if you statically reference something, it is recorded in
the data dictionary and you can query up that fact. If you dynamically reference it -- it is
NOT recordable)
o ease of debugging/testing (with dynamic sql, the query isn't generated until runtime --
will that query work? I don't know until i run EVERY possible combination. With STATIC
sql I know at compile time that its valid sql)

Always use static sql until you cannot.

Difference Between Execute Immediate and DBMS_SQL.

DBMS_SQL Execute Immediate


a) parse once Parse and execute each time.
b) execute over and over and over

It supports more than 32K. String of 32K(Max) is allowed.

DBMS_SQL:
OPEN_CURSOR:
To process a SQL statement, you must have an open cursor. When you call the
OPEN_CURSOR function, you receive a cursor ID number for the data structure representing
a valid cursor maintained by Oracle.

PARSE :
Every SQL statement must be parsed by calling the PARSE procedure. Parsing the
statement checks the statement's syntax and associates it with the cursor in your program.

BIND_VARIABLE or BIND_ARRAY :
Many DML statements require that data in your program be input to Oracle. When you
define a SQL statement that contains input data to be supplied at runtime, you must use
placeholders in the SQL statement to mark where data must be supplied.
For each placeholder in the SQL statement, you must call one of the bind procedures,
BIND_VARIABLE or BIND_ARRAY, to supply the value of a variable in your program (or the
values of an array) to the placeholder. When the SQL statement is subsequently run, Oracle
uses the data that your program has placed in the output and input, or bind, variables.

EXECUTE:
Call the EXECUTE function to run your SQL statement.

FETCH_ROWS or EXECUTE_AND_FETCH :
The FETCH_ROWS function retrieves the rows that satisfy the query. Each successive fetch
retrieves another set of rows, until the fetch is unable to retrieve anymore rows. Instead of
calling EXECUTE and then FETCH_ROWS, you may find it more efficient to call
EXECUTE_AND_FETCH if you are calling EXECUTE for a single execution.

CLOSE_CURSOR :
When you no longer need a cursor for a session, close the cursor by calling
CLOSE_CURSOR.

CREATE OR REPLACE PROCEDURE demo(salary IN NUMBER) AS


cursor_name INTEGER;
rows_processed INTEGER;
BEGIN
cursor_name := dbms_sql.open_cursor;
DBMS_SQL.PARSE(cursor_name, 'DELETE FROM emp WHERE sal > :x',
dbms_sql.native);
DBMS_SQL.BIND_VARIABLE(cursor_name, ':x', salary);
rows_processed := dbms_sql.execute(cursor_name);
DBMS_SQL.close_cursor(cursor_name);
EXCEPTION
WHEN OTHERS THEN
DBMS_SQL.CLOSE_CURSOR(cursor_name);
END;

What is the difference between pragma exception_init , and raise application error( which is
a subprogram from dbms_standard package).

ANSWER=>
pragma exception init turns an Oracle Error into a named exception. If a
database operation raises an ORA-00054 "resource busy", you would have to code:
....
exception
when others then
if (sqlcode=-54) then
.... deal with it.
else
RAISE;
end if;

if you pragma exception init'ed this error to some named exception RESOURCE_BUSY
, you can code:

....
pragma exception_init( resource_busy, -54 );
begin
....
exception
when resource_busy then
.... deal with it.
end;

much cleaner (i hate when others -- should be outlawed).

Raise_application_error is used to RAISE an error - exception_init is used to deal with errors


(i guess you could say they are opposites in a way).

I use raise_application_error when I want to setup a custom error message to be returned


to a client application

raise_application_error( -20001, 'You cannot do that!' );

If I just fling a named exception, the client gets the truly usless error
message "unhandled user defined exception". If I use raise_application_error --
the client gets whatever I send back.

You might also like