Chapter 11 · PL/SQL Fundamentals: Blocks, Types, Procedures, Functions, and Packages

Packages, Specification vs Body, State, Initialization, Encapsulation, and Editioning Awareness

Use package specifications as stable public APIs and package bodies as hidden implementation, then make session package state, initialization, invalidation, and editionability visible.

Advanced115–135 minutesPackage API/state/invalidation labPackage spec/body + ORA-04068 pathEditioning awareness only; EBR not requiredLast reviewed: August 2026

Learning outcomes

ServiceHub exposes many standalone routines. Clients depend on implementation details, and deployments frequently invalidate callers. A redesign moves the public contract into a package specification and hides implementation in the body. Then a long-lived connection pool reveals another Oracle-specific issue: package variables are session state, and replacing or recompiling a stateful package can cause existing sessions to discard state and surface ORA-04068.

01

Treat a package specification as the public API and the body as hidden implementation.

02

Use package initialization deliberately and understand that ordinary package state normally lives for the session.

03

Demonstrate package-state isolation across sessions and ORA-04068 after stateful invalidation/recompilation.

04

Inspect package/object status and dependencies instead of assuming CREATE OR REPLACE is invisible to running sessions.

05

Record EDITIONABLE/NONEDITIONABLE awareness without assuming Edition-Based Redefinition is configured.

Version, scope, privileges, tooling, and licensing baseline

Mandatory examples target a disposable ServiceHub schema in Oracle AI Database Free 26ai and were reviewed against RU 23.26.3, SQL Developer 26.2, and SQLcl 26.2.1. Free is limited to 2 foreground CPU cores, 2 GB combined SGA/PGA memory, and 12 GB user data and receives no Oracle patches or Support service requests. The chapter requires no Diagnostics Pack, Tuning Pack, RAC, Data Guard, Exadata, GoldenGate, OCI service, or COMPATIBLE change. Stored program creation in the course owner requires CREATE PROCEDURE; cross-schema execution requires explicit EXECUTE grants. Dynamic performance views used for optional session/PGA evidence should be read through a DBA observer or narrowly granted V_$ views in the disposable PDB.

1. Specification versus body is an API boundary

The package specification declares public types, constants, variables, exceptions, cursors, procedures, and functions. The body defines public subprograms and can contain private helpers and variables that callers cannot reference directly. Oracle stores the specification and body separately.

Callers that depend only on public declarations depend on the package specification, not on private implementation. Replacing the body without changing the specification therefore avoids many unnecessary caller invalidations—but an instantiated stateful package is a separate runtime concern.

sql · stable public API
CREATE OR REPLACE PACKAGE servicehub_case_api AUTHID DEFINER AS  PROCEDURE set_default_status(p_status IN VARCHAR2);  FUNCTION  get_default_status RETURN VARCHAR2;  FUNCTION  normalize_status(p_status IN VARCHAR2) RETURN VARCHAR2;END servicehub_case_api;/
sql · hidden implementation and package state
CREATE OR REPLACE PACKAGE BODY servicehub_case_api AS  g_default_status VARCHAR2(12);  FUNCTION normalize_status(p_status IN VARCHAR2)    RETURN VARCHAR2  IS  BEGIN    RETURN UPPER(TRIM(p_status));  END;  PROCEDURE set_default_status(p_status IN VARCHAR2) IS  BEGIN    g_default_status := normalize_status(p_status);  END;  FUNCTION get_default_status RETURN VARCHAR2 IS  BEGIN    RETURN g_default_status;  END;BEGIN  g_default_status := 'OPEN';END servicehub_case_api;/

2. Package initialization and state are session-scoped by default

The package body's initialization section executes when the package is instantiated in a session. Package variables can retain values across calls in that same session. Another session gets its own package instance/state. This makes package variables convenient for session-local caches/settings but dangerous as a substitute for durable business state.

sql · Session A
SET SERVEROUTPUT ONEXEC servicehub_case_api.set_default_status('hold');BEGIN  DBMS_OUTPUT.PUT_LINE(    'Session A=' || servicehub_case_api.get_default_status  );END;/-- HOLD
sql · Session B
SET SERVEROUTPUT ONBEGIN  DBMS_OUTPUT.PUT_LINE(    'Session B=' || servicehub_case_api.get_default_status  );END;/-- OPEN on this session's first instantiation

Connection pooling complicates this: a later request can inherit state from whatever database session the pool assigns. Prefer stateless APIs unless session state is intentional and the pool lifecycle explicitly resets it.

3. Changing package implementation can discard instantiated state

If a stateful package instance is invalidated/recompiled while a session has instantiated it, the session can lose package state. Oracle documents ORA-04068 as the signal that existing package state was discarded. The application should be designed to reinitialize or retry at a safe API boundary rather than assuming state survives deployments.

sql · Session A — instantiate state
EXEC servicehub_case_api.set_default_status('closed');SELECT servicehub_case_api.get_default_status AS before_changeFROM dual;-- CLOSED
sql · Session B — recompile the body without changing the API
ALTER PACKAGE servicehub_case_api COMPILE BODY;
sql · Session A — next use after invalidation
SELECT servicehub_case_api.get_default_status AS after_changeFROM dual;-- Stateful invalidation can surface ORA-04068.-- After safe re-instantiation, initialization state is OPEN.

Exact accompanying errors can vary with the invalidation/recompile path, but the mechanism is the same: session package state is not a deployment-stable persistence layer.

4. Deliberately wrong: mask package invalidation with an unrelated error

Replacing package-state errors with a generic server error can prevent clients from recognizing that session state was discarded and must be reinitialized. Oracle's guidance specifically warns that trapping package invalidation at the wrong layer can interfere with expected reinstantiation behavior.

Safer pattern

Keep business operations idempotent at retry boundaries, reconnect or retry a well-defined package call when deployment invalidation is expected, and avoid relying on mutable package globals for durable workflow state.

5. Encapsulation reduces dependency blast radius

Put stable types and callable signatures in the specification. Keep helper routines and implementation variables private in the body. Changing a private algorithm often requires only a body replacement; changing a public parameter type or declaration changes the API and can invalidate dependents.

sql · inspect package objects and dependencies
SELECT object_name, object_type, status, editionableFROM user_objectsWHERE object_name='SERVICEHUB_CASE_API'ORDER BY object_type;SELECT name, type, referenced_name, referenced_type, dependency_typeFROM user_dependenciesWHERE referenced_name='SERVICEHUB_CASE_API'ORDER BY name, type;

6. Editioning awareness: editionability is not the same as using EBR

Current 26ai CREATE PACKAGE syntax supports EDITIONABLE and NONEDITIONABLE; when editioning is enabled for the package object type, the default is EDITIONABLE. A package body inherits the specification's editionability unless explicitly specified to match it.

This is awareness only. Edition-Based Redefinition (EBR) involves editions, editioning-enabled schemas/object types, editioning views, crossedition triggers, deployment routing, grants, and rollback design. The mandatory Chapter 11 lab does not enable editioning or create editions.

sql · observe edition metadata only
SELECT  object_name,  object_type,  editionable,  edition_name,  statusFROM user_objectsWHERE object_name='SERVICEHUB_CASE_API'ORDER BY object_type;

7. Reproducible package lab

sql · create and verify package
CREATE OR REPLACE PACKAGE servicehub_case_api AUTHID DEFINER AS  PROCEDURE set_default_status(p_status IN VARCHAR2);  FUNCTION get_default_status RETURN VARCHAR2;END servicehub_case_api;/CREATE OR REPLACE PACKAGE BODY servicehub_case_api AS  g_default_status VARCHAR2(12);  PROCEDURE set_default_status(p_status IN VARCHAR2) IS  BEGIN    g_default_status := UPPER(TRIM(p_status));  END;  FUNCTION get_default_status RETURN VARCHAR2 IS  BEGIN    RETURN g_default_status;  END;BEGIN  g_default_status := 'OPEN';END servicehub_case_api;/SELECT object_name, object_type, status, editionableFROM user_objectsWHERE object_name='SERVICEHUB_CASE_API'ORDER BY object_type;
sql · verify session state
EXEC servicehub_case_api.set_default_status('hold');SELECT servicehub_case_api.get_default_status AS current_stateFROM dual;-- HOLD in this session
sql · cleanup
DROP PACKAGE servicehub_case_api;

8. Production judgment

Packages are ideal for stable database APIs, related types, encapsulated helpers, and carefully managed session-local state. Keep specs small and stable, bodies replaceable, privileges explicit, and deployment tests aware of long-lived sessions. Avoid package globals for durable business state and be cautious when connection pools reuse sessions across requests.

No edition configuration, special option, pack, restart, or COMPATIBLE change is required. Lesson 4 focuses on data-processing performance: when procedural row handling is unavoidable, reduce PL/SQL-to-SQL boundary crossings with bulk operations while controlling PGA consumption and error semantics.

Check your understanding

  1. What belongs in the package specification?
  2. How long does ordinary package state typically live?
  3. Why can ORA-04068 appear after package recompilation?
  4. Does EDITIONABLE metadata mean EBR is already configured?
  5. Why does keeping private helpers in the body improve deployment isolation?
Review the answers

Public types, variables/constants/exceptions/cursors, and callable subprogram declarations that form the package API.

Normally for the life of the database session, subject to invalidation/recompilation and special package modes.

An instantiated stateful package can be invalidated; Oracle discards its existing session state and reports the discard on subsequent use.

No. Editionability is an object property; full EBR requires explicit edition/deployment architecture.

Callers depend on the specification, so changing body-only implementation can avoid invalidating code that depends only on public declarations.

Authoritative references

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only Ethereum or ERC-20 compatible assets to this address.