【问题标题】:A unhandled exception in a "after create" trigger preventing create“创建后”触发器中的未处理异常阻止创建
【发布时间】:2018-06-08 23:36:25
【问题描述】:

我的架构上有一个引发异常的 AFTER CREATE 触发器;我正在尝试创建一个表。我了解未处理的异常可能导致查询/操作/事务(我找不到适合这种情况的词)终止。但是,当创建表之后引发异常时,到那时表不应该已经创建了吗?

成功触发后创建表时会抛出错误错误:

create table test(testcol number);

错误:

SQL Error: ORA-00604: error occurred at recursive SQL level 1
ORA-06510: PL/SQL: unhandled user-defined exception
ORA-06512: at line 4

触发器:

create or replace trigger ddl_trig_2812
after create
on schema
declare
eirit exception;
begin
raise eirit;
end;
/

【问题讨论】:

    标签: oracle oracle11g triggers


    【解决方案1】:

    验证这一点的一个很好的例子是检查表是否真的存在于触发器中。

    假设您来自EXCEPTION 块的RAISE 并查询DBA_OBJECTS 以查看对象是否存在。

    SQL> create or replace trigger ddl_trig_2812
      2  after create
      3  on schema
      4  declare
      5  v_table_name  DBA_OBJECTS.OBJECT_NAME%TYPE;
      6  eirit exception;
      7  begin
      8  select object_name into v_table_name from DBA_OBJECTS where object_name = 'ATEST';
      9  raise eirit;
     10  EXCEPTION
     11  WHEN OTHERS THEN
     12    DBMS_OUTPUT.PUT_LINE( 'TABLE CREATED '|| v_table_name );
     13    RAISE;
     14   END;
     15
     16  /
    

    触发器已创建。

    现在,让我们创建表。

    SQL> set serveroutput on;
    SQL> create table atest ( a number);
    TABLE CREATED ATEST
    create table atest ( a number)
    *
    ERROR at line 1:
    ORA-00604: error occurred at recursive SQL level 1
    ORA-06510: PL/SQL: unhandled user-defined exception
    ORA-06512: at line 10
    

    尽管引发了异常,但该表存在于数据字典中,如您在dbms_output 显示的消息上方所见。

    现在,如果我们检查表是否存在,

        SQL> select * from atest;
        select * from atest
                      *
        ERROR at line 1:
        ORA-00942: table or view does not exist
    SQL> select object_name from DBA_OBJECTS where object_name = 'ATEST'
      2  ;
    
    no rows selected
    

    这意味着,Oracle 更改 DDL 触发器中的数据字典,但如果触发器中发生错误,则回滚事务。

    【讨论】:

      【解决方案2】:

      来自文档:

      在大多数情况下,如果触发器运行引发异常的语句,并且异常未由异常处理程序处理,则数据库会回滚触发器及其触发语句的影响。

      正如您的问题所暗示的那样,它不仅会导致它终止。您未处理的异常导致触发语句 - 即 create table - 被回滚。 When talking about DDL statements:

      在数据库执行 DDL 语句之前立即发生隐式 COMMIT,之后立即发生 COMMIT 或 ROLLBACK。在前面的示例中,... [if] ALTER TABLE 语句成功,则数据库提交该语句;否则,数据库回滚该语句。 ...

      所以这是预期的行为。

      【讨论】:

        【解决方案3】:

        事务以 CREATE TABLE 开始;然后 AFTER CREATE 触发器触发并引发异常,即表定义不是“提交”到数据字典表(例如 USER_TABLES、USER_TAB_COLUMNS、...)中,而是“回滚”。

        所以 - 不,CREATE TABLE 过程没有正确完成,您不能使用该表,因为它没有被创建,因为它的创建被触发器阻止。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-06-03
          • 1970-01-01
          • 2017-03-29
          • 2020-06-07
          • 2014-05-09
          • 1970-01-01
          • 2018-07-09
          相关资源
          最近更新 更多