在条件编译指令中使用程序包常量为通过单一机制控制一个多个 PL/SQL 编译单元提供了一种方法。例如,假设应用程序由许多 PL/SQL 编译单元组成。在该应用程序内,已嵌入了执行调试或跟踪的 ed 方法。这些方法可以通过使用程序包常量的条件编译指令启用。因此,可以通过随时重新编译该程序包来更改该常量的值。在重新编译程序包时,所有的相关对象都将自动重新编译,以接受该程序包常量的新值。这可以用于在整个应用程序中启用跟踪和调试功能。在进行跟踪和调试时,利用保护跟踪和调试代码的新常量值重新编译程序包规范。这将使所有相关 PL/SQL 单元无效,以便下一次使用时,将不会选中跟踪和调试代码进行编译。程序包常量的使用是一种控制所有相关 PL/SQL 单元的有效机制,这些单元在选择指令内使用打包常量进行条件处理。以下示例演示了这一用法。
打开一个终端窗口,执行以下命令:
cd\wkdir
sqlplus hr/hr
创建程序包 STATIC_CONSTANTS 以声明可用于条件编译的程序包常量。从 SQL*Plus 会话中,执行以下脚本:
@static_constants
static_constants.sql 脚本包含下内容:
CREATE OR REPLACE PACKAGE static_constants is
debug CONSTANT BOOLEAN := FALSE;
trace CONSTANT BOOLEAN := FALSE;
END ;
/
创建两个过程:CHECK_DEBUG(用于检查程序包常量调试的值是否是 TRUE)和 CHECK_TRACE(用于检查程序包跟踪的值是否是 TRUE)。从 SQL*Plus 会话中,执行以下脚本:
@debug_trc
debug_trc.sql 脚本包含以下内容:
CREATE OR REPLACE PROCEDURE check_Debug IS
BEGIN
$IF static_constants.debug $THEN DBMS_OUTPUT.put_line('Debugging ON');
$ELSE DBMS_OUTPUT.put_line('Debugging OFF'); $END
END;
/
CREATE or REPLACE PROCEDURE Check_trace IS
BEGIN
$IF static_constants.trace $THEN DBMS_OUTPUT.put_line('Tracing ON');
$ELSE DBMS_OUTPUT.put_line('Tracing OFF'); $END
END;
/
Set serveroutput on 使用的是 Oracle 数据库 10g 第 2 版中提供的新 SIZE UNLIMITED 语法。现在执行这两个过程。您将看到它显示跟踪和调试均被关闭。
注意:可以将每一行单独地复制到 sqlplus 中,但不要一起复制这 3 个语句。
set serveroutput on size unlimited
exec check_debug
exec check_trace
现在,再次执行这两个过程。您将看到调试和跟踪自动启用了。在重新编译程序包时,所有相关的对象都变为无效,并在下一次执行时重新编译。因此,程序包常量的新值可即刻适用于所有相关对象。
exec check_debug
exec check_trace
这可以扩展至任意数量的相关程序。在需要通过单一机制控制大量程序时,使用这个方法最为有效。用例的其他示例包括针对同一应用程序按州更改赋税,或根据许可选项更改软件特性等等。
DBMS_PREPROCESSOR 子程序会在处理条件编译指令后,打印或检索 PL/SQL 单元的处理后源文本。这个处理后文本是用于编译有效 PL/SQL 单元的实际源。执行以下步骤:
执行以下命令,查看用于编译有效 PL/SQL 程序的实际源代码:
EXEC DBMS_PREPROCESSOR.PRINT_POST_PROCESSED_SOURCE('PROCEDURE', 'HR', 'CHECK_UNIQUE');
请注意,已删除了所有条件编译指令。
Oracle 数据库 10g 引入了 BINARY_DOUBLE 数据类型,该数据类型可用于算法密集的操作。本例中,将对 BINARY_DOUBLE 数据类型与 NUMBER 数据类型进行比较。需要在两个不同版本中创建同样的代码,一个使用 NUMBER,另一个使用 BINARY_DOUBLE。然后,可将两个版本包含在同一过程中,以使用 PLSQL_CCFLAGS 进行测试。执行以下步骤:
启用 ALTER SESSION 以设置标记,从而在两个版本之间进行选择。首先,选择使用 NUMBER 数据类型。从 SQL*Plus 会话中,执行以下命令:
ALTER SESSION SET PLSQL_CCFLAGS = ' numversion:TRUE';
您希望知道哪个代码执行速度更快。创建一个 CALC_CIRCLE 过程计算给定半径的圆的周长和面积。从 SQL*Plus 会话中,执行以下脚本:
@num_bdbl
num_bdbl.sql 脚本包含以下内容:
CREATE or REPLACE PROCEDURE Calc_circle( RADIUS $IF $$NUMVERSION $THEN NUMBER
$ELSE BINARY_DOUBLE $END)
as
SUBTYPE my_real IS
$IF $$numversion $THEN
NUMBER;
$ELSE
BINARY_DOUBLE;
$END
num_circ my_real;
num_area my_real;
BDBL_circ my_real;
BDBL_AREA my_real;
BEGIN
num_CIRC:= (3.14016408289008292431940027343666863227 * 2 * RADIUS);
NUM_AREA := (3.14016408289008292431940027343666863227*radius*radius);
DBMS_OUTPUT.PUT_LINE('The circumference is: '||num_circ);
DBMS_OUTPUT.PUT_LINE('The area is: '||num_area);
END ;
/
使用 ALTER COMPILE 命令将 $$numversion 的值更改为 FALSE 来编译 CALC_CIRCLE,并使用相同的参数再次执行 CALC_CIRCLE。
ALTER PROCEDURE calc_circle COMPILE plsql_ccflags = 'numversion :false' REUSE SETTINGS;
exec calc_circle(1234567890)
set timing off
您可以看出二者性能间的差异。本例阐明了可以使用条件编译在相同程序内有选择地测试两个版本的代码。