我有一个PL / SQL脚本,它运行一堆命令,并在最后调用commit。
select count(*) into countCol from USER_TAB_COLUMNS where TABLE_NAME = 'EVAPP_CARLETON_RESULT' and COLUMN_NAME = 'AMTFIN' and DATA_SCALE is null;
IF (countCol <> 0) then
execute immediate 'alter table EVAPP_CARLETON_RESULT add AMTFIN_TMP NUMBER(10,2)' ;
execute immediate 'update EVAPP_CARLETON_RESULT set AMTFIN_TMP = AMTFIN' ;
execute immediate 'alter table EVAPP_CARLETON_RESULT drop column AMTFIN' ;
execute immediate 'alter table EVAPP_CARLETON_RESULT rename column AMTFIN_TMP to AMTFIN' ;
DBMS_OUTPUT.put_line('This column EVAPP_CARLETON_RESULT.AMTFIN has been modified to the required precision');
END IF;
logger('68');
evaluate.commitScript;
此前有68个此类块,但最后会调用evaluate.commitScript。
但是,logger在每个这样的块之后被调用,并且它内部有一个commit语句。
create or replace
PROCEDURE LOGGER
(MESSAGE1 IN VARCHAR2 ) AS
pragma autonomous_transaction;
BEGIN
insert into message_log (datetime, message) values (sysdate, message1);
commit;
END LOGGER;
提交同时提交所有更改。不仅仅是程序所做的更改。无论如何,我们可以选择性地调用commit吗?
答案 0 :(得分:7)
看起来你已经在LOGGER proc中使用了这一行的解决方案:
pragma autonomous_transaction
该语句在过程中设置单独的事务。在那里发布的COMMIT不会在该过程之外提交任何事务。
此外,EXECUTE IMMEDIATE语句中的DDL是隐式提交的。
答案 1 :(得分:4)
commit
过程中的LOGGER
只会提交LOGGER
程序调用所做的更改。
如果您发布的代码段代表68个块,则问题是DDL语句(如ALTER TABLE
)隐式发出两个提交 - 一个在执行语句之前,一个在执行之后执行时成功的。这意味着DDL无法以事务方式完成,evaluate.commitScript
调用既不会提交也不会回滚任何更改。
根据Oracle版本,版本和配置的不同,您可以使用Oracle flashback database之类的内容在运行脚本之前创建还原点,并在脚本失败时闪回到该还原点(尽管这也会回滚您LOGGER
程序所做的更改。