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

本文探讨了Oracle数据库中触发器的有效性和执行顺序问题,特别是在遇到编译错误时如何影响其他触发器的执行。通过实例展示了当存在编译错误的触发器时,不仅该触发器无法执行,还会影响其他有效触发器的正常工作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

看一个例外的情况。

系统触发器的应用顺序(一):http://yangtingkun.itpub.net/post/468/486884

 

 

上一篇文章中通过测试说明,所有满足触发条件的触发器都会执行,下面再看一个例子。这个例子将触发器变得稍微复杂一点:

SQL> CONN YANGTK/YANGTK
已连接。
SQL> DROP TABLE T_TRIGGER PURGE;

表已删除。

SQL> DROP TRIGGER TRI_SUSPEND;

触发器已删除。

SQL> CONN / AS SYSDBA
已连接。
SQL> DROP TRIGGER TRI_SUSPEND;

触发器已删除。

首先清除上一篇文章的测试环境,下面在当前用户下创建触发器,并在触发器中执行DBMS_RESUMABLE包的过程:

SQL> CONN YANGTK/YANGTK
已连接。
SQL> CREATE TABLE T_TRIGGER (INFO VARCHAR2(20));

表已创建。

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> SHOW ERR
TRIGGER TRI_SUSPEND
出现错误:

LINE/COL ERROR
-------- -----------------------------------------------------------------
11/2     PL/SQL: Statement ignored
11/14    PLS-00201:
必须声明标识符 'DBMS_RESUMABLE'

触发器的创建报错了,这是由于当前用户没有执行DBMS_RESUMABLE的权限。这时如果不删除当前用户下的触发器,而在SYS用户下建立同样的触发器:

SQL> CONN / AS SYSDBA
已连接。
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  /

触发器已创建

SYS用户下的创建显然没有任何问题,下面回到YANGTK用户引发触发器执行条件:

SQL> CONN YANGTK/YANGTK
已连接。
SQL> ALTER SESSION ENABLE RESUMABLE TIMEOUT 300;

会话已更改。

SQL> CREATE TABLE T_BIG (ID NUMBER)
  2  TABLESPACE YANGTK
  3  STORAGE (INITIAL 250M);
CREATE TABLE T_BIG (ID NUMBER)
*
1 行出现错误:
ORA-04098:
触发器 'YANGTK.TRI_SUSPEND' 无效且未通过重新验证
ORA-01659:
无法分配超出 27 MINEXTENTS (在表空间 YANGTK )


SQL> SELECT * FROM T_TRIGGER;

未选定行

显然这次一个触发器都没有执行。不过这也不难理解,由于当前用户下要运行的触发器存在编译错误,显然运行就会报错,因此Oracle没有继续调用其他的触发器。

SQL> SHOW USER
USER
"YANGTK"
SQL> DROP TRIGGER TRI_SUSPEND;

触发器已删除。

SQL> CREATE TABLE T_BIG (ID NUMBER)
  2  TABLESPACE YANGTK
  3  STORAGE (INITIAL 250M);
CREATE TABLE T_BIG (ID NUMBER)
*
1 行出现错误:
ORA-01659:
无法分配超出 27 MINEXTENTS (在表空间 YANGTK )


SQL> SELECT * FROM T_TRIGGER;

未选定行

有意思的情况出现了,删除当前存在编译错误的触发器,然后再次以发触发器事件,而这次SYS用户下的触发器仍然没有执行。

只有重新登陆,才能使得触发器执行:

SQL> CONN YANGTK/YANGTK
已连接。
SQL> ALTER SESSION ENABLE RESUMABLE TIMEOUT 300;

会话已更改。

SQL> CREATE TABLE T_BIG (ID NUMBER)
  2  TABLESPACE YANGTK
  3  STORAGE (INITIAL 250M);
CREATE TABLE T_BIG (ID NUMBER)
*
1 行出现错误:
ORA-30032:
挂起的 (可恢复) 语句已超时
ORA-01659:
无法分配超出 27 MINEXTENTS (在表空间 YANGTK )


SQL> SELECT * FROM T_TRIGGER;

INFO
--------------------
SYS TRIGGER

看来触发器失效影响的并不只是当前的触发器执行,还会影响到其他触发器,而且失效触发器被删除后,仍然可能影响其他的触发器直到会话结束。

 

 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/4227/viewspace-608211/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/4227/viewspace-608211/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值