Oracle 第8章 觸發器、內置程序包


Oracle 第7章 子程序、程序包

Oracle 第8章 觸發器、內置程序包


1、技術目標

  • 應用觸發器
  • 使用內置程序包


2、什麼是觸發器

  • 觸發器是當特定事件出現時自動執行的存儲過程
  • 特定事件可以是執行更新的DML語句和DDL語句
  • 觸發器不能被顯式調用,存儲過程可以顯示調用


觸發器的功能 有:

  • 自動生成數據
  • 自定義複雜的安全權限
  • 提供審計和日誌記錄
  • 啓用複雜的業務邏輯


觸發器可以與特定的表或視圖相關聯,用於檢查對錶/視圖所做的數據修改,
當執行insert、delete、update語句時,可激活觸發器代碼

3、如何創建觸發器


創建觸發器的語法 爲:

CREATE [OR REPLACE] TRIGGER trigger_name
{AFTER | BEFORE | INSTEAD OF}
{insert | delete | update [OF column[, column] ...]}
[OR {insert | delete | update [OF column[, column] ...] }]
ON
[schema.]table_or_view_name
[REFERENCING [NEW AS new_row_name] [OLD AS old_row_name]]
[FOR EACH ROW]
[WHEN (condition)]
[DECLARE
    variable_declation]
BEGIN
    statements;
[EXCEPTION
    exception_handlers]
END [trigger_name];

語法說明:

AFTER | BEFORE,指在事件發生之前或之後激活觸發器
INSTEAD OF,表示可以執行觸發器代碼來代替導致觸發器調用的事件
insert | delete | update,指定構成觸發器事件的數據操縱類型,
    update可指定列列表
REFERENCING,指定新行(即將更新)和舊行(更新前)的其他名稱,
    默認爲NEW和OLD
table_or_view_name,指要創建觸發器的表或視圖的名稱
FOR EACH ROW,指定是否對受影響的每行都執行觸發器,即行級觸發器,
    如不使用此句,則爲語句級觸發器
WHEN,限制執行觸發器的條件,該條件可包括新舊數據值的檢查
DECLARE...END,一個標準的PL/SQL塊

使用: 在Emp表創建觸發器,

CREATE OR REPLACE TRIGGER biu_emp_deptno
--在添加或修改deptNo字段之前觸發
BEFORE INSERT OR UPDATE OF deptNo
ON Emp
--行級觸發器
FOR EACH ROW
--列deptNo的新值不等於40
WHEN (New.deptNo <> 40)
BEGIN
    --將comm列設置爲0
    :New.comm := 0;
END;
/

 


注意:使用SHOW ERRORS命令可查看創建觸發器時出現的錯誤

4、觸發器的組成部分


觸發器由以下3個部分 組成:

    觸發語句 ,定義激活觸發器的 DML 事件和 DDL 事件,如:
        BEFORE INSERT OR UPDATE OF deptNo
        ON Emp
        --行級觸發器
        FOR EACH ROW
       
        這段代碼表示,當對Emp表執行insert語句或對Emp表的
        deptNo列執行update語句時,觸發器會在受影響的每一行
        上執行一次
   
    觸發限制 ,執行觸發器的條件,該條件必須爲真才能激活觸發器,如:
        --列deptNo的新值不等於40,觸發器會執行
        WHEN (New.deptNo <> 40)
       
    觸發操作 ,一些 SQL 語句和代碼,在發出了觸發器語句且觸發限制的
        值爲真時運行,如:
        BEGIN
            --將comm列設置爲0
            :New.comm := 0;
        END;
       

5、觸發器的類型及使用

觸發器有如下的類型:



每種觸發器的作用:



使用1: 應用行級觸發器,

--創建表TEST_TRG
CREATE TABLE TEST_TRG (ID NUMBER, NAME VARCHAR2(20));
--創建序列SEQ_TEST
CREATE SEQUENCE SEQ_TEST;
--爲TEST_TRG表創建行級觸發器
CREATE OR REPLACE TRIGGER BI_TEST_TRG
--在insert(添加)或者update(修改)ID字段時觸發
BEFORE INSERT OR UPDATE OF ID
ON TEST_TRG --指定TEST_TRG表
FOR EACH ROW --設置爲行級觸發器
--觸發器語句部分
BEGIN
     --判斷是不是insert語句
     IF INSERTING THEN
       --如果是insert操作,將序列的值設置給ID列
       SELECT SEQ_TEST.NEXTVAL INTO :NEW.ID FROM DUAL;
     ELSE
       --如果不是insert操作,不能修改ID列的值
       RAISE_APPLICATION_ERROR(-20020, '不允許更新ID值!');
     END IF;
END;
/

 


注意:如果一個觸發器由多種語句觸發,可用INSERTING、UPDATING、
DELETING這些關鍵字進行檢查,對應語句類型


使用2: 應用語句級觸發器,

CREATE OR REPLACE TRIGGER trgdemo
   AFTER INSERT OR UPDATE OR DELETE
   ON order_master
BEGIN
   --根據語句類型輸出信息
   IF UPDATING THEN
     DBMS_OUTPUT.PUT_LINE('已更新ORDER_MASTER中的數據');
   ELSIF DELETING THEN
     DBMS_OUTPUT.PUT_LINE('已刪除ORDER_MASTER中的數據');
   ELSIF INSERTING THEN
     DBMS_OUTPUT.PUT_LINE('已在ORDER_MASTER中插入數據');
   END IF;
END;
/

 


注意:語句級觸發器時CREATE TRIGGER命令所創建觸發器的默認類型

使用3: 應用INSTEAD OF觸發器,同時向兩個表中插入值,

--創建視圖
CREATE VIEW ord_view AS
SELECT order_master.orderno, order_master.ostatus,
    order_detail.qty_deld, order_detail.qty_ord
FROM order_master, order_detail
WHERE order_master.orderno = order_detail.orderno;

--創建INSTEAD OF觸發器
CREATE OR REPLACE TRIGGER order_mast_insert
  INSTEAD OF UPDATE ON ord_view
  --爲NEW關鍵字取別名n
  REFERENCING NEW AS n
  FOR EACH ROW
  DECLARE
    --定義遊標,訪問order_master表
    CURSOR ecur IS SELECT * FROM order_master
    WHERE order_master.orderno = :n.orderno;
    --定義遊標,訪問order_detail表
    CUSEOR dcur IS
    select * from order_detail
    WHERE order_detail.orderno = :n.orderno;
    --定義遊標變量
    a ecur%ROWTYPE;
    b dcur%ROWTYPE;
  BEGIN
    --打開遊標
    OPEN ecur;
    OPEN dcur;
    --讀取行
    FETCH ecur into a;
    FETCH dcur into b;
    --判斷是否有行
    IF dur%NOTFOUND THEN --沒有
        --添加記錄
        INSERT INTO order_master (orderno, ostatus)
        VALUES (:n.orderno, :n.ostatus);
    ELSE --有
        --修改記錄
        UPDATE order_master SET order_master.ostatus = :n.ostatus
        WHERE order_master.orderno = :n.orderno;
    END IF;

    IF ecur%NOTFOUND THEN
        INSERT INTO order_detail (qty_ord, qty_deld, orderno)
        VALUES(:n.qty_ord, :n.qty_deld, :n.orderno);
    ELSE
        UPDATE order_detail SET
        order_detail.qty_ord = :n.qty_ord,
        order_detail.qty_deld = :n.qty_deld
        WHERE order_detail.orderno = :n.orderno;
    END IF;
    --關閉遊標
    CLOSE ecur;
    CLOSE dcur;
  END;
/

 


注意:使用INSTEAD OF觸發器有如下的限制,

  • 只能在行級使用,不能在語句級使用
  • 只能應用於視圖,不能應用於表


使用4: 應用模式(DDL)觸發器,對用戶刪除的對象進行日誌記錄,
創建模式觸發器的語法 爲:

    CREATE OR REPLACE TRIGGER trigger_name
    {BEFORE | AFTER} trigger_event
    ON [schema.]SCHEMA
    WHEN (trigger_condition)
    trigger_body;

--創建日誌記錄表
CREATE TABLE dropped_obj
(
    obj_name VARCHAR2(30),
    obj_type VARCHAR2(20),
    drop_date DATE
);
--創建觸發器
CREATE OR REPLACE TRIGGER log_drop_obj
--在執行drop語句後觸發
AFTER DROP ON SCHEMA
BEGIN
    --將被刪除對象的信息添加到日誌記錄表中
    INSERT INTO dropped_obj
    VALUES (ORA_DICT_OBJ_NAME, ORA_DICT_OBJ_TYPE, SYSDATE);
END;
/

 

使用5: 應用數據庫級觸發器,在數據庫啓動後執行,

CREATE OR REPLACE TRIGGER system_startup
--系統啓動時觸發
AFTER STARTUP ON DATEBASE
BEGIN
    --加入所需代碼
END;
/

6、啓動、禁用、刪除觸發器,查看觸發器信息

啓用和禁用觸發器:
ALTER TRIGGER 觸發器名 DISABLE; --禁用
ALTER TRIGGER 觸發器名 ENABLE; --啓用

刪除觸發器:
DROP TRIGGER 觸發器名;

查看觸發器信息,使用USER_TRIGGERS數據字典:

使用1:
查看爲表EMP設置的觸發器名
select TRIGGER_NAME from USER_TRIGGERS
WHERE TABLE_NAME = 'EMP';

使用2: 查看觸發器BIU_EMP_DEPTNO的類型、觸發事件、觸發條件,
select TRIGGER_TYPE, TRIGGERING_EVENT, WHEN_CLAUSE
from USER_TRIGGERS
WHERE TRIGGER_NAME = 'BIU_EMP_DEPTNO';

7、內置程序包

Oracle提供了許多內置程序包,用於擴展數據庫功能,數據庫用戶SYS
擁有所有程序包,程序包被定義爲公有同義詞,並將執行權限授予了
PUBLIC用戶組,任何用戶都可訪問,部分內置程序包如下:

 



8、總結

  • 觸發器是當特定事件出現時自動執行的存儲過程
  • 觸發器分爲 DML 觸發器、DDL 觸發器和數據庫級觸發器三種類型
  • DML觸發器的三種類型爲行級觸發器、語句級觸發器和INSTEAD OF觸發器
  • 瞭解一些常用的內置程序包


Oracle 第7章 子程序、程序包

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章