Package Writing Guidelines

  • Become familiar with the packages that Oracle Database supplies, and avoid writing packages that duplicate their features.

    For more information about the packages that Oracle Database supplies, see Oracle Database PL/SQL Packages and Types Reference.

  • 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 11-7.

    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 11-8.

In Example 11-7, 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 (for complete syntax and semantics, see "Explicit Cursor Declaration and Definition").

Example 11-8 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 11-7 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;
/

Example 11-8 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;
 
  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