oracle技术之系统触发器的应用顺序(三)


在写一个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视频教程请关注:http://u.youku.com/user_video/id_UMzAzMjkxMjE2.html

你可能感兴趣的:(oracle,系统触发器,系统触发器的应用顺序)