设为首页 收藏本站
查看: 1314|回复: 0

[经验分享] Oracle的触发器迭代限制

[复制链接]

尚未签到

发表于 2016-7-23 11:33:38 | 显示全部楼层 |阅读模式
Oracle的触发器在触发事件发生后,会自动执行触发器的操作,而这个触发器的操作又可能会触发另一个触发器,这就导致了触发器的迭代。


今天在看Concept的时候,发现Oracle对于触发器迭代是有限制的,最多允许32层迭代,不过Oracle并没有说明超过这个限制会怎样,是报错,还是第33个触发器不被触发。下面通过一个例子来验证一下,是否存在这个迭代限制,以及超过迭代限制后,Oracle如何进行处理。
这里不妨先假设一下,个人认为Oracle应该报错。报错虽然不友好,但是至少使终端用户了解发生了什么问题,并有机会解决,而如果不报错,只是简单的不触发触发器的话,可能会留下一个很难排查的系统bug。
  SQL> DECLARE
2 V_STR VARCHAR2(32767);
3 BEGIN
4 FOR I IN 1..33 LOOP
5 V_STR := 'CREATE TABLE T_TRIGGER' || I || '(ID NUMBER)';
6 EXECUTE IMMEDIATE V_STR;
7 END LOOP;
8 FOR I IN 1..32 LOOP
9 V_STR := 'CREATE TRIGGER T_TRIGGER' || I || ' AFTER INSERT ON T_TRIGGER' || I
10 || ' FOR EACH ROW
11 BEGIN
12 INSERT INTO T_TRIGGER' || TO_CHAR(I + 1) || ' VALUES (:NEW.ID);
13 END;';
14 EXECUTE IMMEDIATE V_STR;
15 END LOOP;
16 END;
17 /

  PL/SQL 过程已成功完成。
  SQL> SELECT TABLE_NAME FROM USER_TABLES
2 WHERE TABLE_NAME LIKE 'T_TRIGGER%';

  TABLE_NAME
------------------------------
T_TRIGGER9
T_TRIGGER8
T_TRIGGER7
T_TRIGGER6
T_TRIGGER5
T_TRIGGER4
T_TRIGGER33
T_TRIGGER32
T_TRIGGER31
T_TRIGGER30
T_TRIGGER3
T_TRIGGER29
T_TRIGGER28
T_TRIGGER27
T_TRIGGER26
T_TRIGGER25
T_TRIGGER24
T_TRIGGER23
T_TRIGGER22
T_TRIGGER21
T_TRIGGER20
T_TRIGGER2
T_TRIGGER19
T_TRIGGER18
T_TRIGGER17
T_TRIGGER16
T_TRIGGER15
T_TRIGGER14
T_TRIGGER13
T_TRIGGER12
T_TRIGGER11
T_TRIGGER10
T_TRIGGER1

  已选择33行。
现在已经创建了33张表和32个触发器,尝试在第一张表插入一条数据:
  SQL> INSERT INTO T_TRIGGER1 VALUES (1);
  已创建 1 行。
  SQL> SELECT * FROM T_TRIGGER1;
  ID
----------
1

  SQL> SELECT * FROM T_TRIGGER32;
  ID
----------
1

  SQL> SELECT * FROM T_TRIGGER33;
  ID
----------
1

32个触发器都已经生效,下面创建第34张表和第33个触发器:
  SQL> CREATE TABLE T_TRIGGER34 (ID NUMBER);
  表已创建。
  SQL> CREATE TRIGGER T_TRIGGER33 AFTER INSERT ON T_TRIGGER33
2 FOR EACH ROW
3 BEGIN
4 INSERT INTO T_TRIGGER34 VALUES (:NEW.ID);
5 END;
6 /

  触发器已创建
  SQL> INSERT INTO T_TRIGGER1 VALUES (2);
  已创建 1 行。
  SQL> SELECT * FROM T_TRIGGER1;
  ID
----------
1
2

  SQL> SELECT * FROM T_TRIGGER33;
  ID
----------
1
2

  SQL> SELECT * FROM T_TRIGGER34;
  ID
----------
2

第34张表中也存在记录,看来第33个触发器也生效了,莫非是Oracle的Concept的描述错误,再次检查Concept上的描述,发现Oracle允许32个触发器迭代触发,而第一个触发器只是正常触发,应该不算迭代触发:
  SQL> CREATE TABLE T_TRIGGER35 (ID NUMBER);
  表已创建。
  SQL> CREATE TRIGGER T_TRIGGER34 AFTER INSERT ON T_TRIGGER34
2 FOR EACH ROW
3 BEGIN
4 INSERT INTO T_TRIGGER35 VALUES (:NEW.ID);
5 END;
6 /

  触发器已创建
  SQL> INSERT INTO T_TRIGGER1 VALUES (3);
  已创建 1 行。
  SQL> SELECT * FROM T_TRIGGER1;
  ID
----------
1
2
3

  SQL> SELECT * FROM T_TRIGGER33;
  ID
----------
1
2
3

  SQL> SELECT * FROM T_TRIGGER34;
  ID
----------
2
3

  SQL> SELECT * FROM T_TRIGGER35;
  ID
----------
3

这次唯一的解释只能是Concept的描述出现了错误。
  SQL> BEGIN
2 FOR I IN 1..35 LOOP
3 EXECUTE IMMEDIATE 'DROP TABLE T_TRIGGER' || I;
4 END LOOP;
5 END;
6 /

  PL/SQL 过程已成功完成。
  SQL> DECLARE
2 V_STR VARCHAR2(32767);
3 BEGIN
4 FOR I IN 1..101 LOOP
5 V_STR := 'CREATE TABLE T_TRIGGER' || I || '(ID NUMBER)';
6 EXECUTE IMMEDIATE V_STR;
7 END LOOP;
8 FOR I IN 1..100 LOOP
9 V_STR := 'CREATE TRIGGER T_TRIGGER' || I || ' AFTER INSERT ON T_TRIGGER' || I
10 || ' FOR EACH ROW
11 BEGIN
12 INSERT INTO T_TRIGGER' || TO_CHAR(I + 1) || ' VALUES (:NEW.ID);
13 END;';
14 EXECUTE IMMEDIATE V_STR;
15 END LOOP;
16 END;
17 /

  PL/SQL 过程已成功完成。
  SQL> INSERT INTO T_TRIGGER1 VALUES (1);
INSERT INTO T_TRIGGER1 VALUES (1)
*
第 1 行出现错误:
ORA-00036: 超过递归 SQL 级别的最大值 50
ORA-06512: 在 "TEST.T_TRIGGER50", line 2
ORA-04088: 触发器 'TEST.T_TRIGGER50' 执行过程中出错
ORA-06512: 在 "TEST.T_TRIGGER49", line 2
ORA-04088: 触发器 'TEST.T_TRIGGER49' 执行过程中出错
ORA-06512: 在 "TEST.T_TRIGGER48", line 2
ORA-04088: 触发器 'TEST.T_TRIGGER48' 执行过程中出错
ORA-06512: 在 "TEST.T_TRIGGER47", line 2
ORA-04088: 触发器 'TEST.T_TRIGGER47' 执行过程中出错
ORA-06512: 在 "TEST.T_TRIGGER46", line 2
ORA-04088: 触发器 'TEST.T_TRIGGER46' 执行过程中出错
ORA-06512: 在 "TEST.T_TRIGGER45", line 2
ORA-04088: 触发器 'TEST.T_TRIGGER45' 执行过程中出错
ORA-06512: 在 "TEST.T_TRIGGER44", line 2
ORA-04088: 触发器 'TEST.T_TRIGGER44' 执行过程中出错
ORA-06512: 在 "TEST.T_TRIGGER43", line 2
ORA-04088: 触发器 'TEST.T_TRIGGER43' 执行过程中出错
ORA-06512: 在 "TEST.T_TRIGGER42", line 2
ORA-04088: 触发器 'TEST.T_TRIGGER42' 执行过程中出错
ORA-06512: 在 "TEST.T_TRIGGER41", line 2
ORA-04088: 触发器 'TEST.T_TRIGGER41' 执行过程中出错
ORA-06512: 在 "TEST.T_TRIGGER40", line 2
ORA-04088:

调整了一下并发触发器的个数,再次测试,可以发现,导致错误的原因是超过了SQL递归调用的上限50,而并不是文档中描述的32。
Oracle在出现超过阈值上限的调用时会报错,这也和开始的猜测相吻合,不过相信在正常环境下,应该不会出现这种极端的错误。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-248213-1-1.html 上篇帖子: Oracle session active 和 inactive 状态 说明 下篇帖子: SSH+Oracle批量插入数据小结
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表