在本章中,咱們將討論和學習PL/SQL中的觸發器。 觸發器是存儲的程序,在發生某些事件時會自動執行或觸發。事實上,觸發器是爲了響應如下任何事件而被執行的 -sql
DELETE
,INSERT
或UPDATE
)CREATE
,ALTER
或DROP
)。SERVERERROR
,LOGON
,LOGOFF
,STARTUP
或SHUTDOWN
)。能夠在事件關聯的表,視圖,模式或數據庫上定義觸發器。shell
使用觸發器的好處數據庫
觸發器能夠用於如下目的 -安全
建立觸發器的語法是 -學習
CREATE [OR REPLACE ] TRIGGER trigger_name {BEFORE | AFTER | INSTEAD OF } {INSERT [OR] | UPDATE [OR] | DELETE} [OF col_name] ON table_name [REFERENCING OLD AS o NEW AS n] [FOR EACH ROW] WHEN (condition) DECLARE Declaration-statements BEGIN Executable-statements EXCEPTION Exception-handling-statements END;
其中,code
CREATE [OR REPLACE] TRIGGER trigger_name
- 使用trigger_name
建立或替換現有的觸發器。{BEFORE | AFTER | INSTEAD OF}
- 指定什麼時候執行觸發器。INSTEAD OF
子句用於在視圖上建立觸發器。{INSERT [OR] | UPDATE [OR] | DELETE}
- 這指定了DML操做。[OF col_name]
− 這指定了將要更新的列名稱。[ON table_name]
- 這指定了與觸發器關聯的表的名稱。[REFERENCING OLD AS o NEW AS n]
- 這容許各類DML語句(如INSERT
,UPDATE
和DELETE
)引用新值和舊值。[FOR EACH ROW]
- 這指定了一個行級別的觸發器,即觸發器將被執行的每一行受到影響。不然觸發器將在執行SQL語句時執行一次,這稱爲表級觸發器。WHEN(condition)
- 這爲觸發器觸發的行提供了一個條件。該子句僅對行級觸發器有效。首先,將使用前面章節中建立和使用的CUSTOMERS
表,表的定義和數據以下 -事件
CREATE TABLE CUSTOMERS( ID INT NOT NULL, NAME VARCHAR (20) NOT NULL, AGE INT NOT NULL, ADDRESS CHAR (25), SALARY DECIMAL (18, 2), PRIMARY KEY (ID) ); -- 插入示例數據 INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY) VALUES (1, 'Ramesh', 32, 'Ahmedabad', 2000.00 ); INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY) VALUES (2, 'Khilan', 25, 'Delhi', 1500.00 ); INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY) VALUES (3, 'kaushik', 23, 'Kota', 2000.00 ); INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY) VALUES (4, 'Chaitali', 25, 'Mumbai', 6500.00 ); INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY) VALUES (5, 'Hardik', 27, 'Bhopal', 8500.00 ); INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY) VALUES (6, 'Komal', 22, 'MP', 4500.00 );
下面的程序爲customers
表建立一個行級觸發器,該觸發器將觸發在customers
表上執行的INSERT
,UPDATE
或DELETE
操做。這個觸發器將顯示舊值和新值之間的工資差別 -事務
SET SERVEROUTPUT ON SIZE 999999; CREATE OR REPLACE TRIGGER display_salary_changes BEFORE DELETE OR INSERT OR UPDATE ON customers FOR EACH ROW WHEN (NEW.ID > 0) DECLARE sal_diff number; BEGIN sal_diff := :NEW.salary - :OLD.salary; dbms_output.put_line('Old salary: ' || :OLD.salary); dbms_output.put_line('New salary: ' || :NEW.salary); dbms_output.put_line('Salary difference: ' || sal_diff); END; /
當上面的代碼在SQL提示符下執行時,它會產生如下結果 -同步
這裏須要考慮如下幾點 -it
OLD
和NEW
引用不可用於表級觸發器,而是能夠將它們用於記錄級觸發器。AFTER
關鍵字,由於觸發器只能在應用初始更改而且表返回一致狀態後才能查詢表或進行更改。DELETE
或INSERT
或UPDATE
操做以前觸發,可是能夠在一個或多個操做上編寫觸發器,例如BEFORE DELETE
,當表中的一條記錄被刪除時,自動觸發。觸發一個觸發器
如今,在customers
表上執行一些DML操做。這裏以執行一個INSERT
語句做爲示例,它將在表中建立一個新記錄 -
INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY) VALUES (7, 'Hinew', 23, 'Oracle', 9500.00 );
當在CUSTOMERS
表中建立一條記錄時,上面的建立觸發器display_salary_changes
將被觸發,而且將顯示如下結果 -
SQL> INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY) 2 VALUES (7, 'Hinew', 23, 'Oracle', 9500.00); Old salary: New salary: 9500 Salary difference: 已建立 1 行。 SQL>
由於這是一個新的記錄,舊的薪水(salary
)列是不可用的,上述結果爲空。下面再向CUSTOMERS
表上執行另外一個更多的DML操做。此次使用UPDATE
語句來更新表中的現有記錄 -
UPDATE customers SET salary = salary + 500 WHERE id = 2;
執行上面示例代碼,獲得如下結果 -
SQL> UPDATE customers 2 SET salary = salary + 500 3 WHERE id = 2; Old salary: 1500 New salary: 2000 Salary difference: 500 已更新 1 行。