Conditional Compilation
Conditional compilation lets the PL/SQL compiler include or exclude parts of your source before it compiles — controlled by directives that start with $. The excluded code never becomes part of the compiled unit, so there is zero runtime cost. It is Oracle's mechanism for version-specific code, toggle-able debug instrumentation, and feature flags.
Selection Directives: $IF … $THEN … $END
The core construct chooses which code to compile based on a static (compile-time) boolean expression:
CREATE OR REPLACE PROCEDURE do_work IS
BEGIN
$IF $$debug_on $THEN
DBMS_OUTPUT.PUT_LINE('DEBUG: entering do_work at ' || SYSTIMESTAMP);
$END
-- ... real work ...
NULL;
END do_work;
/
A selection directive can also have $ELSIF and $ELSE branches. The condition must be a static expression — literals, PLS_INTEGER/BOOLEAN compile-time constants, and inquiry directives only. It cannot reference variables, columns, or functions evaluated at runtime.
Inquiry Directives ($$name)
Inquiry directives, written $$name, supply compile-time values. Some are predefined; others you define yourself through the PLSQL_CCFLAGS parameter.
-- Define custom flags for this session (name:value pairs)
ALTER SESSION SET PLSQL_CCFLAGS = 'debug_on:TRUE, trace_level:2';
CREATE OR REPLACE PROCEDURE process_order(p_id IN NUMBER) IS
BEGIN
$IF $$trace_level >= 2 $THEN
DBMS_OUTPUT.PUT_LINE('TRACE: process_order(' || p_id || ')');
$END
NULL;
END process_order;
/
Predefined Inquiry Directives
| Directive | Compile-time value |
|---|---|
$$PLSQL_LINE |
The current source line number (a PLS_INTEGER) |
$$PLSQL_UNIT |
The name of the current unit (empty string for an anonymous block) |
$$PLSQL_UNIT_OWNER |
The owner of the current unit (12c+) |
$$PLSQL_UNIT_TYPE |
The unit type, e.g. PROCEDURE, PACKAGE BODY (12c+) |
BEGIN
DBMS_OUTPUT.PUT_LINE('Compiled from unit ' || $$PLSQL_UNIT ||
', line ' || $$PLSQL_LINE);
END;
/
Version-Specific Code with DBMS_DB_VERSION
The built-in DBMS_DB_VERSION package exposes the database version as compile-time constants, so one source file can compile optimally on different Oracle releases:
CREATE OR REPLACE FUNCTION fast_concat(p_list IN SYS.ODCIVARCHAR2LIST)
RETURN VARCHAR2 IS
v_result VARCHAR2(32767);
BEGIN
$IF DBMS_DB_VERSION.VER_LE_11 $THEN
-- Older releases: manual loop
FOR i IN 1 .. p_list.COUNT LOOP
v_result := v_result || p_list(i);
END LOOP;
$ELSE
-- 12c+: use the newer, faster built-in path
v_result := SYS.LISTAGG_helper(p_list); -- illustrative
$END
RETURN v_result;
END fast_concat;
/
DBMS_DB_VERSION provides VERSION and RELEASE integers plus a family of boolean constants (VER_LE_11, VER_LE_12, VER_LE_18, VER_LE_19, VER_LE_21, …) that are TRUE/FALSE at compile time.
The $ERROR Directive
$ERROR … $END forces a compile-time error with a custom message — useful to reject an unsupported configuration or platform:
$IF DBMS_DB_VERSION.VER_LE_10 $THEN
$ERROR 'This package requires Oracle 11g or later.' $END
$END
Seeing the Post-Processed Source
Because directives change what actually compiles, use DBMS_PREPROCESSOR to view the source after the directives are resolved — invaluable for debugging:
BEGIN
DBMS_PREPROCESSOR.PRINT_POST_PROCESSED_SOURCE(
object_type => 'PROCEDURE',
schema_name => USER,
object_name => 'PROCESS_ORDER'
);
END;
/
PLSQL_CCFLAGS = 'debug_on:FALSE' and the debug lines vanish from the compiled unit — no IF checks, no overhead — then recompile with debug_on:TRUE to bring them back while diagnosing an issue.
PLSQL_CCFLAGS does not retroactively affect already-compiled units. You must recompile (ALTER … COMPILE) for new flag values to take effect. The flags a unit was compiled with are recorded in USER_PLSQL_OBJECT_SETTINGS.
Summary
- Conditional compilation selects code at compile time with
$IF / $ELSIF / $ELSE / $END— excluded code has zero runtime cost. - Conditions must be static expressions (literals, compile-time constants, inquiry directives).
- Inquiry directives
$$namecome fromPLSQL_CCFLAGS(custom) or are predefined ($$PLSQL_LINE,$$PLSQL_UNIT, …). DBMS_DB_VERSIONconstants enable one source file to compile version-specific code paths.$ERROR … $ENDraises a deliberate compile-time error.DBMS_PREPROCESSOR.PRINT_POST_PROCESSED_SOURCEshows the source after directives are applied.- Recompile a unit for changed
PLSQL_CCFLAGSto take effect; settings are recorded inUSER_PLSQL_OBJECT_SETTINGS.