Pragma在PL/SQL编程过程中属于预定义命令,预定义的内容包含以下四点
exception_init绑定错误号
serially_reusable继续可重用包
restrict_references定义函数纯度
autonomous_transaction定义程序块为独立事务
1.exception_init
用于在pl/sql程序块中绑定错误号,就是给错误号取个别名
declare
exce exception;
pragma exception_init(exce,-20001);
begin
raise_application_error(-20001,'错误信息');
exception
when exce then
dbms_output.put_line(sqlerrm);
end;
执行结果:
ORA-20001: 错误信息
同时我们也可以看看不使用exception_init时如何来捕获异常的
declare
--exce exception;
--pragma exception_init(exce,-20001);
begin
raise_application_error(-20001,'错误信息');
exception
when others then
if sqlcode=-20001 then
dbms_output.put_line(sqlerrm);
end if;
end;
注:sqlcode返回错误号,如-20001,-123等等
sqlerrm返回详细错误信息,如ORA-20001: 错误信息
2.serially_reusable
将此pl/sql程序包定义为可重用包。
若未定义serially_reusable时,程序包变量在
同一个会话调用时,上一次对变量值的修改将影响到接下来的使用;若加上定义之后,在下个程序块使用包时将重新初始化这个包状态。
还是弄个简单的东东看下效果
先看看没有加serially_reusable时定义
create or replace package test
is
n number:=1;
--pragma serially_reusable;
end test;
create or replace package body test
is
--pragma serially_reusable;
end test;
下面是调用部分
begin
dbms_output.put_line(test.n);
test.n:=10;
dbms_output.put_line(test.n);
end;
begin
dbms_output.put_line(test.n);
end;
输出结果如下
1
10
10
10
10
结果很明显,在同一个会话中调用时,包变量的值在下一个程序块中也是10
然后我们看看加上serially_reusable会怎么样。
create or replace package test
is
n number:=1;
pragma serially_reusable;
end test;
create or replace package body test
is
pragma serially_reusable;
end test;
执行调用代码后结果如下
1
10
1
10
1
注:调用都要在同一个会话中,否则加不加都不会影响到下次的调用。
加了pragma serially_reusable;之后包内的程序块就不能再修改包变量了?这个还不是非常确定
从原理上讲,若没有加时,第一次调用一个包时会在uga(会话专用内存块?)中存在一个包使用缓存保存下包的相应信息;否则就不会将包在块调用之后就即时清除掉包调用信息。
3.autonomous_transaction
将所在子程序块标注为独立事务块,即在此块中执行的事务命令不影响亦不受外部调用块的事务命令影响。
示例代码
create table temp
(des varchar2(100));--创建表
create or replace procedure temp_proc(val varchar2)
is
pragma autonomous_transaction;
begin
insert into temp values(val);
--update temp set des=val;
commit;
--rollback;
end;
begin
insert into temp values('first');
temp_proc('second');
commit;
end;
select * from temp;
drop table temp;
drop procedure temp_proc;
查询结果为
first
second
我们再看另一段代码
create table temp
(des varchar2(100));--创建表
create or replace procedure temp_proc(val varchar2)
is
--pragma autonomous_transaction;
begin
insert into temp values(val);
--update temp set des=val;
commit;
--rollback;
end;
begin
insert into temp values('first');
temp_proc('second');
rollback;
end;
select * from temp;
drop table temp;
drop procedure temp_proc;
结果依然是
first
second
虽然在调用块中使用了rollback命令,但是"first"依然被插入进去了,因为存储过程里的commit语句影响了事务的提交。
注:1.加上pragma autonomous_transaction标识后,本块在begin...end部分要明确使用commit/rollback命令对本块事务进行处理。
2.在代码块中像下面这样调用会报错,求个解决方法。
begin
declare
pragma autonomous_transaction;
begin
--代码
null;
end;
--代码
null;
end;
4.restrict_references
定义函数纯度,因函数的调用位置可能对函数有一定的影响,用于对相应程序块中的PL/SQL语句进行限制。总共分为四个级别
wnds(Writes no database state):函数不修改数据库
rnds (reads no database state)函数不查询数据库表
wnps(writes no package state)函数不改变包变量的值
rnps(reads no package state)函数不引用包变量的值
...
具体的可以参看
oracle 9i pl/sql开发人员指南5.4.2。
若有不对的地方,请指正