| 選項 | 行為 | 適用場景 |
| OR REPLACE | 視圖存在則重建,保留權限與相依物件 | 開發迭代、腳本重跑 |
| FORCE | 基表不存在也強制建立 (編譯時驗證) | 部署腳本順序不固定、跨 Schema 參考 |
| NOFORCE (預設) | 基表必須存在且有權限 | 嚴格模式 |
| alias 別名清單 | 為 SELECT 列指定顯示名稱,須與列數一致 | 隱藏原欄名、統一報表介面 |
| WITH CHECK OPTION | DML 操作必須符合視圖 WHERE 條件,否則報錯 | 資料隔離、多租戶安全 |
| WITH READ ONLY | 禁止任何 DML (INSERT/UPDATE/DELETE) | 唯讀報表、防誤改 |
經典範例:部門薪資彙總視圖
CREATE OR REPLACE VIEW dept_salary_vw (
dept_name, min_sal, max_sal, avg_sal, emp_cnt
) AS
SELECT d.dname,
MIN(e.sal), MAX(e.sal), AVG(e.sal), COUNT(*)
FROM emp e
JOIN dept d ON e.deptno = d.deptno
GROUP BY d.dname
WITH READ ONLY; -- 報表視圖禁止寫入
簡單視圖 vs 複雜視圖 (可更新性判斷)
| 特徵 | 簡單視圖 (可直接 DML) | 複雜視圖 (需 INSTEAD OF Trigger) |
| 基表數量 | 單一基表 | 多表 JOIN |
| 聚合/分組 | 無 GROUP BY / 聚合函數 | 有 GROUP BY、DISTINCT、聚合 |
| 集合運算 | 無 UNION/INTERSECT/MINUS | 有集合運算 |
| 子查詢 | 無子查詢 (或僅標量子查詢) | 包含子查詢 |
| 虛擬欄/運算式 | 無衍生欄位 | 有運算式、函數結果欄 |
| WITH CHECK OPTION | 支援 | 不支援 (需觸發器實現) |
進階模式 1:安全性隔離 - WITH CHECK OPTION
-- 僅允許存取自己部門資料
CREATE OR REPLACE VIEW emp_self_vw AS
SELECT empno, ename, sal, deptno
FROM emp
WHERE deptno = SYS_CONTEXT('USERENV', 'CLIENT_IDENTIFIER') -- 應用設定 Context
WITH CHECK OPTION; -- 防止 UPDATE deptno 竄改他部門資料
進階模式 2:複雜視圖寫入 - INSTEAD OF TRIGGER
CREATE OR REPLACE VIEW emp_dept_vw AS
SELECT e.empno, e.ename, e.sal, d.dname, d.loc
FROM emp e JOIN dept d ON e.deptno = d.deptno;
CREATE OR REPLACE TRIGGER emp_dept_vw_iud
INSTEAD OF INSERT OR UPDATE OR DELETE ON emp_dept_vw
FOR EACH ROW
DECLARE
v_deptno dept.deptno%TYPE;
BEGIN
IF INSERTING OR UPDATING THEN
-- 確保部門存在或自動建立
SELECT deptno INTO v_deptno FROM dept WHERE dname = :NEW.dname;
EXCEPTION WHEN NO_DATA_FOUND THEN
SELECT dept_seq.NEXTVAL INTO v_deptno FROM dual;
INSERT INTO dept (deptno, dname, loc) VALUES (v_deptno, :NEW.dname, :NEW.loc);
END IF;
IF INSERTING THEN
INSERT INTO emp (empno, ename, sal, deptno)
VALUES (:NEW.empno, :NEW.ename, :NEW.sal, v_deptno);
ELSIF UPDATING THEN
UPDATE emp SET ename = :NEW.ename, sal = :NEW.sal, deptno = v_deptno
WHERE empno = :OLD.empno;
ELSIF DELETING THEN
DELETE FROM emp WHERE empno = :OLD.empno;
END IF;
END;
/
視圖效能優化技巧
- Predicate Pushing:優化器會嘗試將外層 WHERE 條件下推至視圖內部,複雜視圖可能受阻,可用
/*+ PUSH_PRED(view_alias) */ 強制。
- Materialized View 替代:極複雜聚合視圖頻繁查詢,改用 MV + 定時刷新,查詢效能提升數量級。
- 版本控管:
OR REPLACE 會導致相依 PL/SQL 失效 (需重編譯),生產環境建議 DROP VIEW ... CASCADE CONSTRAINTS 後重建,並同步部署相依程式碼。
- 上一篇文章: Oracle 建立分區表與索引語法全攻略
- 下一篇文章: Oracle 表空間建立語法完整指南
Copyright ©
程式碼之家 All Rights Reserved