今天在问答区看到一个问题是
假如有procedureA、procedureB和procedureC,因为数据依赖关系,需要先执行procedureA,再执行procedureB,再执行procedureC,
于是新建了个procedureTEST,
CREATE OR REPLACE PROCEDURE procedureTEST AS
BEGIN
procedureA();
procedureB();
procedureC();
EXCEPTION WHEN OTHERS THEN
ROLLBACK;
RAISE_APPLICATION_ERROR(-20001, 'PROCEDURE ERROR: ' || SQLERRM);
END;
procedureA、procedureB和procedureC 中都有错误处理,
如果procedureA、procedureB正常执行了,procedureC()报错了,因为procedureTEST是一个事务,整个procedureTEST会回滚;
那么procedureA、procedureB中执行的内容会回滚吗?
然后看到一个AI回答是
当然我也试了下我的AI,它也是告诉我同样的答案
然而我觉得这个答案欠缺考虑,不太敢苟同。也可能是提问者表达的不够详细吧。毕竟我们换一种问法,就是不同结果了,回答还是蛮准确。
因此可以大致理解为,只要在异常之前commit的数据还是会生效的,如果没有commit提交,则会回滚所有事务操作。如果你是来找答案的,那么下边就没必要看了,因为都是一些验证而已。
当然有小可爱看到可能会问 “那人家也没说procedureA,B中有提交事务啊”,那当然你可以认为笔者是在吹毛求疵,但是从这个“因为数据依赖关系,需要先执行procedureA,再执行procedureB,再执行procedureC”我觉得可能是有事务提交的吧,如果没有那咱权当拓展知识,毕竟一百个读者就有一百个哈姆雷特。
我们建三个存过procedureA,procedureB,procedureC,在C中调用A,B,然后B中有错误,创建表A,B都只有一个id,时间字段,用来验证。
create or replace procedure procedureA is
begininsert into a values(1,sysdate);
end procedureA;
create or replace procedure procedureB is
a varchar2(10);
begininsert into B values(1,sysdate);a:=1/0;
end procedureB;
create or replace procedure procedureC is
beginprocedureA;procedureB;EXCEPTION WHEN OTHERS THEN
ROLLBACK;
RAISE_APPLICATION_ERROR(-20001, 'PROCEDURE ERROR: ' || SQLERRM);
end procedureC;
测试下几种不同的情况:A,B全部没有提交语句,A有提交语句,C中在A执行后提交
1、A,B全部没有提交语句。
执行procedureC之后报错,
然后查询A表为空,那自然是全部回滚了
2、A有提交语句,我们改下procedureA,加一个commit语句,这个时候再执行procedureC,虽然也还是报错,但是再次查询A表的时候已经有数据了
create or replace procedure procedureA is
begininsert into a values(1,sysdate);commit;
end procedureA;
3、C中在A执行后提交,将procedureA恢复,A表数据删除,修改procedureC,执行procedureA之后加一个commit提交语句。
create or replace procedure procedureC is
beginprocedureA;commit;procedureB;EXCEPTION WHEN OTHERS THEN
ROLLBACK;
RAISE_APPLICATION_ERROR(-20001, 'PROCEDURE ERROR: ' || SQLERRM);
end procedureC;
执行procedureC,报错之后查询A表,有数据。
问题结论是有了,简单的验证也是没问题的,但是遇到问题,我们还是应该尽量多思考一下,开阔一下自己的思路,不要受AI一成不变的答案影响,千万别让人工智能把你变成人工智障。