Oracle在后面的块中使用第一个块的异常处理程序

时间:2017-12-07 23:17:21

标签: oracle plsql flyway

我遇到了一种行为,我试图在Flyway脚本和Oracle中使用特定于案例的异常处理程序来处理几个Oracle PL / SQL块,显然与其记录的异常处理程序的作用域相矛盾,发送第一个块的异常处理程序的所有异常。例如,在此代码中:

begin

  begin
    execute immediate '
create table "test" (
  "id" number not null,
  "name" varchar2(100) not null,
  constraint "test_pk" primary key ("id")
)
';
  exception
  when others then
    if sqlcode != -955 then raise; end if;
  end;

  begin
    execute immediate 'fail to create index "test_name_idx" on "test" ("name")';
  exception
  when others then
    if sqlcode != -6512 then raise; end if;
  end;

end;

未捕获ORA-06512异常,引发的异常标记为第13行。

将积木包裹在更多区块中并没有帮助。

这里发生了什么?我该如何阻止这种情况发生?

1 个答案:

答案 0 :(得分:3)

这似乎是一个错误,到目前为止已经在11.2.0.4,12.1.0.2和12.2.0.1中重现了。它似乎不需要DDL,或第一个子块中的任何实际操作(虽然只是作为占位符执行null;不会触发它,可能是因为编译器删除它),但它似乎似乎需要两个异常处理程序中的if

begin
  begin
    dbms_output.put_line('Dummy message');
  exception
    when others then
      dbms_output.put_line('In first exception handler');
      if 1=1 then
        raise;
      end if;
  end;

  begin
    execute immediate 'invalid';
  exception
    when others then
      dbms_output.put_line('In second exception handler');
      if 1=1 then
        raise;
      end if;
  end;
end;
/

Dummy message
In second exception handler

ORA-00900: invalid SQL statement
ORA-06512: at line 8
ORA-06512: at line 13

与您的示例一样,第13行抛出异常,因此应在第18行报告为(重新);但据报道它是从第8行报出的,这是没有意义的。 (at line 13消息仅显示在12.2中;在11.2和12.1中它仅报告第一个ORA-06512,这更令人困惑。至少在12 2中你有一些线索问题确实存在。)< / p>

从调试中你可以看到它实际上并没有使用第一个异常处理程序,它确实进入第二个异常处理程序。它“似乎”只是报告错误的行号,而不是执行错误的代码。

异常处理部分,似乎在if之前,在raise之前以某种方式修复事情 - 进行实际工作;这会在第一个中添加一条消息,无法访问:

begin
  begin
    dbms_output.put_line('Dummy message');
  exception
    when others then
      dbms_output.put_line('In first exception handler');
      if 1=1 then
        dbms_output.put_line('This avoids the bug somehow');
        raise;
      end if;
  end;

  begin
    execute immediate 'invalid';
  exception
    when others then
      dbms_output.put_line('In second exception handler');
      if 1=1 then
        raise;
      end if;
  end;
end;
/

Dummy message
In second exception handler

ORA-00900: invalid SQL statement
ORA-06512: at line 19
ORA-06512: at line 14

这是第二个:

begin
  begin
    dbms_output.put_line('Dummy message');
  exception
    when others then
      dbms_output.put_line('In first exception handler');
      if 1=1 then
        raise;
      end if;
  end;

  begin
    execute immediate 'invalid';
  exception
    when others then
      dbms_output.put_line('In second exception handler');
      if 1=1 then
        dbms_output.put_line('This avoids the bug somehow');
        raise;
      end if;
  end;
end;
/

Dummy message
In second exception handler

ORA-00900: invalid SQL statement
ORA-06512: at line 19
ORA-06512: at line 13

在这两种情况下,报告的行号现在都是正确的。不知。

它不必是dbms_output调用,任何似乎都可以工作,例如虚拟过程调用或查询,甚至是额外的子块(例如begin execute immediate 'select * from dual'; end;,即使查询未执行,因为没有into ...)。再次使用null;不起作用。

这有点难看但是给你一种方法来阻止它发生至少,有点像。

这显然是奇怪的,意外的和不一致的行为,并且已经存在了一段时间,因此它可能应该通过My Oracle Support作为服务请求引发。我看不到任何现有的报道,但我看起来并不那么努力,所以可能有一个潜伏在某个地方。