"创建"之后的未处理异常触发阻止创建

时间:2017-12-28 12:03:00

标签: oracle oracle11g triggers

我的架构上有一个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;
/

3 个答案:

答案 0 :(得分:2)

事务以CREATE TABLE开头;然后AFTER CREATE触发器触发并引发异常,即表定义不会被提交"到数据字典表(例如USER_TABLES,USER_TAB_COLUMNS,......)但是"回滚"。

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

答案 1 :(得分:2)

来自文档:

  

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

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

  

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

所以这是预期的行为。

答案 2 :(得分:1)

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

让我们从RAISE块中EXCEPTION并查询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触发器中的数据字典,但如果触发器中发生错误,则会回滚事务。