Oracle instead of 觸發器詳解

1 概述

本來是不能在 視圖 上 insert、update、delete 數據的,創建 instead of 觸發器後,就可以了。

  • 實質: 觸發引起 表 的數據發現了變化,從而讓 視圖 查詢的結果變化!

2 語法

instead of 觸發器的侷限性:

  • 只適用於視圖,不能作用於表上
  • 不能指定 before 和 after 選項
  • 必須包含 for each row 選項
CREATE OR REPLACE TRIGGER <觸發器名稱>
   INSTEAD OF INSERT OR UPDATE OR DELETE ON <視圖名>
   FOR EACH ROW -- 必填,且唯一
BEGIN
   pl/sql 語句;
END;

3 實例

1 創建兩張表:

CREATE TABLE stu_info (
  ID   NUMBER(10),
  NAME VARCHAR2(30)
);

CREATE TABLE stu_sex (
  ID   NUMBER(10),
  sex  VARCHAR2(2)
);

INSERT INTO stu_info(ID, NAME) VALUES(1, '瑤瑤');
INSERT INTO stu_info(ID, NAME) VALUES(2, '倩倩');

INSERT INTO stu_sex(ID, sex) VALUES(1, '女');
INSERT INTO stu_sex(ID, sex) VALUES(2, '女');
-- COMMIT 或者 手動提交, 以下同

2 創建視圖:

CREATE OR REPLACE VIEW vw_stu_info AS 
SELECT si.Id, 
       si.NAME, 
       ss.sex
  FROM stu_info SI,
       stu_sex  SS
 WHERE SS.ID = SI.ID;

若直接在視圖上進行 dml 語句,會報錯:

-- ORA-01779: 無法修改與非鍵值保存表對應的列
INSERT INTO vw_stu_info(ID, NAME, sex) VALUES(3, '優優', '男');

3 創建 instead of 觸發器:

CREATE OR REPLACE TRIGGER tr_instead_vw_stu_info
   INSTEAD OF INSERT OR UPDATE OR DELETE ON vw_stu_info
   FOR EACH ROW -- 必填,且唯一
BEGIN
   CASE
      WHEN inserting THEN
         INSERT INTO stu_info (id, NAME) VALUES (:new.id, :new.name);
         INSERT INTO stu_sex (id, sex) VALUES (:new.id, :new.sex);
      WHEN updating THEN
         INSERT INTO stu_info (id, NAME) VALUES (:new.id, :new.name);
         INSERT INTO stu_sex (id, sex) VALUES (:new.id, :new.sex);
      
   -- DELETE FROM stu_info t WHERE t.id = :old.id AND t.name = :old.name;
   -- DELETE FROM stu_sex t WHERE t.id = :old.id AND t.sex = :old.sex;
      ELSE
         -- deleting
         raise_application_error(-2000, '禁止刪除操作!');
   END CASE;
END;

測試:

INSERT INTO vw_stu_info(ID, NAME, sex) VALUES(3, '優優', '男');
UPDATE vw_stu_info t SET t.name = '哥哥' WHERE t.id = 3;
DELETE FROM vw_stu_info t WHERE t.ID = 3;

在這裏插入圖片描述

4 擴展

Oracle 觸發器詳解(trigger)

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