Oracle11新特性——PLSQL新特性(五)

yangtingkun發表於2007-09-23

打算寫一系列的文章介紹11g的新特性和變化。

11gPL/SQL新增了很多特性,在效能和易用性方面做了不少的提升,還有一些功能性的增強。

這篇介紹一下PLSQL的新增的控制觸發器的觸發順序功能。

Oracle11新特性——PLSQL新特性(一):http://yangtingkun.itpub.net/post/468/395965

Oracle11新特性——PLSQL新特性(二):http://yangtingkun.itpub.net/post/468/396571

Oracle11新特性——PLSQL新特性(三):http://yangtingkun.itpub.net/post/468/396994

Oracle11新特性——PLSQL新特性(四):http://yangtingkun.itpub.net/post/468/397350


11g中對於觸發器部分有了一定的增強,主要表現在兩個方面。一個是對觸發器的觸發順序可以進行控制。另一個是可以定義一個複合觸發器。

這一篇首先介紹一下觸發器的順序控制。

在11g以前,Oracle的文件上一直是這樣描述的:Oracle是不會保證同種型別的觸發器的觸發先後順序。不過在測試中發現,Oracle似乎是根據觸發器建立時間的先後決定觸發順序的:

SQL> CREATE TABLE T (ID NUMBER, NAME VARCHAR2(30));

表已建立。

SQL> CREATE OR REPLACE TRIGGER TRI_T_1 AFTER INSERT ON T
2 FOR EACH ROW
3 BEGIN
4 DBMS_OUTPUT.PUT_LINE(1);
5 END;
6 /

觸發器已建立

SQL> CREATE OR REPLACE TRIGGER TRI_T_2 AFTER INSERT ON T
2 FOR EACH ROW
3 BEGIN
4 DBMS_OUTPUT.PUT_LINE(2);
5 END;
6 /

觸發器已建立

SQL> CREATE OR REPLACE TRIGGER TRI_T_3 AFTER INSERT ON T
2 FOR EACH ROW
3 BEGIN
4 DBMS_OUTPUT.PUT_LINE(3);
5 END;
6 /

觸發器已建立

SQL> SET SERVEROUT ON
SQL> INSERT INTO T VALUES (1, 'A');
3
2
1

已建立 1 行。

SQL> INSERT INTO T SELECT ROWNUM, OBJECT_NAME FROM USER_OBJECTS;
3
2
1
3
2
1
3
2
1
3
2
1

已建立4行。

如果將TRI_T_2刪除,並重寫建立,則這個觸發器會最先觸發:

SQL> DROP TRIGGER TRI_T_2;

觸發器已刪除。

SQL> CREATE OR REPLACE TRIGGER TRI_T_2 AFTER INSERT ON T
2 FOR EACH ROW
3 BEGIN
4 DBMS_OUTPUT.PUT_LINE(2);
5 END;
6 /

觸發器已建立

SQL> INSERT INTO T VALUES (2, 'B');
2
3
1

已建立 1 行。

如果同一類的觸發器在觸發的時候需要按照某種順序觸發,那麼僅靠觸發器建立時間先後這個條件是無法確保順序不會發生變化的。

11g觸發器新增了FOLLOWS語句,使得觸發器建立的過程中可以指定順序:

SQL> CREATE TABLE T (ID NUMBER, NAME VARCHAR2(30));

表已建立。

SQL> CREATE OR REPLACE TRIGGER TRI_T_1 AFTER INSERT ON T
2 FOR EACH ROW
3 BEGIN
4 DBMS_OUTPUT.PUT_LINE(1);
5 END;
6 /

觸發器已建立

SQL> CREATE OR REPLACE TRIGGER TRI_T_2 AFTER INSERT ON T
2 FOR EACH ROW FOLLOWS TRI_T_1
3 BEGIN
4 DBMS_OUTPUT.PUT_LINE(2);
5 END;
6 /

觸發器已建立

SQL> CREATE OR REPLACE TRIGGER TRI_T_3 AFTER INSERT ON T
2 FOR EACH ROW FOLLOWS TRI_T_2
3 BEGIN
4 DBMS_OUTPUT.PUT_LINE(3);
5 END;
6 /

觸發器已建立

SQL> SET SERVEROUT ON
SQL> INSERT INTO T VALUES (1, 'A');
1
2
3

已建立 1 行。

Oracle除了增加了FOLLOWS語法,還可以在建立觸發器的時候指定DISABLE/ENABLE。這對於沒有把握觸發器是否會成功編譯的情況很有幫助:

SQL> CREATE OR REPLACE TRIGGER TRI_T_3 AFTER INSERT ON T
2 FOR EACH ROW FOLLOWS TRI_T_2
3 BEGIN
4 DBMS_OUTPUT.PUT_LINE(3)
5 END;
6 /

警告: 建立的觸發器帶有編譯錯誤。

SQL> INSERT INTO T VALUES (2, 'B');
INSERT INTO T VALUES (2, 'B')
*
1 行出現錯誤:
ORA-04098:
觸發器 'YANGTK.TRI_T_3' 無效且未透過重新驗證

如果觸發器建立的時候報錯,那麼這個基表相應的操作都會由於觸發器的錯誤是失敗。11g可以在建立觸發器的時候就指定DISABLE,避免上面的問題產生:

SQL> CREATE OR REPLACE TRIGGER TRI_T_3 AFTER INSERT ON T
2 FOR EACH ROW DISABLE
3 BEGIN
4 DBMS_OUTPUT.PUT_LINE(3)
5 END;
6 /

警告: 建立的觸發器帶有編譯錯誤。

SQL> INSERT INTO T VALUES (2, 'B');
1
2

已建立 1 行。

這樣避免了觸發器建立中出現的錯誤影響到基表的DML操作。在觸發器編譯成功後,就可以透過ENABLE來啟動觸發器了。

SQL> CREATE OR REPLACE TRIGGER TRI_T_3 AFTER INSERT ON T
2 FOR EACH ROW DISABLE
3 BEGIN
4 DBMS_OUTPUT.PUT_LINE(3)
5 END;
6 /

警告: 建立的觸發器帶有編譯錯誤。

SQL> INSERT INTO T VALUES (2, 'B');
1
2

已建立 1 行。

SQL> CREATE OR REPLACE TRIGGER TRI_T_3 AFTER INSERT ON T
2 FOR EACH ROW DISABLE
3 BEGIN
4 DBMS_OUTPUT.PUT_LINE(3);
5 END;
6 /

觸發器已建立

SQL> INSERT INTO T VALUES (3, 'C');
1
2

已建立 1 行。

SQL> ALTER TRIGGER TRI_T_3 ENABLE;

觸發器已更改

SQL> INSERT INTO T VALUES (4, 'D');
3
1
2

已建立 1 行。

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

相關文章