視圖定義包含 WHERE 條件時,若直接對視圖執行 INSERT/UPDATE,可能導致資料「脫離」視圖範圍,造成後續查詢視圖看不到該資料。
-- 基礎表
CREATE TABLE employee (
id NUMBER PRIMARY KEY,
name VARCHAR2(50),
dept NUMBER,
job VARCHAR2(50),
hiredate DATE
);
-- 僅顯示部門 10 的視圖
CREATE VIEW emp_view2 AS
SELECT id, name, dept, job, hiredate
FROM employee
WHERE dept = 10;
-- 透過視圖更新部門為 20
UPDATE emp_view2 SET dept = 20 WHERE dept = 10;
-- 執行成功!但視圖現在查無資料 (部門 10 已無員工)
SELECT * FROM emp_view2; -- 空結果
資料仍在基礎表中,但不再符合視圖定義條件,導致視圖「失效」。
CREATE OR REPLACE VIEW emp_view2 AS
SELECT id, name, dept, job, hiredate
FROM employee
WHERE dept = 10
WITH CHECK OPTION;
-- 再次嘗試更新部門
UPDATE emp_view2 SET dept = 20 WHERE dept = 10;
-- 錯誤:ORA-01402: view WITH CHECK OPTION where-clause violation
資料庫攔截違反視圖條件的 DML,保護視圖資料完整性。
-- 嘗試插入部門 20 的員工
INSERT INTO emp_view2 (id, name, dept, job, hiredate)
VALUES (999, 'TEST', 20, 'CLERK', SYSDATE);
-- 錯誤:ORA-01402: view WITH CHECK OPTION where-clause violation
-- 基礎視圖:部門 10
CREATE VIEW v_dept10 AS
SELECT * FROM employee WHERE dept = 10;
-- 衍生視圖:薪資 > 5000
CREATE VIEW v_dept10_highsal AS
SELECT * FROM v_dept10 WHERE sal > 5000
WITH CHECK OPTION; -- 只檢查 sal > 5000
-- 衍生視圖加上 CASCADED (預設)
CREATE VIEW v_dept10_highsal_c AS
SELECT * FROM v_dept10 WHERE sal > 5000
WITH CASCADED CHECK OPTION; -- 檢查 sal > 5000 AND dept = 10
-- 衍生視圖加上 LOCAL
CREATE VIEW v_dept10_highsal_l AS
SELECT * FROM v_dept10 WHERE sal > 5000
WITH LOCAL CHECK OPTION; -- 只檢查 sal > 5000
| 選項 | 檢查範圍 | 說明 |
|---|---|---|
WITH CHECK OPTION (預設 CASCADED) | 自身 + 所有底層視圖條件 | 最嚴格,確保完全符合視圖鏈定義 |
WITH CASCADED CHECK OPTION | 自身 + 所有底層視圖條件 | 明確指定級聯檢查 |
WITH LOCAL CHECK OPTION | 僅自身條件 | 較寬鬆,不檢查底層視圖條件 |
查詢 USER_UPDATABLE_COLUMNS 確認視圖欄位是否可更新:
SELECT table_name, column_name, updatable, insertable, deletable
FROM user_updatable_columns
WHERE table_name = 'EMP_VIEW2';
WHERE 條件且需支援 DML 的視圖,**務必加上 WITH CHECK OPTION**CASCADED (預設) 確保完整性INSTEAD OF 觸發器控制 DML 行為WITH READ ONLY 視圖本身禁止 DML,無需 CHECK OPTION