如何通过执行立即传播全局定义的异常?

时间:2016-06-10 14:43:57

标签: oracle plsql exception-handling dynamic-sql execute-immediate

这是一个最小的测试用例,由于某种原因失败了

  

ORA-06510:PL / SQL:未处理的用户定义异常

CREATE PACKAGE my_test
AS
  global_exception EXCEPTION;
END;
/

set serveroutput on;

BEGIN
  execute immediate 'BEGIN RAISE my_test.global_exception; END;';
EXCEPTION
  WHEN my_test.global_exception THEN 
    dbms_output.put_line('global_exception');
END;
/

这是一个有效的测试用例:

BEGIN
  RAISE my_test.global_exception;
EXCEPTION
  WHEN my_test.global_exception THEN 
    dbms_output.put_line('global_exception');
END;
/

有没有办法通过EXECUTE IMMEDIATE提出全局异常? 数据库版本12c或11g

1 个答案:

答案 0 :(得分:4)

如果您使用dbms_sql代替DECLARE l_cur pls_integer; l_rc pls_integer; BEGIN l_cur := dbms_sql.open_cursor; dbms_sql.parse (l_cur, 'BEGIN RAISE my_test.global_exception; END;', dbms_sql.native); l_rc := dbms_sql.execute(l_cur); EXCEPTION WHEN my_test.global_exception THEN dbms_output.put_line('global_exception'); END; / PL/SQL procedure successfully completed. global_exception (在11gR2中),则可以抓住它:

execute immediate

不完全确定为什么会有效,但你的确不然。

啊,investigating the different behaviour threw up a hint。如果您的包裹中有associate an error number with the exception,则可以使用CREATE PACKAGE my_test AS global_exception EXCEPTION; PRAGMA exception_init(global_exception, -20001); END; / BEGIN execute immediate 'BEGIN RAISE my_test.global_exception; END;'; EXCEPTION WHEN my_test.global_exception THEN dbms_output.put_line('global_exception'); END; / PL/SQL procedure successfully completed. global_exception 来抓住它:

execute immediate

您现在也可以在匿名块中静态引发异常,但这并非常有用;如果没有编译指示,这也会得到ORA-06510,就像你在BEGIN RAISE my_test.global_exception; END; / Error report - ORA-20001: ORA-06512: at line 2 内所做的一样:

execute immediate

现在可以将ORA-20001抛入dbms_sql内,并且pragma允许通过上下文切换识别它。或类似的东西。似乎 CREATE OR REPLACE FUNCTION table_date() RETURNS text AS $$ SELECT 'foo_'||to_char(current_timestamp, 'DDMONYY') AS result $ LANGUAGE SQL; 包处理的方式略有不同。