您在这里:首页 > 学员专区 > 技术文章
Oracle视频
Oracle
CUUG课程

系统触发器的应用顺序(三)

 

在写一个AFTER SUSPEND触发器的时候碰到了一个很有趣的现象。

寻找导致问题的原因。

 

 

上一篇文章介绍了,如果当前用户下的触发器出现了编译错误,则会导致其他触发器也无法触发,即使当前触发器被删除。

是什么原因导致了这种情况的产生,怀疑可能与触发器的运行顺序有关,由于触发器的运行是根据触发器的建立顺序,下面将SYS用户下的触发器和当前用户下的触发器建立顺序倒置,看看是否出现同样的问题:

SQL> DROP TABLE T_TRIGGER PURGE;

表已删除。

SQL> CREATE TABLE T_TRIGGER (INFO VARCHAR2(20));

表已创建。

SQL> CONN / AS SYSDBA

已连接。

SQL> DROP TRIGGER TRI_SUSPEND;

触发器已删除。

SQL> CREATE OR REPLACE TRIGGER TRI_SUSPEND

  2  AFTER SUSPEND ON DATABASE

  3  DECLARE

  4   PRAGMA AUTONOMOUS_TRANSACTION;

  5   V_RESULT BOOLEAN;

  6   V_ERROR_TYPE VARCHAR2(32767);

  7   V_OBJECT_TYPE VARCHAR2(32767);

  8   V_OBJECT_OWNER VARCHAR2(30);

  9   V_TABLESPACE_NAME VARCHAR2(30);

 10   V_OBJECT_NAME VARCHAR2(128);

 11   V_SUB_OBJECT_NAME VARCHAR2(128);

 12  BEGIN

 13   V_RESULT := DBMS_RESUMABLE.SPACE_ERROR_INFO(

 14    V_ERROR_TYPE,

 15    V_OBJECT_TYPE,

 16    V_OBJECT_OWNER,

 17    V_TABLESPACE_NAME,

 18    V_OBJECT_NAME,

 19    V_SUB_OBJECT_NAME);

 20   INSERT INTO YANGTK.T_TRIGGER VALUES ('SYS TRIGGER');

 21   COMMIT;

 22  END;

 23  /

触发器已创建

SQL> CONN YANGTK/YANGTK

已连接。

SQL> DROP TRIGGER TRI_SUSPEND;

DROP TRIGGER TRI_SUSPEND

*

第1行出现错误:

ORA-04080:触发器'TRI_SUSPEND'不存在

 

SQL> CREATE OR REPLACE TRIGGER TRI_SUSPEND

  2  AFTER SUSPEND ON DATABASE

  3  DECLARE

  4   PRAGMA AUTONOMOUS_TRANSACTION;

  5   V_RESULT BOOLEAN;

  6   V_ERROR_TYPE VARCHAR2(32767);

  7   V_OBJECT_TYPE VARCHAR2(32767);

  8   V_OBJECT_OWNER VARCHAR2(30);

  9   V_TABLESPACE_NAME VARCHAR2(30);

 10   V_OBJECT_NAME VARCHAR2(128);

 11   V_SUB_OBJECT_NAME VARCHAR2(128);

 12  BEGIN

 13   V_RESULT := DBMS_RESUMABLE.SPACE_ERROR_INFO(

 14    V_ERROR_TYPE,

 15    V_OBJECT_TYPE,

 16    V_OBJECT_OWNER,

 17    V_TABLESPACE_NAME,

 18    V_OBJECT_NAME,

 19    V_SUB_OBJECT_NAME);

 20   INSERT INTO T_TRIGGER VALUES ('YANGTK TRIGGER');

 21   COMMIT;

 22  END;

 23  /

警告:创建的触发器带有编译错误。

SQL> ALTER SESSION ENABLE RESUMABLE TIMEOUT 300;

会话已更改。

SQL> CREATE TABLE T_BIG (ID NUMBER)

  2  TABLESPACE YANGTK

  3  STORAGE (INITIAL250M);

CREATE TABLE T_BIG (ID NUMBER)

*

第1行出现错误:

ORA-04098:触发器'YANGTK.TRI_SUSPEND'无效且未通过重新验证

ORA-01659:无法分配超出27的MINEXTENTS (在表空间YANGTK中)

 

SQL> SELECT * FROM T_TRIGGER;

INFO

--------------------

SYS TRIGGER

SQL> SELECT OBJECT_ID, OWNER

  2  FROM DBA_OBJECTS

  3  WHERE OBJECT_NAME = 'TRI_SUSPEND';

 OBJECT_ID OWNER

---------- ------------------------------

     92651 SYS

     92652 YANGTK

虽然错误信息一样,但是可以看到,这次T_TRIGGER表中包含一条记录,说明SYS触发器已经执行成功了。是在尝试调用第二个触发器YANGTK用户下的触发器时出现的错误。

SQL> DROP TRIGGER TRI_SUSPEND;

触发器已删除。

SQL> CREATE TABLE T_BIG (ID NUMBER)

  2  TABLESPACE YANGTK

  3  STORAGE (INITIAL250M);

CREATE TABLE T_BIG (ID NUMBER)

*

第1行出现错误:

ORA-01659:无法分配超出27的MINEXTENTS (在表空间YANGTK中)

 

SQL> SELECT * FROM T_TRIGGER;

INFO

--------------------

SYS TRIGGER

可以看到,就是由于触发器状态的不正确,导致当前会话调用触发器出现了问题。即使删除了问题触发器,发生了SUSPEND事件后,SYS用户下的AFTER SYSPEND也没有再次被触发。

尝试在当前会话再次添加一个正确的触发器:

SQL> CREATE OR REPLACE TRIGGER TRI_SUSPEND

  2  AFTER SUSPEND ON DATABASE

  3  DECLARE

  4   PRAGMA AUTONOMOUS_TRANSACTION;

  5  BEGIN

  6   INSERT INTO T_TRIGGER VALUES ('YANGTK TRIGGER');

  7   COMMIT;

  8  END;

  9  /

触发器已创建

SQL> CREATE TABLE T_BIG (ID NUMBER)

  2  TABLESPACE YANGTK

  3  STORAGE (INITIAL250M);

CREATE TABLE T_BIG (ID NUMBER)

*

第1行出现错误:

ORA-01659:无法分配超出27的MINEXTENTS (在表空间YANGTK中)

 

SQL> SELECT * FROM T_TRIGGER;

INFO

--------------------

SYS TRIGGER

即使重建当前用户下的触发器,使其状态正确,在当前的会话中,Oracle也不会再次调用触发器了。

相关文章 [上一篇] Oracle数据类型
010-56426307(59426319)
CUUG热门培训课程
Oracle DBA就业培训
CUUG名师
网络课程
技术沙龙
最新动态

总机:(010)-56426307,59426319 QQ讨论群:243729577 182441349 邮箱:yuezt@cuug.com
通信地址:北京市海淀区紫竹院路88号紫竹花园D座703(CUUG)邮政编码:100089 
中国UNIX用户协会 Copyright 2010  ALL Rights Reserved 北京神脑资讯技术有限公司
京ICP备11008061号