在文章《自动启用表的FLASHBACK ARCHIVE》中用的是DATABASE级别的触发器,并且指出使用SCHEMA级别的触发器可能会失效,也就是触发器不会触发。这里就通过实验的方式来说明。
首先我们来建立两个实验用户JET1和JET2:
15:15:13 sys@audtest[hxddcx02]> CREATE USER JET1 IDENTIFIED BY JET1;
User created.
15:15:28 sys@audtest[hxddcx02]> GRANT DBA TO JET1;
Grant succeeded.
15:15:40 sys@audtest[hxddcx02]> CREATE USER JET2 IDENTIFIED BY JET2;
User created.
15:15:53 sys@audtest[hxddcx02]> GRANT DBA TO JET2;
Grant succeeded. |
我们以JET1用户登录到数据库,并建立一个SCHEMA触发器:
15:15:59 sys@audtest[hxddcx02]> conn JET1/JET1 Connected. 15:19:45 jet1@audtest[hxddcx02]> CREATE OR REPLACE TRIGGER TRI_JET1 15:20:43 2 AFTER DDL ON JET1.SCHEMA 15:20:43 3 BEGIN 15:20:43 4 dbms_output.put_line(‘DDL Trigger on JET1.‘); 15:20:43 5 END; 15:20:43 6 /
Trigger created. |
然后我们尝试建一个TABLE:
我们可以看到触发器已经被触发了。我们另开一个窗口,以JET2用户登录数据库,并尝试在JET1上建一个TABLE:
TABLE顺利创建,但是我们可以看到触发器并没有触发。为什么会这样呢?这是因为我们在执行CREATE TABLE JET1.TEST2语句时其实是在执行一个匿名块(anonymous block),而匿名块始终表现为IR unit(invoker’s rights unit),也就是说此时的触发事件是属于JET2的,而不是JET1,这样的话自然就不会触发触发器了。为了更直观的来理解该问题,我们可以建两个存储过程来说明。
首先建一个DR unit(definer‘s rights unit)的存储过程:
CREATE OR REPLACE PROCEDURE CRT_TABLE ( tabname VARCHAR2 ) IS opsql VARCHAR2(200); BEGIN opsql := ‘CREATE TABLE JET1.‘||tabname||‘ (ID NUMBER, NAME VARCHAR2(30))‘; EXECUTE IMMEDIATE opsql; END; / |
然后建一个IR unit的存储过程:
CREATE OR REPLACE PROCEDURE CRT_TABLE2 ( tabname VARCHAR2 ) AUTHID CURRENT_USER IS opsql VARCHAR2(200); BEGIN opsql := ‘CREATE TABLE JET1.‘||tabname||‘ (ID NUMBER, NAME VARCHAR2(30))‘; EXECUTE IMMEDIATE opsql; END; / |
JET1用户调用CRT_TABLE时:
可以看到触发器被正确触发了。JET2用户调用CRT_TABLE时:
可以看到触发器也被触发了,这也是正确的动作。那作为对比,我们来看看调用CRT_TABLE2时的情况:
JET1用户调用CRT_TABLE2时:
JET2用户调用CRT_TABLE2时:
这个就和之前直接执行CREATE TABLE时的情景一样了。
自动启用表的FLASHBACK ARCHIVE续之触发器类型的选择
原文:http://blog.itpub.net/13885898/viewspace-1656453/