You are on page 1of 11

Subprograms

Subprograms are named PL/SQL blocks that can take parameters and be invoked.
PL/SQL has two types of subprograms called procedures and functions. Generally, you
use a procedure to perform an action and a function to compute a value.
Like anonymous PL/SQL blocks, subprograms have a declarative part, an executable
part, and an optional exception-handling part.
Stored subprograms defined within a package are called packaged subprograms. Those
defined independently are called standalone subprograms.
Advantages of Subprograms
Stored subprograms offer higher productivity, better performance, memory savings,
application integrity, and tighter security.
Subprograms provide extensibility; that is, they let you tailor the PL/SQL language to suit
your needs.
Subprograms also provide modularity; that is, they let you break a program down into
manageable, well-defined modules. This supports top-down design and the stepwise
refinement approach to problem solving.
Subprograms promote reusability and maintainability. Once validated, a subprogram can
be used with confidence in any number of applications. If its definition changes, only the
subprogram is affected. This simplifies maintenance.
Subprograms are stored in parsed, compiled form. So, when called, they are loaded and
passed to the PL/SQL engine immediately. Also, they take advantage of shared memory.
So, only one copy of a subprogram need be loaded into memory for execution by
multiple users.
Procedures:
A procedure is a subprogram that performs a specific action.
[CREATE [OR REPLACE]]
PROCEDURE procedure_name [(parameter [, parameter]...)]
{IS | AS}
[Local declarations]
BEGIN
Executable statements
[EXCEPTION
Exception handlers]
END [name];

A procedure has two parts: the specification (spec for short) and the body. The procedure
spec begins with the keyword PROCEDURE and ends with the procedure name or a
parameter list. Parameter declarations are optional. Procedures that take no parameters
are written without parentheses.
The procedure body begins with the keyword IS (or AS) and ends with the keyword END
followed by an optional procedure name.
The procedure body has three parts: a declarative part, an executable part, and an optional
exception-handling part.
Create or Replace Procedure Emp_Insert (V_empno in number, V_ename
in varchar2) is
Procedure Emp_Log is
BEGIN
INSERT into LOG Values (User, Sysdate);
END Emp_Log;
BEGIN
INSERT into EMP (Empno, Ename) Values (V_empno, V_ename);
Emp_Log;
EXCEPTION
When Others then
Dbms_output.put_line (sqlcode||' '||sqlerrm);
END Emp_Insert;
/
A function is a subprogram that computes a value. Functions and procedures are
structured alike, except that functions have a RETURN clause
[CREATE [OR REPLACE]]
FUNCTION function_name [(parameter [, parameter]...)] RETURN
Datatype
{IS | AS}
[Local declarations]
BEGIN
Executable statements
[EXCEPTION
Exception handlers]
END [name];

Like a procedure, a function has two parts: the spec and the body. The function spec
begins with the keyword FUNCTION and ends with the RETURN clause, which specifies the
datatype of the return value. Parameter declarations are optional. Functions that take no
parameters are written without parentheses.
The function body begins with the keyword IS (or AS) and ends with the keyword END
followed by an optional function name. The function body has three parts: a declarative
part, an executable part, and an optional exception-handling part.

RETURN Statement
The RETURN statement immediately completes the execution of a subprogram
and returns control to the caller.
In procedures, a RETURN statement cannot return a value, and therefore
cannot contain an expression. The statement simply returns control to
the caller before the normal end of the procedure is reached.
In functions, a RETURN statement must contain an expression, which is
evaluated when the RETURN statement is executed. The resulting value is
assigned to the function identifier, which acts like a variable of the
type specified in the RETURN clause.

In a function, there must be at least one execution path that leads to a RETURN statement.
Otherwise, you get a function returned without value error at run time.
Actual Versus Formal Subprogram Parameters

The variables or expressions referenced in the parameter list of a subprogram call are
actual parameters.
Example:
raise_salary (emp_num, amount);

The variables declared in a subprogram spec and referenced in the subprogram body are
formal parameters. Formal parameters cannot be constrained.

Subprogram Parameter Modes


Parameter modes define the behavior of formal parameters.
The three parameter modes, IN (the default), OUT, and IN OUT.
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. The actual parameter that corresponds to an IN


formal parameter can be a constant, literal, initialized variable, or expression.
IN parameters can be initialized to default values.
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
The actual parameter that corresponds to an OUT formal parameter must be a variable; it
cannot be a constant or an expression.

IN

OUT

IN OUT

the default

must be specified

must be specified

passes values to a subprogram

returns values to the passes initial values to a


caller
subprogram and returns updated
values to the caller

formal parameter acts like a


constant

formal parameter
acts like a variable

formal parameter acts like an


initialized variable

formal parameter cannot be


assigned a value

formal parameter
must be assigned a
value

formal parameter should be


assigned a value

actual parameter can be a


constant, initialized variable,
literal, or expression

actual parameter
must be a variable

actual parameter must be a


variable

Example:
CREATE or Replace PROCEDURE calc_comm (emp_id IN INTEGER, comm OUT REAL)
IS
Hire_date
DATE;
Comm_missing EXCEPTION;
BEGIN
SELECT comm, hiredate INTO comm, hire_date FROM EMP
WHERE empno = emp_id;
IF comm IS NULL THEN
RAISE comm_missing;
END IF;
IF MONTHS_BETWEEN (SYSDATE, hire_date) > 60 THEN

Comm:=comm + 500;
END IF;
EXCEPTION
WHEN comm_missing THEN
Update EMP set comm=500 where empno=emp_id;
END calc_comm;

DECLARE
V_comm number;
BEGIN
calc_comm (7566, v_comm);
Dbms_output.put_line (v_comm);
END;
/

Example:
PROCEDURE raise_salary (emp_id INTEGER, amount REAL) IS
BEGIN
UPDATE EMP SET sal = sal + amount WHERE empno = emp_id;
END raise_salary;

The actual parameter and its corresponding formal parameter must have compatible
datatypes.
When you call the subprogram, the IN parameter is passed by reference. That is, a pointer
to the IN actual parameter is passed to the corresponding formal parameter. So, both
parameters reference the same memory location, which holds the value of the actual
parameter.
By default, the OUT and IN OUT parameters are passed by value. That is, the value of the
IN OUT actual parameter is copied into the corresponding formal parameter, results into
slow down the execution process and uses up memory.
To prevent that, you can specify the NOCOPY hint, which allows the PL/SQL compiler to
pass OUT and IN OUT parameters by reference.
Example:
calc_comm (emp_id IN INTEGER, comm OUT NOCOPY REAL) IS...

Packages
A package is an encapsulated collection of related program objects stored together in the
database. Program objects are procedures, functions, variables, constants, cursors, and
exceptions.
Packages have many advantages over standalone procedures and functions. For example,
they:

Let you organize your application development more efficiently.


Let you grant privileges more efficiently.
Let you modify package objects without recompiling dependent schema objects.
Enable Oracle to read multiple package objects into memory at once.
Let you overload procedures or functions. Overloading means creating multiple
procedures with the same name in the same package, each taking arguments of
different number or datatype.
Can contain global variables and cursors that are available to all procedures and
functions in the package.

Packages usually have two parts, a specification and a body, although sometimes the
body is unnecessary. The specification (spec for short) is the interface to your
applications; it declares the types, variables, constants, exceptions, cursors, and
subprograms available for use. The body fully defines cursors and subprograms, and so
implements the spec.

Package Interface

Unlike subprograms, packages cannot be called, parameterized, or nested.


Syntax: Package Specification.
CREATE PACKAGE name AS -- specification (visible part)
-- Public type and item declarations
-- Subprogram specifications
END [name];
Syntax: Package body
CREATE PACKAGE BODY name AS -- body (hidden part)
-- Private type and item declarations
-- Subprogram bodies
[BEGIN
-- initialization statements]
END [name];
The spec holds public declarations, which are visible to your
application. You must declare subprograms at the end of the spec after
all other items.

The body holds implementation details and private declarations, which are hidden from
your application.
Oracle stores the specification and body of a package separately in the database. Other
schema objects that call or reference public program objects depend only on the package
specification, not on the package body. Using this distinction, you can change the
definition of a program object in the package body without causing Oracle to invalidate
other schema objects that call or reference the program object. Oracle invalidates
dependent schema objects only if you change the declaration of the program object in the
package specification.

Advantages of PL/SQL Packages

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.
Easier Application Design
When designing an application, all you need initially is the interface information in the
package specs. You can code and compile a spec without its body. Then, stored
subprograms that reference the package can be compiled as well. You need not define the
package bodies fully until you are ready to complete the application.
Information Hiding
With packages, you can specify which types, items, and subprograms are public (visible
and accessible) or private (hidden and inaccessible). For example, if a package contains
four subprograms, three might be public and one private. The package hides the
implementation of the private subprogram so that only the package (not your application)
is affected if the implementation 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.
Better Performance
When you call a packaged 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 implementation of a packaged function, Oracle need not
recompile the calling subprograms because they do not depend on the package body

Examples:
Create or Replace Package Emp_Pack is
V_totsal number;
Cursor c1 is select Ename from EMP;
Procedure Get_empsal (V_Ename in varchar2);
Function Get_totsal Return Number;
END Emp_pack;

/
Create or Replace Package body Emp_pack is
Procedure Get_empsal (V_Ename in varchar2) is
BEGIN
Select Sal into V_totsal from EMP where Ename=V_Ename;
Dbms_output.put_line (V_totsal|| ||V_Ename);
END Get_empsal;
Function Get_totsal Return Number is
BEGIN
Select sum (Sal) into V_totsal from EMP;
Return (V_totsal);
END Get_totsal;
END Emp_pack;
/
BEGIN
For I in Emp_pack.c1 Loop
Emp_pack.Get_Empsal (I.Ename);
End Loop;
END;
/
Create or Replace Package Admin_Data As
Type GenCurTyp is Ref Cursor;
Procedure Open_cv (Generic_cv IN OUT GenCurTyp, choice INT);
END Admin_Data;
Create or Replace Package Body Admin_Data As
Procedure Open_cv (Generic_cv in out GenCurTyp, choice Int) Is
BEGIN
IF choice = 1 Then
OPEN Generic_cv FOR SELECT * FROM Emp;
ELSIF choice = 2 THEN
OPEN Generic_cv FOR SELECT * FROM Dept;
ELSIF choice = 3 THEN
OPEN Generic_cv FOR SELECT * FROM Salgrade;
END IF;
END;
END Admin_Data;
/

/* Calling program*/
DECLARE
Type CV is Ref Cursor;
Cv1 CV;
BEGIN
Admin_Data.Open_cv (cv1, 1);
END;
/
CREATE or Replace procedure Dynatest (V_tname varchar2) as
Cursor c1 is Select column_name from user_tab_columns where table_name =
V_tname;
TYPE cur_typ IS REF CURSOR;
V_cursor cur_typ;
V_query varchar2(1000);
V_columns varchar2(200):= NULL;
V_records EMP%RowType;
BEGIN
For I in c1 loop
V_columns:= V_columns||I.column_name||',';
End Loop;
V_columns:= Substr (V_columns, 1, length (V_columns)-1);
V_query:= 'SELECT'||' '|| V_columns||' FROM'||' '||V_tname;
Dbms_output.put_line (V_query);
OPEN V_cursor FOR V_query;
LOOP
FETCH V_cursor into V_records;
Dbms_output.put_line (V_records.empno);
EXIT When V_cursor%NOTFOUND;
END LOOP;
Dbms_output.put_line (V_cursor%rowcount);
CLOSE V_cursor;
END;
/
Create or Replace Procedure Auto is
PRAGMA Autonomous_Transaction;
BEGIN
INSERT into DEPT values (50,'mark','hyd');
IF sql%found then
Dbms_output.put_line ('Autonomous Transaction Successful');

ELSE
Dbms_output.put_line ('Autonomous Transaction Failure');
END IF;
Commit;
END Auto;
Create or Replace Procedure Emp_insert is
BEGIN
INSERT into EMP (Empno, Ename) values (111,'venkat');
Auto;
Rollback;
END Emp_insert;

Overloading Packaged Subprograms


PL/SQL allows two or more packaged subprograms to have the same name. This option
is useful when you want a subprogram to accept similar sets of parameters that have
different datatypes. For example, the following package defines two procedures named
journalize:
CREATE PACKAGE journal_entries AS
...
PROCEDURE journalize (amount REAL, trans_date VARCHAR2);
PROCEDURE journalize (amount REAL, trans_date INT);
END journal_entries;
CREATE PACKAGE BODY journal_entries AS
...
PROCEDURE journalize (amount REAL, trans_date VARCHAR2) IS
BEGIN
INSERT INTO journal
VALUES (amount, TO_DATE (trans_date, 'DD-MON-YYYY'));
END journalize;
PROCEDURE journalize (amount REAL, trans_date INT) IS
BEGIN
INSERT INTO journal
VALUES (amount, TO_DATE (trans_date, 'J'));
END journalize;
END journal_entries;

The first procedure accepts trans_date as a character string, while the second procedure
accepts it as a number (the Julian day). Each procedure handles the data appropriately.
For the rules that apply to overloaded subprograms.