Chinaunix首页 | 论坛 | 博客
  • 博客访问: 92177473
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类: Oracle

2008-04-20 21:28:58

作者 :    文章来源:       

 

  PL/SQL 中的条件编译:一次编写,多次执行

  你们中很多人曾经使用过 C 语言,它支持编译器指令的概念。在 C 程序中,根据相关编译器的版本,特定变量的值有可能不同。

  在 Oracle 数据库 10g 第 2 版中,PL/SQL 有一个类似的特性:现在可以提供预处理器指令,它们在编译期间而不是在运行时进行求值。例如,让我们创建一个非常简单的返回字符串的函数。

1 create or replace function myfunc
2 return varchar2
3 as
4 begin
5 $if $$ppval $then
6 return 'PPVAL was TRUE';
7 $else
8 return 'PPVAL was FALSE';
9 $end
10* end;

  注意第 5 行,您已经使用预处理器指令为变量 ppval 求值。因为 ppval 是一个预处理器变量,而不是常规的 PL/SQL 变量,所以使用 $$ 标志来指定它。同样,为了编译器能分辨自己只需在编译期间处理这些行,你要用特殊的 $ 标志来指定求值项,例如用 $if 代替 if。现在,利用变量 ppval 的不同值来编译这个函数。

SQL> alter session set plsql_ccflags = 'PPVAL:TRUE';

Session altered.

  现在编译该函数并执行它。

SQL> alter function myfunc compile;

Function altered.

SQL> select myfunc from dual;

MYFUNC
-------------------------------------
PPVAL was TRUE

  在编译期间 ppval 的值被设为 false。现在更改该变量的值并重新执行该函数。

SQL> alter session set plsql_ccflags = 'PPVAL:FALSE';

Session altered.

SQL> select myfunc from dual;

MYFUNC
---------------------------------------------------------
PPVAL was TRUE

  虽然这里 ppval 的值在会话中是 FALSE,但函数没有采用它;而是采用了在编译期间所设置的值。现在,重新编译该函数并执行它。
SQL> alter function myfunc compile;

Function altered.

SQL> select myfunc from dual;

MYFUNC
---------------------------------------------------
PPVAL was FALSE

  在编译期间,ppval 的值是 FALSE,而这就是所返回的值。

  那么您如何利用这个特性呢?有几种可能性 — 例如,您可以将它用作一个调试标志来显示更多的消息,或者可以编写一个程序,这个程序在各个平台上进行不同的编译。因为求值是在编译期间而不是在运行时间内完成的,运行时效率得到显著增强。

  当您拥有相同的预处理器标志(在所有将要编译的函数中引用该标志)时,以上示例运行正常。但是如果您的每段代码具有不同的标志,情况会怎样?例如,函数 calculate_interest 可能将标志 ACTIVE_STATUS_ONLY 设为 TRUE,而函数 apply_interest 可能将标志 FOREIGN_ACCOUNTS 设为 FALSE。为了利用相应的标志来编译这些函数,您可以执行:

alter function calculate_interest compile
plsql_ccflags = 'ACTIVE_STATUS_ONLY:TRUE'
reuse settings;
alter function apply_interest compile
plsql_ccflags = FOREIGN_ACCOUNTS:TRUE'
reuse settings;

  注意,这些设置都不是会话级的。子句 reuse settings 确保在以后重新编译函数时使用相同的编译器指令。

  让我们来看这个新特性的另一个变体。除了条件变量的定义之外,您还可以在条件编译中检查程序包的静态常量。例如,假设您希望基于一个布尔型打包常数来控制 PL/SQL 过程的调试输出。首先创建程序包:

create or replace package debug_pkg
is
debug_flag constant boolean := FALSE;
end;

  debug_flag 是在代码中确定条件逻辑的常数。现在您可以将代码嵌入程序包,如下所示:

create or replace procedure myproc
as
begin
$if debug_pkg.debug_flag $then
dbms_output.put_line ('Debug=T');
$else
dbms_output.put_line ('Debug=F');
$end
end;

  注意,打包的常量被直接引用,没有任何 $ 符号。在本案例中,不需要设置任何会话级或系统级的条件编译参数。在编译函数时,您也不需要传递任何额外的子句。要了解具体的工作过程,可执行:

SQL> exec myproc

Debug=F

  因为现在 debug_pkg.debug_flag 的值是 FALSE,所以执行该过程返回了预期的“F”。现在,更改常数值:

create or replace package debug_pkg
is
debug_flag constant boolean := TRUE;
end;

  然后再次执行该过程:

SQL> exec myproc

Debug=T

  该过程获该常量的值,即预期的“T”。注意这里有一个非常重要的区别 — 您不需要重新编译过程;将自动获取对常量的更改!
       
  无限制的 DBMS 输出

  还记得类似以下各行的令人讨厌的错误吗?

ERROR at line 1:
ORA-20000:ORU-10027:buffer overflow, limit of 1000000 bytes
ORA-06512:at "SYS.DBMS_OUTPUT", line 32
ORA-06512:at "SYS.DBMS_OUTPUT", line 97
ORA-06512:at "SYS.DBMS_OUTPUT", line 112
ORA-06512:at line 2

  这是由于供应程序包 dbms_output 过去能够处理的最大字符数量是 1 百万字节。在 Oracle 数据库 10g 第 2 版中,该限制已经解除:现在最大输出数量是不封顶的。您只需通过执行以下命令,就可以将其设为“unlimited”
set serveroutput on

  以上语句的输出结果如下:

SQL> show serveroutput
serveroutput ON size 2000 format WORD_WRAPPED

  注意输出的最大默认值过去是 2000 。在 Oracle 数据库 10g 第 2 版中,该命令显示以下结果:

SQL> show serveroutput
serveroutput ON SIZE UNLIMITED FORMAT WORD_WRAPPED

  默认值是 UNLIMITED。

  老版本的另一个不便之处是 dbms_output 所显示的行的最大长度。以下是行的长度超过 255 字节时的一个典型错误消息。

ERROR at line 1:
ORA-20000:ORU-10028:line length overflow, limit of 255 chars per line
ORA-06512:at "SYS.DBMS_OUTPUT", line 35
ORA-06512:at "SYS.DBMS_OUTPUT", line 115
ORA-06512:at line 2

  在 Oracle 数据库 10g 第 2 版中,行可以具有任意长度。
阅读(321) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~