预处理器指令

指令由指令控制标记“$”和普通的 PL/SQL

文本组成。条件编译使用三个指令:选择、查询和错误。特殊的触发器字符“$”代表条件编译指令。选择指令是条件编译机制的重要组成部分,而查询和错误指令支持有用的附加功能。

选择指令

选择指令对条件编译表达式进行评估,并根据评估的结果选择要包含在该编译中的代码。完全忽略未选中的代码。这不会干扰到现有程序,因为这些程序并未使用条件编译。条件选择指令以

$if 开始并使用常规语法:

$if $then? $elsif $then? …$else? $end

其中, 表示静态布尔表达式。静态布尔表达式是一个或多个程序包常量或一个或多个查询指令的任意组合。以下是选择指令将程序包常量用作静态布尔表达式的示例:

$if Trace_Pkg.Trace > 2 $then ?$end

其中,Trace_pkg 是程序包的名称,Trace

是声明为 PLS_INTEGER 的常量。请注意,如果 PL/SQL 编译单元 U 内的选择指令中使用了在程序包

Trace_pkg 内声明的常量,那么,U 将在 Trace_pkg 上具有一个依赖项,就好像

Trace_pkg 已经在常规 PL/SQL 代码中进行了引用。

查询指令允许访问编译环境,以便将选择基于当前环境。查询指令的形式为 $$ 开头,例如:

$if $$debug_level > 3 $then … $end

标识符 debug_level 是使用

plsql_ccflags 初始化参数(Oracle 数据库 10g 第 2

版中的新增内容)定义的,因此:

...plsql_ccflags =

'debug_level:4, ...'

错误指令

错误指令的形式如下所示

$error $end。

它可以使编译器报告编译错误,包括 VARCHAR2 表达式中提供的消息。

Oracle 数据库 10g 第 2

版提供了以下可以在条件查询指令中使用的 PL/SQL 编译器参数:

PLSQL_CCFLAGS

PLSQL_DEBUG

PLSQL_OPTIMIZE_LEVEL

PLSQL_CODE_TYPE

PLSQL_WARNINGS

NLS_LENGTH_SEMANTICS

编译时,PL/SQL 编译器参数的值存储在编译单元中,并可以使用

all_plsql_object_settings 系列视图进行查看。此外,还提供了预定义的查询指令

$$PLSQL_UNIT, $$PLSQL_LINE。有关条件编译指令语法的详细信息,请参阅 PL/SQL

用户指南和参考 手册。

使用指令

示例 1:使用程序包常量进行跟踪和调试

在条件编译指令中使用程序包常量为通过单一机制控制一个或多个 PL/SQL

编译单元提供了一种方法。例如,假设应用程序由许多 PL/SQL 编译单元组成。在该应用程序内,已嵌入了执行调试或跟踪的

ed

方法。这些方法可以通过使用程序包常量的条件编译指令启用。因此,可以通过随时重新编译该程序包来更改该常量的值。在重新编译程序包时,所有的相关对象都将自动重新编译,以接受该程序包常量的新值。这可以用于在整个应用程序中启用跟踪和调试功能。在进行跟踪和调试时,利用保护跟踪和调试代码的新常量值重新编译程序包规范。这将使所有相关

PL/SQL 单元无效,以便下一次使用时,将不会选中跟踪和调试代码进行编译。程序包常量的使用是一种控制所有相关 PL/SQL

单元的有效机制,这些单元在选择指令内使用打包常量进行条件处理。以下示例演示了这一用法。

1.

打开一个终端窗口,执行以下命令:

cd /home/oracle/wkdir

sqlplus hr/hr

2.

创建程序包 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 ;

/

3.

创建两个过程: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;

/

4.

Set serveroutput on using the

new SIZE UNLIMITED

syntax available in Oracle Database 10g Release 2. Now execute both

the procedures.您将看到它显示跟踪和调试均被关闭。

注意:可以将每一行单独地复制到 sqlplus 中,但不要一起复制这 3 个语句。

set serveroutput on size unlimited

exec check_debug

exec check_trace

5.

现在,将更改程序包常量的值。从 SQL*Plus 会话中,执行以下脚本:

@reset_const

reset_const.sql

脚本包含以下内容:

CREATE OR REPLACE PACKAGE static_constants is

debug CONSTANT BOOLEAN := TRUE;

trace CONSTANT BOOLEAN := TRUE;

END ;

/

6.

现在,再次执行这两个过程。您将看到调试和跟踪自动启用了。在重新编译程序包时,所有相关的对象都变为无效,并在下一次执行时重新编译。因此,程序包常量的新值可即刻适用于所有相关对象。

exec check_debug

exec check_trace

这可以扩展至任意数量的相关程序。在需要通过单一机制控制大量程序时,使用这个方法最为有效。用例的其他示例包括针对同一应用程序按州更改赋税,或根据许可选项更改软件特性等等。

通过设置 ALTER COMPILE

命令只影响正在编译的程序。利用 CREATE or REPLACE

重新编译这些程序,GET_RECORD 的过程,以接受

employee_id 的值,并显示相应的记录。为了保持良好的编程实践,该过程将调用

请注意,已删除了所有条件编译指令。

2.

创建 SEND_MESSAGE_TO_DBA

和 CHECK_UNIQUE

过程。CHECK_UNIQUE

过程包含两个不同的代码段,一个用于开发中的测试,另一个部署在最终生产环境中。开发代码使用条件编译指令,而生产代码使用传统的

IF-THEN-ELSE 逻辑检查重复的记录。从

SQL*Plus 会话中,执行以下脚本:

@dba_email

@chk_unq

show errors

dba_email.sql

脚本包含以下内容:

CREATE OR REPLACE PROCEDURE send_message_to_DBA(emp_id number)

IS

mailhost VARCHAR2(64) := 'mailhost.fictional-domain.com';

sender VARCHAR2(64) := 'HR_APP@fictional-domain.com';

recipient VARCHAR2(64) := 'DBA@fictional-domain.com';

mail_conn utl_smtp.connection;

BEGIN

mail_conn := utl_smtp.open_connection(mailhost, 25);

utl_smtp.helo(mail_conn, mailhost);

utl_smtp.mail(mail_conn, sender);

utl_smtp.rcpt(mail_conn, recipient);

-- open_data(), write_data(), and close_data() into a single call to data().

utl_smtp.open_data(mail_conn);

utl_smtp.write_data(mail_conn, 'A primary key violation has occured for record '||

emp_id || 'in the EMPLOYEES table.This is an automatically generated e-mail

message.Please do not respond to this, this is an alert.'|| chr(13));

utl_smtp.write_data(mail_conn, 'This is line 2.'|| chr(13));

utl_smtp.close_data(mail_conn);

utl_smtp.quit(mail_conn);

EXCEPTION

WHEN OTHERS THEN

NULL;

END;

/

chk_unq.sql

脚本包含以下内容:

Create or replace Procedure check_unique(emp_id NUMBER) is

v_num number;

force_pk_violation exception;

Begin

Select count(*) into v_num from employees where employee_id = emp_id;

-- production code

If v_num > 1

then SEND_MESSAGE_TO_DBA(emp_id);

raise force_pk_violation;

END IF ;

-- Development code

$if $$FORCE

$then SEND_MESSAGE_TO_DBA(emp_id);

raise force_pk_violation;

$end

END;

/

3.

现在,更改会话将 $$force 的值设为

FALSE。从 SQL*Plus 执行以下命令。

ALTER SESSION SET

PLSQL_CCFLAGS='force:FALSE';

4.

现在,再次执行 chk_unq.sql。

因为变量 $$force 现在的值是

FALSE,所以没有出现警告;

5.

创建 GET_RECORD 过程。该过程接受

employee id 并返回员工记录。如果 CHECK_UNIQUE

过程检查出存在重复记录,则会显示一个友好消息。从 SQL*Plus 会话执行以下脚本:

@get_record

get_record.sql

脚本包含以下内容:

Create or replace procedure get_record(emp_id IN NUMBER)

as

emp_record employees%rowtype;

Begin

check_unique(emp_id);

Select * into emp_record from employees where employee_id =emp_id;

Dbms_output.put_line ( 'Name:'|| emp_record.first_name||'

'||emp_record.last_name||' '||'Hiredate:

' ||emp_record.hire_date||'

'||'Job:'||' '||emp_record.job_id);

Exception

When others then

DBMS_OUTPUT.PUT_LINE('We are unable to process your request at this time.

Please try again later.We apologize for any inconvenience');

End;

/

6.

现在,执行 GET_RECORD 过程,传入

100 作为参数。

exec GET_RECORD(100)

因为没有重复记录,所以该过程成功执行。

7.

现在,测试是否在出现重复记录时显示消息。更改会话将 $$force 的值设为

TRUE,并再次执行 GET_RECORD。从 SQL*Plus 会话执行以下命令:

ALTER SESSION SET PLSQL_CCFLAGS='force:TRUE';exec GET_RECORD(100)

由于未重新编译该过程,因此它不会受到影响。

8.

使用 ALTER...COMPILE 语句重新编译

CHECK_UNIQUE 过程,并为

PLSQL_CCFLAGS 参数提供新值。使用

REUSE SETTINGS

选项。然后,以值 100 再次执行 GET_RECORD。从 SQL*Plus 会话执行以下命令。

ALTER PROCEDURE CHECK_UNIQUE compile

plsql_ccflags = 'force:TRUE' REUSE SETTINGS;

exec GET_RECORD(100)

现在,PLSQL_CCFLAGS

值生效,因而程序发出消息。该方法可以用于影响会话内的特定程序,比如后生产调试。然而,每个需要新设置的程序都必须使用

CREATE OR REPLACE 或

ALTER...COMPILE 语句进行重新编译。

示例 3:使用 DBMS_PREPROCESSOR 过程打印或检索源文本

DBMS_PREPROCESSOR

子程序会在处理条件编译指令后,打印或检索 PL/SQL 单元的处理后源文本。这个处理后文本是用于编译有效 PL/SQL

单元的实际源。执行以下步骤:

1.

Execute the following command to see

the actual source code used to compile a valid PL/SQL

program:

EXEC DBMS_PREPROCESSOR.PRINT_POST_PROCESSED_SOURCE('PROCEDURE', 'HR', 'CHECK_UNIQUE');

请注意,已删除了所有条件编译指令。

示例

4:使用条件编译分支代码确定最佳性能版本

Oracle 数据库 10g 引入了 BINARY_DOUBLE 数据类型,该数据类型可用于算法密集的操作。本例中,将对

BINARY_DOUBLE 数据类型与 NUMBER 数据类型进行比较。需要在两个不同版本中创建同样的代码,一个使用

NUMBER,另一个使用 BINARY_DOUBLE。然后,可将两个版本包含在同一过程中,以使用 PLSQL_CCFLAGS 进行测试。执行以下步骤:

1.

启用 ALTER SESSION

以设置标记,从而在两个版本之间进行选择。首先,选择使用 NUMBER 数据类型。从 SQL*Plus 会话中,执行以下命令:

ALTER SESSION SET

PLSQL_CCFLAGS = ' numversion:TRUE';

2.

您希望知道哪个代码执行速度更快。创建一个 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 ;

/

3.

执行 CALC_CIRCLE 过程,使用数字 1234567890 作为半径

set timing on

exec calc_circle(1234567890)

4.

使用 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

您可以看出二者性能间的差异。本例阐明了可以使用条件编译在相同程序内有选择地测试两个版本的代码。

示例 5:将条件编译与不同的 Oracle

数据库版本结合使用

以下示例演示了 DBMS_DB_VERSION

常量与条件编译的结合使用。其中对 Oracle 数据库版本和发布均进行了检查。这个 CHECK_VERSIONS 过程使用

COMMIT WRITE IMMEDIATE NOWAIT 命令(已在 Oracle 数据库 10g 第 2 版中引入)。如果在

Oracle 数据库早期版本中执行该过程,则无法识别该命令。因此,该过程 DBMS_DB_VERSION 程序包检查数据库的版本。 如果返回的版本低于

10.2,那么将使用常规的 COMMIT 提交事务。当在版本为 10.2 或更高版本的数据库中执行该过程时,将使用 COMMIT

WRITE IMMEDIATE NOWAIT 命令完成该事务。

1.

现在可以测试 Oracle 数据库版本了。从终端窗口中执行以下脚本:

@check_version

check_version.sql

脚本包含以下内容:

CREATE OR REPLACE PROCEDURE check_version AS

BEGIN

-- some code which performs transaction processing ...

$if DBMS_DB_VERSION.VER_LE_10_2 $then

-- traditional commit

COMMIT;

DBMS_OUTPUT.PUT_LINE ('The transaction has been successfully committed.');

$else

-- faster COMMIT supported in 10.2

COMMIT WRITE IMMEDIATE NOWAIT;

DBMS_OUTPUT.PUT_LINE ('The transaction has been successfully committed.');

$end

END;

/

2.

现在,在 SQL*Plus 窗口中执行以下命令来运行 check_version

过程。

exec check_version

check_version

的输出说明:无论版本如何,该过程都能成功完成而且对最终用户而言是透明的。因此,没有理由在不同的数据库版本中使用不同的程序单元。

oracle bl编译,使用 PL/SQL 条件编译相关推荐

  1. JAVA_WEB Oracle 10g学习: PL/SQL与Oracle间交互

    一.抽象的角色 抽象是对一个真实世界实体的高级描述或建模.它能排除掉无关的细节内容,使我们的日常生活更有条理.例如,驾驶一辆汽车时,我们是不需要知道它的发动机是如何工作的.由变速排档.方向盘.加速器和 ...

  2. oracle sql循环判断语句怎么写,Oracle 非常详细的 PL/SQL入门教程,PL/SQL语法格式/循环语句/条件判断/异常处理...

    PL/SQL入门教程目录 Oracle PL/SQL入门教程,PL/SQL语法格式/循环语句/条件判断/异常处理 一.PL/SQL简介 1.PL/SQL简介 1.PL/SQl是过程语言PL与结构化语言 ...

  3. Oracle数据库学习:PL/SQL(详解)

    Oracle数据库学习:PL/SQL 什么是PL/SQL PL/SQL 是过程语言(Procedural Language)与结构化查询语言(SQL)结合而成的扩展语言; 使用PL/SQL 可以编写具 ...

  4. oracle - - 注释符,Oracle数据库扩展语言PL/SQL之注释、分隔符和标识符

    点击蓝字关注我吧 [本文详细介绍了Oracle数据库扩展语言PL/SQL的注释.分隔符和标识符,欢迎读者朋友们阅读.转发和收藏!] 1 基本概念 1.1 注释 注释不会被数据库编译,只是给开发人提供一 ...

  5. Oracle安装步骤及PL/SQL Developer连接数据库

    一:Oracle安装步骤及PL/SQL Developer连接数据库 win7 64位 11g 点击(操作步骤):http://www.cnblogs.com/haoke/articles/27343 ...

  6. 也谈Oracle异常: ORA-06502: PL/SQL: 数字或值错误 : 字符串缓冲区太小

    也谈Oracle异常: ORA-06502: PL/SQL: 数字或值错误 : 字符串缓冲区太小 参考文章: (1)也谈Oracle异常: ORA-06502: PL/SQL: 数字或值错误 : 字符 ...

  7. 64位oracle 和64位 PL/SQL 的配置

    64位oracle 和64位 PL/SQL 的配置 现在大公司所使用的大多是oracle和其可视化的PL/SQL,本文将对其配置安装做简短的笔记.网上有许多有许多类似的文章,博主看了许多许多,所以写了 ...

  8. oracle数据库匿名快,pl/sql分匿名块和命名块

    命名块:存储过程,函数,触发器,包等 pl/sql语句块分3部分: (1)声明部分 (2)可执行部分 (3)异常处理部分 其中可执行部分是语句块中唯一要求必须存在的部分,声明部分和异常处理部分是可选的 ...

  9. oracle pl sql面试题,Oracle 面试题库—PL/SQL

    2015-11-21 06:30:02 阅读( 295 ) 1 PL/SQL代表 A  PROCEDURAL LANGUAGE/SQL B  PROGRAM LANGUAGE SQL C  POWER ...

最新文章

  1. 华为,你终于活成了他们害怕的样子
  2. 解决LNMP环境下客户端远程连接不上mysql的问题(已经排除防火墙/selinux问题)...
  3. 知物由学 | 未来安全隐患:AI的软肋——故意欺骗神经网络
  4. 信息系统管理十大知识领域
  5. 学习韩立刚老师IT运维课程,成为韩立刚老师正式学生,在全国范围为你就近推荐工作。...
  6. 浅谈C++类(6)--复制构造函数
  7. 【CF1199 D,E, F】Welfare State // Matching vs Independent Set // Rectangle Painting 1
  8. office2007右键doc,xls
  9. 库函数手册_Linux应用编程(1)系统调用库函数 确定真懂?
  10. h5的table表格边框线问题解决方案
  11. TMC8670 – 集成EtherCAT通讯和FOC伺服运动控制芯片适用2/3相永磁同步电机
  12. PS制作或编辑gif动态图
  13. allegro怎么导出PCB文件里封装
  14. 数据字典的作用是什么,它有哪些条目?
  15. 分享美容护肤门店预约下单小程序开发制作功能介绍
  16. 【基因芯片】差异表达分析的基本原理与方法
  17. 根域名服务器作用,域名系统的主要功能是什么?域名系统中的本地域名服务器、根域名服务器、顶级域名 - 问答库...
  18. w10更新后怎么找计算机全民,Win10系统下全民WiFi不能用了怎么办
  19. 【Gradle】Gradle运行main方法报错:Unnecessarily replacing a task that does not exist is not supported.
  20. android简易计算器的实现

热门文章

  1. size_t和int区别
  2. 线性连续时间状态空间模型的离散化及实例
  3. ATS 4.2.3自定义日志文件格式的方法
  4. 记一次shell脚本推后台stopped的问题
  5. Https的底层原理
  6. PHPMailer类 发送邮件
  7. iOS 相册和网络图片的存取
  8. Linux Shell ssh登录脚本
  9. php 学习笔记 数组1
  10. FilenameFilter的使用