目錄
觸發器
- 是特殊的PL/SQL塊或存儲過程
- 是基於表、視圖、方案、數據庫的
- 是針對特定事件發生時觸發的
- 是隱式執行的
能夠更爲複雜的控制用戶的操作,例如:週末不允許進行離職手續等。
自動處理一些值,例如:賬目低於多少錢自動發消息。
類型
應用程序觸發器
在應用程序內發生特定DML事件時,將隱式觸發它
數據庫觸發器
在表、視圖、方案或數據庫上發生特定事件時,將隱式觸發它
觸發器設計原則
設計觸發器爲了:
- 保證當一個指定的操作被執行時,執行相關的動作
- 集中全局操作
如果觸發器的算法很長,將算法創建於存儲過程中,再在觸發器中調用它們,觸發器的大小不能超過32K。過分地使用觸發器可能導致複雜的依賴,這在大的應用程序中可能會產生維護困難。
DML觸發器
一個觸發器語句包含:
觸發時間
- 對於表: BEFORE, AFTER
- 對於視圖: INSTEAD OF
觸發事件: INSERT, UPDATE或DELETE
表名: On table、view
觸發器類型: Row或statement (只執行一次)
WHEN子句:限制條件,只能在行級觸發器中使用
觸發器體: PL/SQL塊
部分 | 說明 | 可能值 |
觸發器時機 | 當觸發器涉及觸發事件時的觸發時機 | BEFORE、AFTER、INSTEAD OF |
觸發事件 | 在表或視圖上的哪一-個數據操縱操作引發了觸發器觸發 | INSERT、UPDATE、DELETE |
觸發器類型 | 觸發器體被執行多少次 | Sta tement、ROW |
觸發器體 | 觸發器執行的那些動作 | PL/SQL塊 |
創建
語法:
CREATE [OR REPLACE] TRIGGER
trigger_name
[ BEFOREI AFTER]
[ INSERTI UPDATE [of column] | DELETE]
ON table name
Trigger_body
例子:
員工信息只有在工作日才能進行修改
CREAT OR REPLACE TRIGGER sal_emp
BEFORE INSERT ON emp
BEGIN
IF(to_char(sysdate),'DY') in ('星期六','星期日')
then
raise_application_error(-20001,'只有工作日才能錄入數據');
END IF
END;
INSERT INTO
emp(empno,ename,job,mgr,hiredate,sal)
VALUES(1002,'ljs','clerk',7902,sysdate,2000);
觸發事件
觸發事件可以是表上的INSERT、UPDATE或DELETE語句。
當觸發事件是一個UPDATE語句時,可以用一個字段列表來確定那些必需觸發觸發器自來改變的列。不能爲INSERT或DELETE語句指定字段列表,因爲它們總是影響整個行(...UPDATE OF sal...)。
對於語句觸發器,觸發事件對於觸發器執行一次;對於行觸發器,觸發事件僅當行被修改時觸發。
例如:
語句觸發器
例子:
create or replace trigger trg_empl_ins
after insert on empl
begin
INSERT INTO empl_new (empno, ename,sal)
VALUES (999, '張三', 3000) ;
end trg_empl_ins;
CREATE TABLE empl_new
AS SELECT *FROM emp
WHERE empno IS
NULL
INSERT INTO empl ( empno, ename, sal)
VALUES (888,'李四',4000)
這樣就實現了在兩張表同時添加數據了,做成了兩張表的同步。一條是insert的一條是觸發器添加的。
行觸發器
使用關鍵字for each row
創建語法:
CREATE [OR REPLACE] TRIGGER trigger_ name
[BEFORE | AFTER ]
[ INSERT | UPDATE [of column] | DELETE]
ON table_name
[ REFERENCING OLD as old | NEW as new]
FOR EACH ROW
[WHEN (condition)]
Trigger_body
NEW代表新加的數據,OLD代表老數據。靈活使用,例如刪除的時候沒有新值,修改時old,new都有。
例子:
CREATE OR REPLACE TRIGGER sal_emp
BEFORE UPDATE OF sal ON emp
FOR EACH ROW
BEGIN
IF(:new.sal >:old.sa1) THEN
raise_application_error(-20001,薪水太高了);
END IF;
END;
UPDATE emp SET sal=5000;
在BEGIN之前不用加冒號,在BEGIN內的語句體內需要加冒號(表示外部變量)
例子:
create or replace trigger trg_emp1_ins_row
after insert on emp1
for each row
begin
INSERT INTO emp_new(empno, ename,sal)
VALUES ( :NEW. empno, :NEW. ename, :NEW.sal);
end trg_empl_ins_row;
這樣也能做成兩張相同的表。
注意:回滾時兩張表的數據均會回滾掉。COMMIT命令不能出現在觸發器中。
INSTEAD_OF觸發器
視圖上是不能插入數據的,但是如果創建一個instead_of觸發器,就可以實現在視圖中向表中插入數據。
語法:
CREATE OR REPLACE TRIGGER trigger_name
INSTEAD OF
[INSERT | UPDATE [OF column] | DELETE]
ON view_ ame
[REFERENCING OLD as old | NEW as new]
FOR EACH ROW
Trigger_body
維護
ALTER TRIGGER trigger name DISABLE| ENABLE
例如在提前編好觸發器,先禁用掉,等需要的時候上線使用。
刪除
DROP TRIGGER trigger_name ;
另外,當表被刪除時,表上的所有觸發器都被刪除。
數據庫觸發器和存儲過程之間的區別
觸發器 | 過程 |
用CREATE TRIGGER定 義 | 用CREATE PROCEDURE定義 |
在數據字典USER TRIGGERS中包含源代碼 | 在數據字典USER_SOURCE中包含源代碼 |
隱式調用 | 顯式調用 |
不允許COMMIT,SAVEPOINT和ROLLBACK | 允許COMMIT,SAVEPOINT和ROLLBACK |