自動啟用表的FLASHBACK ARCHIVE續之觸發器型別的選擇

Jet_Zhang發表於2015-05-15


在文章《自動啟用表的FLASHBACK ARCHIVE中用的是DATABASE級別的觸發器,並且指出使用SCHEMA級別的觸發器可能會失效,也就是觸發器不會觸發。這裡就透過實驗的方式來說明。

首先我們來建立兩個實驗使用者JET1JET2

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時的情景一樣了。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/13885898/viewspace-1656453/,如需轉載,請註明出處,否則將追究法律責任。

相關文章