Package
Package
Goods which are not shared are not goods. --Fernando de Rojas
This chapter shows you how to bundle related PL/SQL programming resources into a package.
The resources might include a collection of procedures or a pool of type definitions and variable
declarations. For example, a Human Resources package might contain hiring and firing
procedures. Once written, your general-purpose package is compiled, then stored in an Oracle
database, where its contents can be shared by many applications.
As Figure 9-1 shows, you can think of the spec as an operational interface and of the body as a
"black box." You can debug, enhance, or replace a package body without changing the interface
(package spec) to the package.
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 (except pragmas that name a specific
function; such pragmas must follow the function spec).
The body holds implementation details and private declarations, which are hidden from your
application. Following the declarative part of the package body is the optional initialization part,
which typically holds statements that initialize package variables.
The AUTHID clause determines whether all the packaged subprograms execute with the privileges
of their definer (the default) or invoker, and whether their unqualified references to schema
objects are resolved in the schema of the definer or invoker. For more information, see "Invoker
Rights Versus Definer Rights".
A call spec lets you publish a Java method or external C function in the Oracle data dictionary.
The call spec publishes the routine by mapping its name, parameter types, and return type to their
SQL counterparts. To learn how to write Java call specs, see Oracle9i Java Stored Procedures
Developer's Guide. To learn how to write C call specs, see Oracle9i Application Developer's
Guide - Fundamentals.
In the example below, you package a record type, a cursor, and two employment procedures.
Notice that the procedure hire_employee uses the database sequence empno_seq and the
function SYSDATE to insert a new employee number and hire date, respectively.
Modularity
Packages let you encapsulate logically related types, items, and subprograms in a named PL/SQL
module. Each package is easy to understand, and the interfaces between packages are simple,
clear, and well defined. This aids application development.
When designing an application, all you need initially is the interface information in the package
specs. You can code and compile a spec without its body. Then, stored subprograms that
reference the package can be compiled as well. You need not define the package bodies fully
until you are ready to complete the application.
Information Hiding
With packages, you can specify which types, items, and subprograms are public (visible and
accessible) or private (hidden and inaccessible). For example, if a package contains four
subprograms, three might be public and one private. The package hides the 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. Also, they allow you to maintain data across
transactions without having to store it in the database.
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.
Understanding The Package Spec
The package spec contains public declarations. The scope of these declarations is local to your
database schema and global to the package. So, the declared items are accessible from your
application and from anywhere in the package. Figure 9-2 illustrates the scoping.
The spec lists the package resources available to applications. All the information your
application needs to use the resources is in the spec. For example, the following declaration
shows that the function named fac takes one argument of type INTEGER and returns a value of
type INTEGER:
That is all the information you need to call the function. You need not consider its underlying
implementation (whether it is iterative or recursive for example).
Only subprograms and cursors have an underlying implementation. So, if a spec declares only
types, constants, variables, exceptions, and call specs, the package body is unnecessary. Consider
the following bodiless package:
To reference the types, items, subprograms, and call specs declared within a package spec, use
dot notation, as follows:
package_name.type_name
package_name.item_name
package_name.subprogram_name
package_name.call_spec_name
You can reference package contents from database triggers, stored subprograms, 3GL
application programs, and various Oracle tools. For example, you might call the packaged
procedure hire_employee from SQL*Plus, as follows:
In the example below, you call the same procedure from an anonymous PL/SQL block
embedded in a Pro*C program. The actual parameters emp_name and job_title are host
variables (that is, variables declared in a host environment).
Restrictions
You cannot reference remote packaged variables directly or indirectly. For example, you cannot
call the following procedure remotely because it references a packaged variable in a parameter
initialization clause:
To match subprogram specs and bodies, PL/SQL does a token-by-token comparison of their
headers. So, except for white space, the headers must match word for word. Otherwise, PL/SQL
raises an exception, as the following example shows:
The package body can also contain private declarations, which define types and items necessary
for the internal workings of the package. The scope of these declarations is local to the package
body. Therefore, the declared types and items are inaccessible except from within the package
body. Unlike a package spec, the declarative part of a package body can contain subprogram
bodies.
Following the declarative part of a package body is the optional initialization part, which
typically holds statements that initialize some of the variables previously declared in the
package.
The initialization part of a package plays a minor role because, unlike subprograms, a package
cannot be called or passed parameters. As a result, the initialization part of a package is run only
once, the first time you reference the package.
Remember, if a package spec declares only types, constants, variables, exceptions, and call
specs, the package body is unnecessary. However, the body can still be used to initialize items
declared in the package spec.
After writing the package, you can develop applications that reference its types, call its
subprograms, use its cursor, and raise its exception. When you create the package, it is stored in
an Oracle database for general use.
Remember, the initialization part of a package is run just once, the first time you reference the
package. So, in the last example, only one row is inserted into the database table emp_audit.
Likewise, the variable number_hired is initialized only once.
Every time the procedure hire_employee is called, the variable number_hired is updated.
However, the count kept by number_hired is session specific. That is, the count reflects the
number of new employees processed by one user, not the number processed by all users.
In the next example, you package some typical bank transactions. Assume that debit and credit
transactions are entered after business hours through automatic teller machines, then applied to
accounts the next morning.
PROCEDURE enter_transaction (
/* Add a transaction to transactions table. */
acct INT,
kind CHAR,
amount REAL) IS
BEGIN
INSERT INTO transactions
VALUES (acct, kind, amount, 'Pending', SYSDATE);
END enter_transaction;
However, items declared in the spec of emp_actions, such as the exception invalid_salary,
are visible outside the package. Therefore, any PL/SQL code can reference the exception
invalid_salary. Such items are called public.
When you must maintain items throughout a session or across transactions, place them in the
declarative part of the package body. For example, the value of number_hired is kept between
calls to hire_employee within the same session. The value is lost when the session ends.
If you must also make the items public, place them in the package spec. For example, the
constant minimum_balance declared in the spec of the package bank_transactions is available
for general use.
The contents of package STANDARD are directly visible to applications. You do not need to
qualify references to its contents by prefixing the package name. For example, you might call
ABS from a database trigger, stored subprogram, Oracle tool, or 3GL application, as follows:
If you redeclare ABS in a PL/SQL program, your local declaration overrides the global
declaration. However, you can still call the built-in function by qualifying the reference to ABS,
as follows:
Most built-in functions are overloaded. For example, package STANDARD contains the following
declarations:
PL/SQL resolves a call to TO_CHAR by matching the number and datatypes of the formal and
actual parameters.
Package DBMS_ALERT lets you use database triggers to alert an application when specific database
values change. The alerts are transaction based and asynchronous (that is, they operate
independently of any timing mechanism). For example, a company might use this package to
update the value of its investment portfolio as new stock and bond quotes arrive.
Package DBMS_OUTPUT enables you to display output from PL/SQL blocks and subprograms,
which makes it easier to test and debug them. The procedure put_line outputs information to a
buffer in the SGA. You display the information by calling the procedure get_line or by setting
SERVEROUTPUT ON in SQL*Plus. For example, suppose you create the following stored
procedure:
When you issue the following commands, SQL*Plus displays the value assigned by the
procedure to parameter payroll:
Package DBMS_PIPE allows different sessions to communicate over named pipes. (A pipe is an
area of memory used by one process to pass information to another.) You can use the procedures
pack_message and send_message to pack a message into a pipe, then send it to another session
in the same instance.
At the other end of the pipe, you can use the procedures receive_message and
unpack_message to receive and unpack (read) the message. Named pipes are useful in many
ways. For example, you can write routines in C that allow external programs to collect
information, then send it through pipes to procedures stored in an Oracle database.
Package UTL_FILE allows your PL/SQL programs to read and write operating system (OS) text
files. It provides a restricted version of standard OS stream file I/O, including open, put, get, and
close operations.
When you want to read or write a text file, you call the function fopen, which returns a file
handle for use in subsequent procedure calls. For example, the procedure put_line writes a text
string and line terminator to an open file, and the procedure get_line reads a line of text from
an open file into an output buffer.
Package UTL_HTTP allows your PL/SQL programs to make hypertext transfer protocol (HTTP)
callouts. It can retrieve data from the Internet or call Oracle Web Server cartridges. The package
has two entry points, each of which accepts a URL (uniform resource locator) string, contacts the
specified site, and returns the requested data, which is usually in hypertext markup language
(HTML) format.
Package specs reflect the design of your application. So, define them before the package bodies.
Place in a spec only the types, items, and subprograms that must be visible to users of the
package. That way, other developers cannot misuse the package by basing their code on
irrelevant implementation details.
To reduce the need for recompiling when code is changed, place as few items as possible in a
package spec. Changes to a package body do not require Oracle to recompile dependent
procedures. However, changes to a package spec require Oracle to recompile every stored
subprogram that references the package.