日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

PL/SQL -- DML 触发器

發布時間:2025/3/15 数据库 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 PL/SQL -- DML 触发器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

--=======================

-- PL/SQL --> DML 觸發器

--=======================

???

??? 何謂觸發器?簡言之,是一段命名的PL/SQL代碼塊,只不過該代碼塊在特定的條件下被觸發并且執行。對于這樣的代碼我們稱之為觸發器

。觸發器根據觸發類型的不同又分為不同級別的觸發器,下面將給出觸發器的分類,定義,以及使用的示例。

?

一、觸發器的相關概念

??? 1.觸發器的分類

??????? 通常根據觸發條件以及觸發級別的不同分為DML觸發器,INSTEAD OF 觸發器,系統事件觸發器。

??????? DML觸發器

??????????? ORACLE DML語句進行觸發,可以在DML操作前或操作后進行觸發,并且可以對每個行或語句操作上進行觸發。

??????? INSTEAD OF 觸發器

??????????? ORACLE里,對于簡單視圖,可以直接使用DML進行操作,而復雜視圖則不能直接使用DML,因此INSTEAD OF 觸發器應運而生。

??????????? INSTEAD OF 觸發器主要是為解決復雜視圖不能執行DML而創建。

??????? 系統事件觸發器?

??????????? ORACLE 數據庫系統的事件中進行觸發,ORACLE系統的啟動與關閉等.使用系統觸發器,便于系統跟蹤,監測數據庫變化情況等。

?

??? 2.觸發器的組成(一段PL/SQL代碼塊,可以由PL/SQL,Java,C進行開發,特定事件發生將被觸發)

??????? a.觸發事件

??????????? Oracle 啟動、關閉

??????????? Oracle 錯誤消息

??????????? 用戶登錄與斷開會話

??????????? 特定的表、視圖上的DML操作

??????????? 基于schemaDDL操作

??????? b.觸發時間

??????????? 即該TRIGGER 是在觸發事件發生之前(BEFORE)還是之后(AFTER)觸發,也就是觸發事件和該TRIGGER 的操作順序。?

??????? c.觸發器本身

??????????? 指實際的觸發代碼,當觸發事件發生后,觸發器代碼決定將做何種操作。

??????????? 觸發器代碼大小不能超過32k,對于超長的代碼可以將其置于單獨的存儲過程,然后在觸發器中使用call 調用該過程。

??????????? 觸發器代碼只能包含DQLDML,而不能包含DDL以及事務控制語言(COMMIT,ROLLBACK,SAVEPOINT)

??????? d.觸發頻率

??????????? 說明觸發器內定義的動作被執行的次數。即語句級(STATEMENT)觸發器和行級(ROW)觸發器。

??????????? 語句級(STATEMENT)觸發器:是指當某觸發事件發生時,該觸發器只執行一次。

??????????? 行級(ROW)觸發器:是指當某觸發事件發生時,對受到該操作影響的每一行數據,觸發器都單獨執行一次。

??? 3.觸發器的用途

??????? 控制DDL語句的行為,如通過更改、創建或重命名對象

??????? 控制DML語句的行為,如插入、更新和刪除

??????? 實施參照完整性、復雜業務規則和安全性策略

??????? 在修改視圖中的數據時控制和重定向DML語句

??????? 通過創建透明日志來審核系統訪問和行為的信息

?

二、創建DML觸發器語法描述

??? 1.創建觸發器的語法

??????? CREATE [OR REPLACE] TRIGGER trigger_name

??????? {BEFORE | AFTER | INSTEAD OF}????

??????? {INSERT | DELETE | UPDATE [OF column [, column …]]}??????????????? ??--定義觸發類型,即那一種或多種DML以及特定的列

??????? ON {[schema.] table_name | [schema.] view_name}?????????????????????? --特定的觸發對象,表或視圖

??????? [REFERENCING {OLD [AS] old | NEW [AS] new| PARENT as parent}]

??????? [FOR EACH ROW ]?????????????????????????????????????????????????????? --定義觸發器為行級觸發器

??????? [WHEN condition]

??????? BEGIN

??????????? trigger_body;

??????? END;

???

??????? BEFORE | AFTER | INSTEAD OF

??????????? BEFORE指在執行DML之前觸發觸發器,AFTER則是指在DML執行之后觸發觸發器

??????????? INSTEAD OF觸發器只針對視圖和對象視圖建立,而不能對表、模式和數據庫建立INSTEAD OF 觸發器

???????????

??????? [REFERENCING {OLD [AS] old | NEW [AS] new| PARENT as parent}]

??????????? 說明相關名稱,在行觸發器的PL/SQL塊和WHEN 子句中可以使用相關名稱參照當前的新,舊列值,默認的相關名稱分別為OLDNEW

??????????? 觸發器的PL/SQL塊中應用相關名稱時,必須在它們之前加冒號(:),但在WHEN子句中則不能加冒號。

???????????

??????? [FOR EACH ROW ]

??????????? 定義觸發器為行級觸發器。

??????????? 行級觸發器和語句級觸發器的區別表現在:一個DML語句可能操縱多行,也可能操縱一行,使用行級觸發器,不論是一行還是多

??????????? 行數據被操縱,行觸發器為該DML的每一行觸發一次觸發器操作。語句級觸發器將整個語句操作作為觸發事件,不論該語句影響

??????????? 了多少行,僅僅觸發一次觸發器。

??????????? 當省略FOR EACH ROW 選項時,BEFORE AFTER 觸發器為語句觸發器,而INSTEAD OF 觸發器則為行觸發器。???

??????? ???

??????? [WHEN condition]

??????????? 觸發條件,當條件為TRUE時,觸發器代碼才會被執行,對于DML觸發器,僅僅允許在行級觸發器上指定觸發條件。

??????????? condition 為一個邏輯表達時,其中必須包含相關名稱,而不能包含查詢語句,也不能調用PL/SQL 函數。

WHEN 子句可通過引用newold偽記錄、一個組件選擇符和一個列名來訪問偽字段。

??????????? WHEN 子句不能用在INSTEAD OF 行觸發器和其它類型的觸發器中。

???????????

??? 2.DML觸發器的觸發順序

??????? a.在單行數據上的觸發順序(觸發代碼僅被執行一次)

??????????? BEFORE 語句級觸發器

??????????????? BEFORE 行級觸發器

??????????????? AFTER 行級觸發器

??????????? AFTER 語句級觸發器

??????? b.在多行數據上的觸發順序(語句級觸發器僅被執行一次,行級觸發器在每個作業行上被執行一次)

??????????? BEFORE 語句級觸發器

??????????????? BEFORE 行級觸發器

??????????????? AFTER 行級觸發器

??????????????? BEFORE 行級觸發器

??????????????? AFTER 行級觸發器

??????????? AFTER 語句級觸發器

???????????

???

??? 3.觸發器中的條件謂詞

??????? ORACLE 提供三個參數INSERTING, UPDATING, DELETING 用于判斷觸發了哪些操作。

??????? INSERTING:如果觸發語句是INSERT 語句,則為TRUE,否則為FALSE

??????? UPDATING:如果觸發語句是UPDATE語句,則為TRUE,否則為FALSE

??????? DELETING:如果觸發語句是DELETE 語句,則為TRUE,否則為FALSE

?

??? 4.NEWOLD 限定符的使用

??????? 使用被插入、更新或刪除的記錄中的列值,可以使用NEWOLD限定符來表示

??????? :old 修飾符訪問操作完成前列的值

??????? :new 修飾符訪問操作完成后列的值

???????

??????? 限定符??? INSERT操作???? UPDATE操作? DELETE操作

??????? ---------? --------------? -----------? ----------

??????? OLD??????? NULL??????????? 有效???????? 有效

??????? NEW??????? 有效?????????? 有效???????? NULL

?

三、創建DML觸發器??

??? 1.創建BEFORE 語句級觸發器

??????? sys@ORCL> drop user scott cascade;???? --刪除scott方案

?

??????? sys@ORCL> start $ORACLE_HOME/rdbms/admin/utlsampl.sql?? --重建scott方案

?

??????? sys@ORCL> grant dba to scott;? --授予Scott DBA角色

???????????????????

??????? scott@ORCL> create table emp_check(oper varchar2(30),upd_date date);??? --創建表存放emp表的更新記錄操作的跟蹤???

?

??????? CREATE OR REPLACE TRIGGER tr_before_update_emp??? --創建update觸發器

??????? ? BEFORE UPDATE ON emp??

??????? ? -- FOR EACH ROW

??????? BEGIN

??????? ? INSERT INTO emp_check

??????? ? Values

??????????? ('Before update, statement level', sysdate);

??????? END;

?

??????? scott@ORCL> select * from emp_check;? --未執行update前,跟蹤表記錄為空

?

??????? no rows selected

?

??????? scott@ORCL> update emp set sal = sal + 100 where deptno = 20;?? --更新了四條記錄

?

??????? 4 rows updated.

?

??????? scott@ORCL> select * from emp_check;???? --跟蹤表表插入了一條跟蹤記錄

?

??????? OPER?????????????????????????? UPD_DATE

??????? ------------------------------ ---------

??????? Before update, statement level 24-DEC-10

?

??????? scott@ORCL> update emp set sal = sal + 200 where empno = 7369; --更新了一條記錄,跟蹤表再次插入一條新記錄

?

??????? 1 row updated.

?

??????? scott@ORCL> select * from emp_check;

?

??????? OPER?????????????????????????? UPD_DATE

??????? ------------------------------ ---------

??????? Before update, statement level 24-DEC-10

??????? Before update, statement level 24-DEC-10???????

???

??? 2.創建 BEFORE 行級觸發器???

??????? 使用上面的代碼來創建行級觸發器,與之不同的是將上面的代碼中"-- FOR EACH ROW" "--"刪除,則創建的觸發器即為行級觸發器

??????? 代碼省略

??????????? scott@ORCL> update emp set sal = sal + 200 where deptno = 20; --再次更新deptno為的記錄,且記錄總數為四條

?

??????????? 4 rows updated.????????????????????

?

??????????? scott@ORCL> select * from emp_check;?? --emp_check中增加四條,即為update的每一行增加一條記錄

?

??????????? OPER?????????????????????????? UPD_DATE

??????????? ------------------------------ ---------

??????????? Before update, statement level 24-DEC-10

??????????? Before update, statement level 24-DEC-10

??????????? Before update, statement level 24-DEC-10

??????????? Before update, statement level 24-DEC-10

??????????? Before update, statement level 24-DEC-10

??????????? Before update, statement level 24-DEC-10???

???????????

??? 3.創建 AFTER 語句級觸發器??????

??????? CREATE TABLE audit_table_emp?? --創建一張表audit_table_emp存放emp表上DML操作的次數

??????? (

??????????? name??????? VARCHAR2(20),

??????????? ins???? INT,

??????????? upd???? INT,

??????????? del???? INT,

??????????? starttime?? DATE,

??????????? endtime???? DATE

??????? );

?

??????? CREATE OR REPLACE TRIGGER tr_audit_emp

??????? AFTER INSERT OR UPDATE OR DELETE ON emp

??????? DECLARE

??????????? v_temp INT;

??????? BEGIN

??????????? SELECT COUNT(*) INTO v_temp FROM audit_table_emp WHERE name = 'EMP';

??????????? IF v_temp = 0 THEN

??????????????? INSERT INTO audit_table_emp VALUES('EMP', 0, 0, 0, SYSDATE, NULL);

??????????? END IF;

??????????? CASE

??????????????? WHEN INSERTING THEN? --注意此例中條件謂詞的使用INSERTINGUPDATINGDELETING

??????????????????? UPDATE audit_table_emp SET ins = ins + 1, endtime = SYSDATE WHERE name = 'EMP';

??????????????? WHEN UPDATING THEN

??????????????????? UPDATE audit_table_emp SET upd = upd + 1, endtime = SYSDATE WHERE name = 'EMP';

??????????????? WHEN DELETING THEN

??????????????????? UPDATE audit_table_emp SET del = del + 1, endtime = SYSDATE WHERE name = 'EMP';

??????????? END CASE;

??????? END;???

?

??????? scott@ORCL> update emp set sal=sal+200 where empno=7788;?

?

??????? scott@ORCL> update emp set sal=sal+200 where ename='SMITH';

?

??????? scott@ORCL> delete from emp where empno=7788;?

?

??????? scott@ORCL> select * from audit_table_emp;?? --兩次更新及一次被記錄到表中

?

??????? NAME??????????????????????? INS??????? UPD??????? DEL STARTTIME ENDTIME

??????? -------------------- ---------- ---------- ---------- --------- ---------

??????? EMP?????????????????????????? 0????????? 2????????? 1 24-DEC-10 24-DEC-10??

?

??????? scott@ORCL> update emp set sal=sal+100 where deptno=10;

?

??????? 3 rows updated.?? --更新了行,當audit_table_emp表中僅僅記錄一次,UPD的值增加到

?

??????? scott@ORCL> select * from audit_table_emp;

?

??????? NAME??????????????????????? INS??????? UPD??????? DEL STARTTIME ENDTIME

??????? -------------------- ---------- ---------- ---------- --------- ---------

??????? EMP?????????????????????????? 0????????? 3????????? 1 24-DEC-10 24-DEC-10??????

???????

??? 4.創建 AFTER 行級觸發器

??????? CREATE TABLE audit_emp_change??? --創建audit_emp_change存放emp sal列被更新前后的值

??????? (

??????????? name??????? VARCHAR2(10),

??????????? oldsal????? NUMBER(6, 2),

??????????? newsal????? NUMBER(6, 2),

??????????? time??????? DATE

??????? );

?

??????? CREATE OR REPLACE TRIGGER tr_sal_change?

??????? AFTER UPDATE OF sal ON emp? --注意update 觸發器中使用了OF 關鍵字,當sal列發生變化時,tr_sal_change被觸發

??????? FOR EACH ROW??????????????? --使用行級觸發器

??????? --WHEN old.job='CLERK')

??????? DECLARE

??????????? v_temp INT;

??????? BEGIN

??????????? SELECT COUNT(*) INTO v_temp FROM audit_emp_change WHERE name = :old.ename;? --注意OLD NEW 的使用

??????????? IF v_temp = 0 THEN

??????????????? INSERT INTO audit_emp_change VALUES(:old.ename, :old.sal, :new.sal, SYSDATE);

??????????? ELSE

??????????????? UPDATE audit_emp_change SET oldsal = :old.sal, newsal = :new.sal, time = SYSDATE WHERE name = :old.ename;

??????????? END IF;

??????? END;

?

??????? scott@ORCL> update emp set sal=sal-100 where empno=7369;? --更新一行

?

??????? scott@ORCL> select * from audit_emp_change;??? --audit_emp_change表中記錄了一行

?

??????? NAME?????????? OLDSAL???? NEWSAL TIME

??????? ---------- ---------- ---------- ---------

??????? SMITH??????????? 1400?????? 1300 24-DEC-10

?

??????? scott@ORCL> delete from audit_emp_change;? --刪除之前的記錄

???

??????? scott@ORCL> update emp set sal=sal+200 where deptno=10;?? --更新了三行

?

??????? 3 rows updated.

?

??????? scott@ORCL> select * from audit_emp_change;?? --audit_emp_change表中記錄了三行

?

??????? NAME?????????? OLDSAL???? NEWSAL TIME

??????? ---------- ---------- ---------- ---------

??????? CLARK??????????? 2550?????? 2750 24-DEC-10

??????? KING???????????? 5100???? ??5300 24-DEC-10

??????? MILLER?????????? 1400?????? 1600 24-DEC-10?

???

??? 5.限制行級觸發器

??????? 限制行級觸發器是通過添加[WHEN condition]判斷條件,來對滿足特定condition的記錄觸發觸發器。

??????? 對于DML觸發器而言,僅僅允許在行級觸發器上指定觸發條件。

??????? 在上面第4小點創建AFTER 行級觸發器的代碼中,這一行"--WHEN old.job='CLERK')" 去掉"--",觸發器變為具有限定條件的行級

??????? 觸發器,則對特定的條件,即job='CLERK'的記錄在更新其sal時才會被觸發。演示省略。

???????

??? 6.創建DML觸發器的注意事項

??????? DML觸發器中不能包含對基表的DQL查詢操作

??????????? CREATE OR REPLACE TRIGGER tr_emp_sal

??????????? ? BEFORE UPDATE OF sal ON emp --注意update 觸發器中使用了OF 關鍵字,當sal列發生變化時,tr_emp_sal被觸發

??????????? ? FOR EACH ROW --使用行級觸發器

??????????? DECLARE

??????????? ? maxsal NUMBER(6, 2);

??????????? BEGIN

??????????? ? SELECT MAX(sal) INTO maxsal FROM emp;

??????????? ? IF :new.sal > maxsal THEN

??????????????? RAISE_APPLICATION_ERROR(-20004, 'Beyond the highest salary');

??????????? ? END IF;

??????????? END;

?

??????????? scott@ORCL> update emp set sal=5000 where empno=7369;

??????????? update emp set sal=5000 where empno=7369

??????????? *

??????????? ERROR at line 1:

??????????? ORA-04091: table SCOTT.EMP is mutating, trigger/function may not see it

??????????? ORA-06512: at "SCOTT.TR_EMP_SAL", line 4

??????????? ORA-04088: error during execution of trigger 'SCOTT.TR_EMP_SAL'????????

???????

??? 7.使用DML觸發器實現數據完整性,參照完整性

??????? 對于復雜的數據完整性,參照完整性,可以通過DML觸發器來完成普通約束所不能完成的任務

??????????? CREATE OR REPLACE TRIGGER tr_del_upd_deptno

??????????? AFTER DELETE OR UPDATE OF deptno ON dept

??????????? FOR EACH ROW

??????????? BEGIN

??????????? ? IF (UPDATING AND :old.deptno<>:new.deptno) THEN

??????????????? UPDATE emp SET deptno=:new.deptno WHERE deptno=:old.deptno;

??????????? ? END IF;

??????????? ?

??????????? ? IF DELETING THEN

??????????????? DELETE FROM emp WHERE deptno=:old.deptno;

??????????? ? END IF;

??????????? END;

?

??????????? scott@ORCL> update dept set deptno=50 where deptno=10;

?

??????????? 1 row updated.?????

?

??????????? scott@ORCL> select * from emp where deptno=10;

?

??????????? no rows selected

?

??????????? scott@ORCL> select * from emp where deptno=50;

?

??????????????? ?EMPNO ENAME????? JOB????????????? MGR HIREDATE???????? SAL?????? COMM???? DEPTNO

??????????? ---------- ---------- --------- ---------- --------- ---------- ---------- ----------

??????????????? ? 7782 CLARK????? MANAGER???????? 7839 09-JUN-81?????? 2750??????????????????? 50

??????????????? ? 7839 KING?????? PRESIDENT??????????? 17-NOV-81?????? 5300??????????????????? 50

??????????????? ? 7934 MILLER???? CLERK?????????? 7782 23-JAN-82?????? 1600???? ???????????????50

??? ?

四、管理觸發器

??? 1.查看系統中特定對象上的觸發器

??????? scott@ORCL> select trigger_name,status from user_triggers

??????? ? 2? where table_name='EMP';

?

??????? TRIGGER_NAME?????????????????? STATUS

??????? ------------------------------ --------

??????? TR_BEFORE_UPDATE_EMP?????????? ENABLED

??????? TR_AUDIT_EMP?????????????????? ENABLED

??????? TR_SEC_EMP???????????????????? ENABLED

??????? TR_SAL_CHANGE????????????????? ENABLED

??????? TR_EMP_SAL???????????????????? ENABLED?

???

??? 2.查看觸發器的源代碼

??????? scott@ORCL> col text format a65

??????? scott@ORCL> select line,text from user_source where name='TR_DEL_UPD_DEPTNO';

?

??????????? ? LINE TEXT

??????? ---------- -----------------------------------------------------------------

??????????????? ?1 TRIGGER tr_del_upd_deptno

??????????????? ?2 AFTER DELETE OR UPDATE OF deptno ON dept

??????????????? ?3 FOR EACH ROW

??????????????? ?4 BEGIN

??????? ??????? ?5?? IF (UPDATING AND :old.deptno<>:new.deptno) THEN

??????????????? ?6???? UPDATE emp SET deptno=:new.deptno WHERE deptno=:old.deptno;

??????????????? ?7?? END IF;

??????????????? ?8

??????????????? ?9?? IF DELETING THEN

??????????????? 10???? DELETE FROM emp WHERE deptno=:old.deptno;

??????????????? 11?? END IF;

??????????????? 12 END;

??? 3.禁用觸發器

??????? 當觸發器被禁用后,則表上的DML操作將不會觸發該觸發器,直到該觸發器被解除禁用(alter trigger trigger_name disable)

??????? scott@ORCL> alter trigger tr_emp_sal disable;

???????

??? 4.啟用觸發器

??????? 被禁用的觸發器可以被解除禁用(alter trigger trigger_name enable)

??????? scott@ORCL> alter trigger tr_emp_sal enable;

???

??? 5.禁用、啟用表上的所有觸發器

??????? scott@ORCL> alter table emp disable all triggers;

?

??????? scott@ORCL> alter table emp enable all triggers;

?

??? 6.重新編譯觸發器

??????? scott@ORCL> alter trigger tr_emp_sal compile;

???

??? 7.刪除觸發器

??????? scott@ORCL> drop trigger tr_emp_sal;

?

五、更多參考

有關SQL請參考

??????? SQL 基礎--> 子查詢

??????? SQL 基礎-->多表查詢

SQL基礎-->分組與分組函數

SQL 基礎-->常用函數

SQL 基礎--> ROLLUP與CUBE運算符實現數據匯總

SQL基礎-->層次化查詢(START BY ... CONNECT BY PRIOR)

?

??? 有關PL/SQL請參考

??????? PL/SQL --> 語言基礎

PL/SQL --> 流程控制

PL/SQL --> 存儲過程

PL/SQL --> 函數

PL/SQL --> 游標

PL/SQL -->隱式游標(SQL%FOUND)

PL/SQL --> 異常處理(Exception)

PL/SQL --> PL/SQL記錄

PL/SQL --> 包的創建與管理

PL/SQL --> 包重載、初始化

PL/SQL --> DBMS_DDL包的使用

PL/SQL --> DML 觸發器

PL/SQL --> INSTEAD OF 觸發器

???????

總結

以上是生活随笔為你收集整理的PL/SQL -- DML 触发器的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。