Oracle中觸發器的應用 (zt)

tolywang發表於2008-04-24
觸發器
(此文為greenfish原創,轉載請註明)
觸發器是指存放在資料庫中,並且被隱含執行的儲存過程。當發生特定事件時,Oracle會自動執行觸發器的響應程式碼。觸發器又分為DML觸發器、INSTEAD OF觸發器和事件觸發器三種。
[@more@]


一、 DML觸發器
DML觸發器是指基於 DML操作所建立的觸發器。在建立了DML觸發器之後,如果執行了關於DML語句,那麼Oracle會隱含的執行觸發器程式碼。DML觸發器包括語句觸發器和行觸發器兩種型別。
1.1 語句觸發器
語句觸發器是指當執行DML語句時被隱含執行的觸發器。在建立了語句觸發器之後,如果執行了相關的DML語句,那麼會執行該觸發器的相應程式碼。注意,當執行語句觸發器時,不能記錄列資料的變化。建立語句觸發器的語法如下:
CREATE [OR REPLACE] TRIGGER trigger_name
{before | after } event1 [or event2 or event3]
ON table_name
如上所示。Trigger_name用於指定觸發器的名稱,event用於指定觸發事件(INSERT、UPDATE、DELETE),table_name用於指定DML語句所對應的表名。
1.建立BEFORE語句觸發器
BEFORE語句觸發器是指在執行DML語句之前被觸發的觸發器。下面以禁止在週六、週日改變EMP表資料為例,說明BEFORE語句觸發器的方法。
CREATE OR REPLACE TRIGGER TR_SEC_EMP BEFORE
INSERT
OR UPDATE
OR DELETE ON EMPLOYEE
begin
if to_char(sysdate,'dy','nls_date_language=american')
in ('SAT','SUN') then
raise_application_error(-20001,'不能在休息日改變僱員資訊');
end if;
end;
/
UPDATE employee sal =sal*1.1 WHERE deptno=4;
UPDATE employee sal=sal*1.1 WHERE deptno=4
ORA-20001: 不能在休息日改變僱員資訊
ORA-06512: 在"TEST.TR_SEC_EMP1", line 2
ORA-04088: 觸發器 'TEST.TR_SEC_EMP1' 執行過程中出錯
2.建立AFTER語句觸發器
AFTER語句觸發器是指在執行了DML語句之後被觸發的觸發器。下面以使用者對test表執行DML語句時,將相關資訊記錄到日誌表為例,說明AFTER語句觸發器的方法。
CREATE OR REPLACE TRIGGER test_trigger
AFTER DELETE OR INSERT OR UPDATE ON test
DECLARE
v_type test_log.l_type%TYPE;
BEGIN
IF INSERTING THEN
--INSERT觸發
v_type := 'INSERT';
DBMS_OUTPUT.PUT_LINE('記錄已經成功插入,並已記錄到日誌');
ELSE
IF UPDATING THEN --UPDATE觸發 v_type := 'UPDATE';
DBMS_OUTPUT.PUT_LINE('記錄已經成功更新,並已記錄到日誌');
ELSE
IF DELETING THEN v_type := 'DELETE';
DBMS_OUTPUT.PUT_LINE('記錄已經成功刪除,並已記錄到日誌');
END IF;
INSERT INTO test_log VALUES(user,v_type, TO_CHAR(sysdate,'yyyy-mm-dd hh24:mi:ss'));
END;
--下面我們來分別執行DML語句
INSERT INTO test VALUES(101,'zhao',22,'M');
UPDATE test SET t_age = 30 WHERE t_id = 101;
DELETE test WHERE t_id = 101;
--然後檢視效果
SELECT * FROM test;SELECT * FROM test_log;
3.使用條件謂詞
當DML觸發器包含多個觸發事件(INSERT、UPDATE、DELETE)時,為了區分具體的觸發事件,可以使用以下謂詞:
INSERTING:當觸發事件是INSERT語句時,返回TRUE,否則返回FALSE。
UPDATING:當觸發事件是UPDATE語句時,返回TRUE,否則返回FALSE。
DELETING:當觸發事件是DELETE語句時,返回TRUE,否則返回FALSE。
下面以防止週六、週日在EMPLOYEE表上執行DML,根據不同謂詞顯示不同錯誤資訊,並建立tr_sec_emp為例,說明使用條件謂詞的方法。
create or replace trigger tr_sec_emp
before insert or update or delete on employee
begin
if to_char(sysdate,'dy','nls_data_language')
in ('SAT','SUN') then
case
when inserting then
raise_application_error(-20001,'不能在休息日執行INSERT');
when updating then
raise_application_error(-20002,'不能在休息日執行UPDATE');
when deleting then
raise_application_error(-20003,'不能在休息日執行DELETE');
end case;
end if;
end;
/
執行DML語句
Delete from employee where empno=4;
1.2 行觸發器
行觸發器是指當執行DML語句時,每作用一行被觸發一次的觸發器。當使用DML語句觸發器時,不能記錄資料的變化;為了審計表資料的變化,就需要使用行觸發器。注意,當編寫行觸發器時,觸發器程式碼不能從觸發器所對應的基表中讀取資料。建立行觸發器的語法如下:
CREATE [OR REPLACE] TRIGGER trigger_name
{BEFORE | AFTER} event1 [OR event2 OR event3]
ON table_name [REFERENCING OLD AS old | NEW AS new]
FOR EACH ROW [WHEN condition]
如上所示,trigger_name用於指定觸發器名,event用於指定觸發事件(INSERT、UPDATE、DELETE),table_name用於指定DML語句所對應的表名,REFERENCING子句用於指定引用新、舊資料的方式,預設情況下使用old運算子引用舊資料,使用new運算子引用新資料,FOR EACH ROW用於指定建立行觸發器,WHEN子句(可選)用於指定觸發事件。
1.建立BEFORE行觸發器
BEFORE行觸發器是指在處理行之前被觸發的觸發器。下面以確保僱員工資不能低於其原有工資,並建立行觸發器tr_emp_sal為例,說明建立BEFORE行觸發器的方法。
create or replace trigger tr_emp_sal
before update of sal on employee for each row
begin
if :new.sal<:old.sal then="">raise_application_error(-20010,'工資只升不降');
end if;
end;
/
update employee set sal=1000 where empno=10

ORA-20931: 工資只升不降,並且升幅不能超過20%
ORA-06512: 在"TEST.TR_CHECK_SAL", line 2
ORA-04088: 觸發器 'TEST.TR_CHECK_SAL' 執行過程中出錯
2.建立AFTER行觸發器
AFTER行觸發器是指在處理行之後被觸發的觸發器。下面以修改僱員表裡的部門號必先修改部門表的部門號,並建立行觸發器tr_update_deptno為例,說明建立AFTER行觸發器的方法。
create or replace trigger tr_update_tr_update_deptno
after update of deptno on department for each row
begin
update employee set deptno=:new.deptno where deptno=:old.deptno;
end;
/
update department set deptno=8 where deptno=5;
select ename from employee where deptno=8;

ENAME
----------
CLARK
KING
MILLER

關鍵字:DML 語句觸發器 行觸發器 BEFORE AFTER 條件謂詞

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

相關文章