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;