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

PLSQL Packages

What is a Package. Reasons to use Packages. Package Specification and Body in detail. Package state. SERIALLY_REUSABLE packages. Package writing guidelines.

Uploaded by

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

PLSQL Packages

What is a Package. Reasons to use Packages. Package Specification and Body in detail. Package state. SERIALLY_REUSABLE packages. Package writing guidelines.

Uploaded by

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

Page 1 of 13

PL/SQL Packages
What is a Package:
 A package is a schema object that groups logically related PL/SQL types, variables,
constants, subprograms, cursors, and exceptions.
 A package is compiled and stored in the database, where many applications can
share its contents.
 A package always has a specification, which declares the public items that can be
referenced from outside the package.
 If the public items include cursors or subprograms, then the package must also have
a body. The body must define queries for public cursors and code for public
subprograms.
 The AUTHID clause of the package specification determines whether the
subprograms and cursors in the package run with the privileges of their definer (the
default) or invoker.
 The ACCESSIBLE BY clause of the package specification lets you specify a white list of
PL/SQL units that can access the package. You use this clause in situations like these:
 You implement a PL/SQL application as several packages—one package that
provides the application programming interface (API) and helper packages to
do the work. You want clients to have access to the API, but not to the helper
packages. Therefore, you omit the ACCESSIBLE BY clause from the API package
specification and include it in each helper package specification, where you
specify that only the API package can access the helper package.

 You create a utility package to provide services to some, but not all, PL/SQL
units in the same schema. To restrict use of the package to the intended units,
you list them in the ACCESSIBLE BY clause in the package specification.

Reasons to Use Packages:


Packages support the development and maintenance of reliable, reusable code with the
following features:

 Modularity
Packages let you encapsulate logically related types, variables, constants,
subprograms, cursors, and exceptions in named PL/SQL modules. You can make each
package easy to understand, and make the interfaces between packages simple,
clear, and well defined.
Page 2 of 13

 Easier Application Design


When designing an application, all you need initially is the interface information in
the package specifications. You can code and compile specifications without their
bodies. Next, you can compile standalone subprograms that reference the Packages.

 Hidden Implementation Details


Packages let you share your interface information in the package specification, and
hide the implementation details in the package body. Hiding the implementation
details in the body has these advantages:
– You can change the implementation details without affecting the application
interface.
– Application users cannot develop code that depends on implementation
details that you might want to change.

 Added Functionality
Package public variables and cursors can persist for the life of a session. They can be
shared by all subprograms that run in the environment. They let you maintain data
across transactions without storing it in the database.

 Better Performance
The first time you invoke a package subprogram, Oracle Database loads the whole
package into memory. Subsequent invocations of other subprograms in same the
package require no disk I/O. Packages prevent cascading dependencies and
unnecessary recompiling. For example, if you change the body of a package function,
Oracle Database does not recompile other subprograms that invoke the function,
because these subprograms depend only on the parameters and return value that
are declared in the specification.

 Easier to Grant Roles


You can grant roles on the package, instead of granting roles on each object in the
package.

Note:
You cannot reference host variables from inside a package.
Page 3 of 13

Package Specification
A package specification declares public items. The scope of a public item is the
schema of the package. A public item is visible everywhere in the schema. To
reference a public item that is in scope but not visible, qualify it with the package
name. Each public item declaration has all information needed to use the item.
CREATE PACKAGE Statement:

The CREATE PACKAGE statement creates or replaces the specification for a stored
package.

Prerequisite: To create or replace a package in your schema, you must have the
CREATE PROCEDURE system privilege. To create or replace a package in another
user's schema, you must have the CREATE ANY PROCEDURE system privilege.
To embed a CREATE PACKAGE statement inside the database precompiler program,
you must terminate the statement with the keyword END-EXEC followed by the
embedded SQL statement terminator for the specific language.

Syntax:
Page 4 of 13

Semantics:
OR REPLACE

Re-creates the procedure if it exists, and recompiles it. Users who were granted
privileges on the procedure before it was redefined can still access the procedure
without being regranted the privileges. If any function-based indexes depend on the
procedure, then the database marks the indexes DISABLED.

item_list_1
Defines every type in the package and declares every cursor and subprogram in the
package. Every declaration must have a corresponding definition in the package
body. The headings of corresponding declarations and definitions must match word
for
word, except for white space.

Restriction on item_list_1
PRAGMA AUTONOMOUS_TRANSACTION cannot appear here.

Example: Passing Associative Array to Standalone Subprogram

CREATE OR REPLACE PACKAGE aa_pkg AUTHID DEFINER IS


TYPE aa_type IS TABLE OF INTEGER INDEX BY VARCHAR2(15);
END;
/

CREATE OR REPLACE PROCEDURE print_aa (aa aa_pkg.aa_type) AUTHID DEFINER IS


i VARCHAR2(15);
BEGIN
i := aa.FIRST;
WHILE i IS NOT NULL LOOP
DBMS_OUTPUT.PUT_LINE (aa(i) || ' ' || i);
i := aa.NEXT(i);
END LOOP;
END;
/

DECLARE
aa_var aa_pkg.aa_type;
BEGIN
aa_var('zero') := 0;
aa_var('one') := 1;
aa_var('two') := 2;
Page 5 of 13

print_aa(aa_var);
END;
/

Result:
1 one
2 two
0 zero

Package Body
If a package specification declares cursors or subprograms, then a package body is
required; otherwise, it is optional. The package body and package specification must
be in the same schema.
Every cursor or subprogram declaration in the package specification must have a
corresponding definition in the package body. The headings of corresponding
subprogram declarations and definitions must match word for word, except for white
space.
Package Instantiation and Initialization
When a session references a package item, Oracle Database instantiates the package
for that session. Every session that references a package has its own instantiation of
that package. When Oracle Database instantiates a package, it initializes it.
Initialization includes whichever of the following are applicable:
• Assigning initial values to public constants
• Assigning initial values to public variables whose declarations specify them
• Executing the initialization part of the package body

Package State
The values of the variables, constants, and cursors that a package declares (in either
its specification or body) comprise its package state. If a PL/SQL package declares at
least one variable, constant, or cursor, then the package is stateful; otherwise, it is
stateless. Each session that references a package item has its own instantiation of
that package. If the package is stateful, the instantiation includes its state.
The package state persists for the life of a session, except in these situations:
• The package is SERIALLY_REUSABLE.
• The package body is recompiled.
If the body of an instantiated, stateful package is recompiled (either explicitly, with
the "ALTER PACKAGE Statement", or implicitly), the next invocation of a
subprogram in the package causes Oracle Database to discard the existing package
state and raise the exception ORA-04068.

After PL/SQL raises the exception, a reference to the package causes Oracle
Database to re-instantiate the package, which re-initializes it. Therefore, previous
changes to the package state are lost.
Page 6 of 13

• Any of the session's instantiated packages are invalidated and revalidated.


All of a session's package instantiations (including package states) can be lost if any
of the session's instantiated packages are invalidated and revalidated.

SERIALLY_REUSABLE Packages
SERIALLY_REUSABLE packages let you design applications that manage memory
better for scalability. If a package is not SERIALLY_REUSABLE, its package state is
stored in the user global area (UGA) for each user. Therefore, the amount of UGA
memory needed increases linearly with the number of users, limiting scalability. The
package state can persist for the life of a session, locking UGA memory until the
session ends. In some applications, such as Oracle Office, a typical session lasts
several days.
If a package is SERIALLY_REUSABLE, its package state is stored in a work area in a
small pool in the system global area (SGA). The package state persists only for the
life of a server call. After the server call, the work area returns to the pool. If a
subsequent server call references the package, then Oracle Database reuses an
instantiation from the pool. Reusing an instantiation re-initializes it; therefore,
changes made to the package state in previous server calls are invisible.

Note:
Trying to access a SERIALLY_REUSABLE package from a database trigger, or from a
PL/SQL subprogram invoked by a SQL statement, raises an error.

Creating SERIALLY_REUSABLE Packages


To create a SERIALLY_REUSABLE package, include the SERIALLY_REUSABLE pragma in
the package specification and, if it exists, the package body.

Example: Creating SERIALLY_REUSABLE Packages

-- Create bodiless SERIALLY_REUSABLE package:


CREATE OR REPLACE PACKAGE bodiless_pkg AUTHID DEFINER IS
PRAGMA SERIALLY_REUSABLE;
n NUMBER := 5;
END;
/

-- Create SERIALLY_REUSABLE package with specification and body:


CREATE OR REPLACE PACKAGE pkg AUTHID DEFINER IS
PRAGMA SERIALLY_REUSABLE;
n NUMBER := 5;
END;
/
Page 7 of 13

CREATE OR REPLACE PACKAGE BODY pkg IS


PRAGMA SERIALLY_REUSABLE;
BEGIN
n := 5;
END;
/

SERIALLY_REUSABLE Package Work Unit


For a SERIALLY_REUSABLE package, the work unit is a server call. You must use its
public variables only within the work unit.

Note:
If you make a mistake and depend on the value of a public variable that was set in a
previous work unit, then your program can fail. PL/SQL cannot check for such cases.

In below example, the bodiless packages pkg and pkg_sr are the same, except that
pkg_sr is SERIALLY_REUSABLE and pkg is not. Each package declares public variable n
with initial value 5. Then, an anonymous block changes the value of each variable to
10. Next, another anonymous block prints the value of each variable. The value of
pkg.n is still 10, because the state of pkg persists for the life of the session. The value
of pkg_sr.n is 5, because the state of pkg_sr persists only for the life of the
server call.

After the work unit (server call) of a SERIALLY_REUSABLE package completes, Oracle
Database does the following:
• Closes any open cursors.
• Frees some nonreusable memory (for example, memory for collection and long
VARCHAR2 variables)
• Returns the package instantiation to the pool of reusable instantiations kept for this
package.

Example: Effect of SERIALLY_REUSABLE Pragma

CREATE OR REPLACE PACKAGE pkg IS


n NUMBER := 5;
END pkg;
/

CREATE OR REPLACE PACKAGE sr_pkg IS


PRAGMA SERIALLY_REUSABLE;
n NUMBER := 5;
Page 8 of 13

END sr_pkg;
/

BEGIN
pkg.n := 10;
sr_pkg.n := 10;
END;
/

BEGIN
DBMS_OUTPUT.PUT_LINE('pkg.n: ' || pkg.n);
DBMS_OUTPUT.PUT_LINE('sr_pkg.n: ' || sr_pkg.n);
END;
/
Result:
pkg.n: 10
sr_pkg.n: 5

Explicit Cursors in SERIALLY_REUSABLE Packages


An explicit cursor in a SERIALLY_REUSABLE package remains open until either you
close it or its work unit (server call) ends. To re-open the cursor, you must make a
new server call. A server call can be different from a subprogram invocation, as in
below example.
In contrast, an explicit cursor in a package that is not SERIALLY_REUSABLE remains
open until you either close it or disconnect from the session.

Example: Cursor in SERIALLY_REUSABLE Package Open at Call Boundary


DROP TABLE people;
CREATE TABLE people (name VARCHAR2(20));
INSERT INTO people (name) VALUES ('John Smith');
INSERT INTO people (name) VALUES ('Mary Jones');
INSERT INTO people (name) VALUES ('Joe Brown');
INSERT INTO people (name) VALUES ('Jane White');

CREATE OR REPLACE PACKAGE sr_pkg IS


PRAGMA SERIALLY_REUSABLE;
CURSOR c IS SELECT name FROM people;
END sr_pkg;
/

CREATE OR REPLACE PROCEDURE fetch_from_cursor IS


Page 9 of 13

v_name people.name%TYPE;
BEGIN
IF sr_pkg.c%ISOPEN THEN
DBMS_OUTPUT.PUT_LINE('Cursor is open.');
ELSE
DBMS_OUTPUT.PUT_LINE('Cursor is closed; opening now.');
OPEN sr_pkg.c;
END IF;
FETCH sr_pkg.c INTO v_name;
DBMS_OUTPUT.PUT_LINE('Fetched: ' || v_name);
FETCH sr_pkg.c INTO v_name;
DBMS_OUTPUT.PUT_LINE('Fetched: ' || v_name);
END fetch_from_cursor;
/

First call to server:


BEGIN
fetch_from_cursor;
fetch_from_cursor;
END;
/
Result:
Cursor is closed; opening now.
Fetched: John Smith
Fetched: Mary Jones
Cursor is open.
Fetched: Joe Brown
Fetched: Jane White

New call to server:


BEGIN
fetch_from_cursor;
fetch_from_cursor;
END;
/

Result:
Cursor is closed; opening now.
Fetched: John Smith
Fetched: Mary Jones
Cursor is open.
Fetched: Joe Brown
Fetched: Jane White
Page 10 of 13

Package Writing Guidelines


• Become familiar with the packages that Oracle Database supplies, and avoid writing
packages that duplicate their features.
• Keep your packages general so that future applications can reuse them.
• Design and define the package specifications before the package bodies.
• In package specifications, declare only items that must be visible to invoking
programs. This practice prevents other developers from building unsafe
dependencies on your implementation details and reduces the need for
recompilation.
If you change the package specification, you must recompile any subprograms that
invoke the public subprograms of the package. If you change only the package body,
you need not recompile those subprograms.
• Declare public cursors in package specifications and define them in package bodies,
as in Example 1.
This practice lets you hide cursors' queries from package users and change them
without changing cursor declarations.
• Assign initial values in the initialization part of the package body instead of in
declarations.
This practice has these advantages:
– The code for computing the initial values can be more complex and better
documented.
– If computing an initial value raises an exception, the initialization part can handle
it with its own exception handler.
• If you implement a database application as several PL/SQL packages—one package
that provides the API and helper packages to do the work, then make the helper
packages available only to the API package, as in Example 2.

Example 1, the declaration and definition of the cursor c1 are in the specification and
body, respectively, of the package emp_stuff. The cursor declaration specifies only
the data type of the return value, not the query, which appears in the cursor
definition.

Example 1: Separating Cursor Declaration and Definition in Package

CREATE PACKAGE emp_stuff AS


CURSOR c1 RETURN employees%ROWTYPE; -- Declare cursor
END emp_stuff;
/

CREATE PACKAGE BODY emp_stuff AS


CURSOR c1 RETURN employees%ROWTYPE IS
SELECT * FROM employees WHERE salary > 2500; -- Define cursor
END emp_stuff; /
Page 11 of 13

Example 2, creates an API package and a helper package. Because of the ACCESSIBLE
BY clause in the helper package specification, only the API package can access the
helper package.

Example 2: ACCESSIBLE BY Clause

CREATE OR REPLACE PACKAGE helper


AUTHID DEFINER
ACCESSIBLE BY (api)
IS
PROCEDURE h1;
PROCEDURE h2;
END;
/
CREATE OR REPLACE PACKAGE BODY helper
IS
PROCEDURE h1 IS
BEGIN
DBMS_OUTPUT.PUT_LINE('Helper procedure h1');
END;

PROCEDURE h2 IS
BEGIN
DBMS_OUTPUT.PUT_LINE('Helper procedure h2');
END;
END;
/

CREATE OR REPLACE PACKAGE api


AUTHID DEFINER
IS
PROCEDURE p1;
PROCEDURE p2;
END;
/

CREATE OR REPLACE PACKAGE BODY api


IS
PROCEDURE p1 IS
BEGIN
DBMS_OUTPUT.PUT_LINE('API procedure p1');
helper.h1;
END;
Page 12 of 13

PROCEDURE p2 IS
BEGIN
DBMS_OUTPUT.PUT_LINE('API procedure p2');
helper.h2;
END;
END;
/

Invoke procedures in API package:


BEGIN
api.p1;
api.p2;
END;
/
Result:
API procedure p1
Helper procedure h1
API procedure p2
Helper procedure h2

Invoke a procedure in helper package:


BEGIN
helper.h1;
END;
/

Result:
SQL> BEGIN
2 helper.h1;
3 END;
4/
helper.h1;
*
ERROR at line 2:
ORA-06550: line 2, column 3:
PLS-00904: insufficient privilege to access object HELPER
ORA-06550: line 2, column 3:
PL/SQL: Statement ignored
Page 13 of 13

How STANDARD Package Defines the PL/SQL Environment


A package named STANDARD defines the PL/SQL environment. The package
specification declares public types, variables, exceptions, subprograms, which are
available automatically to PL/SQL programs.

For example, package STANDARD declares function ABS, which returns the absolute
value of its argument, as follows:
FUNCTION ABS (n NUMBER) RETURN NUMBER;

The contents of package STANDARD are directly visible to applications. You need not
qualify references to its contents by prefixing the package name.

For example, you might invoke ABS from a database trigger, stored subprogram,
Oracle tool, or 3GL application, as follows:
abs_diff := ABS(x - y);

If you declare your own version of ABS, your local declaration overrides the public
declaration. You can still invoke the SQL function by specifying its full name:
abs_diff := STANDARD.ABS(x - y);

Most SQL functions are overloaded. For example, package STANDARD contains these
declarations:
FUNCTION TO_CHAR (right DATE) RETURN VARCHAR2;
FUNCTION TO_CHAR (left NUMBER) RETURN VARCHAR2;
FUNCTION TO_CHAR (left DATE, right VARCHAR2) RETURN VARCHAR2;
FUNCTION TO_CHAR (left NUMBER, right VARCHAR2) RETURN VARCHAR2;

PL/SQL resolves an invocation of TO_CHAR by matching the number and data types
of the formal and actual parameters.

Disadvantages of Packages:
More memory may be required on the Oracle database server when using Oracle
PL/SQL packages as the whole package is loaded into memory as soon as any object
in the package is accessed.

Updating one of the functions/procedures will invalid other objects which use
different function/procedures since whole package need to be compiled.

--------------------------- End ---------------------------

You might also like