Oracle11g oracle11-sqlplus-在出错时回滚整个脚本-如何?

Oracle11g oracle11-sqlplus-在出错时回滚整个脚本-如何?,oracle11g,sqlplus,rollback,Oracle11g,Sqlplus,Rollback,如何使Oracle 11g在包含的SQL文件中出现任何错误时回滚整个事务 文件内容包括: set autocommit off whenever SQLERROR EXIT ROLLBACK insert into a values (1); insert into a values (2); drop index PK_NOT_EXIST; commit; 并使用“@”将文件包含到sqlplus会话中: 正如预期的那样,sqlplus会话终止,输出也将停止 SQL> @error

如何使Oracle 11g在包含的SQL文件中出现任何错误时回滚整个事务

文件内容包括:

set autocommit off
whenever SQLERROR EXIT ROLLBACK

insert into a values (1);
insert into a values (2);

drop index PK_NOT_EXIST;

commit;
并使用“@”将文件包含到sqlplus会话中:

正如预期的那样,sqlplus会话终止,输出也将停止

SQL> @error.sql
1 row created.
1 row created.
drop index PK_NOT_EXIST           *
ERROR at line 1:
ORA-01418: specified index does not exist
Disconnected from Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
但是当我重新启动sqlplus时,表a包含2条记录,这意味着在sqlplus退出时有一个提交,而不是回滚

我是否可以强制sqlplus执行以下操作:

  • 出现错误时停止处理文件
  • 并在出错时回滚整个事务

  • 我解决了这个问题,并将解决方案发回,以防有人遇到这样的问题

    如果我没有在脚本中放入DDL命令,那么回滚将正确执行

    所以剧本:

    set autocommit off
    whenever SQLERROR EXIT ROLLBACK
    
    insert into a values (1);
    insert into a values (2);
    
    insert into a values ('x');
    
    commit;
    
    工作


    如果使用DDL,则通常Oracle不提供回滚功能。

    DDL在运行前和运行后执行提交,这样即使DDL失败,Oracle也会提交事务

    您可以通过以下方式解决此问题:

    set autocommit off
    whenever SQLERROR EXIT ROLLBACK
    
    
    declare
      procedure drop_idx(i varchar2)  
      is
        pragma autonomous_transaction; -- this runs in its own transaction.
      begin
        execute immediate 'drop index ' || i;
      end;
    begin
      insert into a values (1);
      insert into a values (2);
      drop_idx('PK_NOT_EXIST');
    end;
    /
    

    谢谢问题是成功的DDL无论如何都会被提交。所以我无论如何都会得到它。似乎应用这样一个脚本的唯一方法是一步一步地执行,在出现错误时停止,然后在修复后从失败的地方继续。为了确认,我刚刚在12c上测试了一个案例,其中包含一些DDL,后面是DML。如果执行
    ddl_语句;dml_声明_1;dml_声明_2
    如果dmlstatement_2中有错误,那么它将提交(当然)
    ddl_语句
    ,但回滚
    dml_语句_1
    dml_语句_2
    。(这对于我们的案例来说是可以接受的。)
    set autocommit off
    whenever SQLERROR EXIT ROLLBACK
    
    
    declare
      procedure drop_idx(i varchar2)  
      is
        pragma autonomous_transaction; -- this runs in its own transaction.
      begin
        execute immediate 'drop index ' || i;
      end;
    begin
      insert into a values (1);
      insert into a values (2);
      drop_idx('PK_NOT_EXIST');
    end;
    /