免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1634 | 回复: 0
打印 上一主题 下一主题

原创:异常与事务控制汇总[转] [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-01-28 18:08 |只看该作者 |倒序浏览
author :seao
------------------------------------------------------------------------------------------
在这里详细论证一下异常和事务之间如何控制:在plsql程序设计中与事务有关的对象无外乎就如下3种LSQL(block),procedure,trigger,
1LSQL(block) + Procedure
2LSQL(bolck) + trigger
3LSQL(block) + Procedure or (Function) + trigger
第一步搭建试验环境:
create table test (
  a1 number,
a2 varchar2(20)
);
select * from test;

A1    A2
---------- --------------------

第二步:
1>LSQL(block) + Procedure
a)CREATE OR REPLACE PROCEDURE test_p1(a test.a1%TYPE,b test.a2%TYPE)
IS
BEGIN
INSERT INTO test VALUES(a,b);
raise_application_error('-20001','raise a exception');
END;

BEGIN
INSERT INTO test VALUES(1,'a');
test_p1(2,'b');
END;
结果:存储过程抛出异常给被调用对象(block),该块没有做异常捕捉,则异常抛给(调用其block的环境),即-plsql developer工具,先前的事务(两天insert语句,自动回滚).

b)更改该存储过程如下
CREATE OR REPLACE PROCEDURE test_p1(a test.a1%TYPE,b test.a2%TYPE)
IS
BEGIN
INSERT INTO test VALUES(a,b);
raise_application_error('-20001','raise a exception');
INSERT INTO test VALUES(3,'c');
EXCEPTION  WHEN OTHERS THEN
dbms_output.put_line('handle 2001 exception');
END;

BEGIN
INSERT INTO test VALUES(1,'a');
test_p1(2,'b');
INSERT INTO test VALUES(4,'d');
END;

结果:异常被捕捉,异常前面的事务和plsql块的黄色部分都可有效手动提交.蓝色部分不会执行

C)再次更改如下:
CREATE OR REPLACE PROCEDURE test_p1(a test.a1%TYPE,b test.a2%TYPE)
IS
BEGIN
INSERT INTO test VALUES(a,b);
raise_application_error('-20001','raise a exception');
INSERT INTO test VALUES(3,'c');
END;

BEGIN
INSERT INTO test VALUES(1,'a');
test_p1(2,'b');
INSERT INTO test VALUES(4,'d');-不会运行
EXCEPTION  WHEN OTHERS THEN
dbms_output.put_line('handle 2001 exception');
--commit or rollback;
END;
总结: 如果异常被所在块所捕获处理,CALLING对象程序会继续进行,该事务对先前和以后的DML操作都有效;反之,如果异常没有所在块所捕获处理(由calling对象处理),则calling先前事务是可控制的.



2>LSQL(bolck) + trigger
Create table test2 (num number);
a:
CREATE OR REPLACE TRIGGER test_trigger
AFTER INSERT OR UPDATE OR DELETE ON test
DECLARE
v NUMBER DEFAULT 1;
BEGIN
INSERT INTO test2 VALUES(1);
dbms_output.put_line('trigger is working');
END;

Declare
Insert into test (1,’a’);
End;
说明:建立test表的UML语句级触发器,执行pssql块后,可成功手动提交该事务中的两条insert语句.

b:修改后
CREATE OR REPLACE TRIGGER test_trigger
AFTER INSERT OR UPDATE OR DELETE ON test
DECLARE
v NUMBER DEFAULT 1;
BEGIN
INSERT INTO test2 VALUES(v);
dbms_output.put_line('trigger is working');
raise_application_error('-20002','raise a exception from this trigger'); END;
BEGIN
INSERT INTO test VALUES(1,'a');
END;
说明:只要异常没有被捕捉,则程序将报错,先前执行事务语句,全部由系统自动回滚.

c:再修改
CREATE OR REPLACE TRIGGER test_trigger
AFTER INSERT OR UPDATE OR DELETE ON test
DECLARE
v NUMBER DEFAULT 1;
BEGIN
INSERT INTO test2 VALUES(v);
dbms_output.put_line('trigger is working');
raise_application_error('-200        02','raise a exception from this trigger');
EXCEPTION WHEN OTHERS THEN
dbms_output.put_line('handle it');
END;

BEGIN
INSERT INTO test VALUES(1,'a');
END;
说明:异常被自身所处理,程序可正常运行.事务可成功手动提交.

d:再修改
CREATE OR REPLACE TRIGGER test_trigger
AFTER INSERT OR UPDATE OR DELETE ON test
DECLARE
v NUMBER DEFAULT 1;
BEGIN
INSERT INTO test2 VALUES(v);
dbms_output.put_line('trigger is working');
raise_application_error('-20002','raise a exception from this trigger');
END;

BEGIN
INSERT INTO test VALUES(1,'a');
EXCEPTION WHEN OTHERS THEN
dbms_output.put_line('handle it');
--commit or rollback;
END;
说明:此时即使是”calling”对象作了例外处理,那也无法控制先前的DML事务.
为什么呢?我认为像先前类似这种只要父对象接收处理子对象就可以保证事务的顺利提交-属于calling objet  revoke called object,结构.而触发器这个对象比较特殊,它不属于这种模式.可以这么理解:因为触发器是伴随着DML语句的,触发器的执行失败可视为该DML语句没有执行成功,所以该DML语句不属于该事务.但是其他表的事务控制语句不影响事务控制,我们接着看如下的例子:





e:再修改
CREATE OR REPLACE TRIGGER test_trigger
AFTER INSERT OR UPDATE OR DELETE ON test
BEGIN
raise_application_error('-20002','raise a exception from this trigger');
END;

BEGIN
INSERT INTO test2 VALUES(1);
INSERT INTO test2 VALUES(2);
INSERT INTO test  VALUES(1,'abc');出现异常,该条DML语句应视为无效.
INSERT INTO test2 VALUES(3);既然出现异常,这条语句不会运行.
EXCEPTION WHEN OTHERS THEN
dbms_output.put_line('handle it');
--commit or rollback;  此时事务可控制,但只对非触发器的表有效.
END;




第三种:其实就是一,二的混合.就不再论述了.

如有问题请及时反馈,谢谢!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP