CREATE [OR REPLACE] [FORCE] VIEW [schema.]view_name
[(col_alias1, col_alias2, ...)]
AS subquery
[WITH CHECK OPTION [CONSTRAINT constr_name]]
[WITH READ ONLY];
| 子句 | 核心作用 | 常見誤區 |
|---|---|---|
OR REPLACE | 替換同名視圖,**保留授權** | 以為會保留相依 PL/SQL 狀態(實則變 INVALID) |
FORCE | 基表不存在/無權限也能建,狀態 INVALID | 以為永久有效(基表就緒前查詢會報錯) |
| 別名列表 | 對應 SELECT 列,**函數/運算式必須別名** | 忘記給 AVG(SAL) 別名導致建立失敗 |
WITH CHECK OPTION | DML 時檢查新行是否滿足子查詢 WHERE | 以為能檢查所有業務規則(僅檢視圖 WHERE 條件) |
WITH READ ONLY | 禁止任何 DML | 以為 SELECT 也受限(不影響) |
| 類型 | 定義特徵 | INSERT | UPDATE | DELETE | 典型場景 |
|---|---|---|---|---|---|
| Simple | 單表、無函數/群組、含 PK/所有 NOT NULL | ✓ | ✓ | ✓ | 權限過濾、欄位掩碼 |
| Join | 多表 JOIN | 條件✓ | 條件✓ | ✓ | 多表邏輯整合 |
| Complex | 含函數/群組/DISTINCT/子查詢/集合運算 | ✗ | ✗ | ✗ | 報表、聚合、轉換 |
| Read-Only | 加 WITH READ ONLY | ✗ | ✗ | ✗ | 純查詢、防誤改 |
**定義**:基表的 PK/UK 在 View 中**仍保持唯一** → Key-Preserved。
鐵律:
WITH CHECK OPTION 時:Join 條件欄位、基表其他共同欄位**不可更新**;非共同欄位可更新。DELETE 允許(即使有 CHECK OPTION)。CREATE VIEW V_EMP_DEPT AS
SELECT e.EMPNO, e.ENAME, e.SAL, d.DNAME, d.LOC
FROM EMP e, DEPT d
WHERE e.DEPTNO = d.DEPTNO;
ENAME, SAL(EMP 欄位)。DNAME, LOC, DEPTNO(Join 欄位/非 Key-Preserved)。INSERT 需提供 EMP 所有 NOT NULL 欄位。CREATE FORCE VIEW V_FUTURE AS SELECT c1, c2 FROM NOT_YET_EXIST; -- WARNING: INVALID
CREATE TABLE NOT_YET_EXIST (c1 NUMBER PRIMARY KEY, c2 VARCHAR2(20));
SELECT * FROM V_FUTURE; -- 自動編譯 → VALID
適用:大型專案並行開發、遷移腳本順序不確定。
| 操作 | 語法 | 授權 | 相依物件 |
|---|---|---|---|
| 修改定義 | CREATE OR REPLACE VIEW v AS ... | **保留** | **變 INVALID**(需重編譯) |
| 重新編譯 | ALTER VIEW v COMPILE; | 不變 | 成功則 VALID,失敗則 INVALID |
| 刪除 | DROP VIEW v; | **移除** | **變 INVALID** |
部署最佳實踐:CREATE OR REPLACE VIEW ... 後緊跟批量重編譯:
BEGIN
FOR r IN (SELECT object_name, object_type
FROM USER_OBJECTS
WHERE STATUS = 'INVALID'
AND OBJECT_TYPE IN ('VIEW','PROCEDURE','FUNCTION','PACKAGE','TRIGGER'))
LOOP
EXECUTE IMMEDIATE 'ALTER ' || r.OBJECT_TYPE || ' ' || r.OBJECT_NAME || ' COMPILE';
END LOOP;
END;
/
-- 定義文本
SELECT view_name, text FROM USER_VIEWS;
-- 欄位資訊
SELECT * FROM USER_TAB_COLUMNS WHERE TABLE_NAME = 'V_EMP_DEPT';
-- 可更新欄位(關鍵!)
SELECT column_name, insertable, updatable, deletable
FROM USER_UPDATABLE_COLUMNS
WHERE TABLE_NAME = 'V_EMP_DEPT';
Oracle 執行查詢視圖時,將**視圖定義與外層查詢合併**為單一查詢塊(Query Transformation),再優化。等同直接寫合併後的 SQL。
WITH CHECK OPTION / WITH READ ONLY。ROWNUM、MODEL、XML 等特殊子句。_OPTIMIZER_VIEW_MERGING = FALSE(隱藏參數,勿動)。FAST REFRESH。WITH 子句 (CTE) 或拆分邏輯。WITH CHECK OPTION View 授權應用帳號,基表僅 DBA 可見。V_ + 業務域 + 用途(如 V_HR_EMP_SALARY_MASKED)。| 現象 | 根因 | 對策 |
|---|---|---|
| View 查詢慢 | 合併後計畫差、缺索引、統計過期 | 看合併後計畫(EXPLAIN PLAN FOR SELECT * FROM V)、補索引、收集統計、考慮 MV |
| DML 報 ORA-01779 | 修改非 Key-Preserved 表欄位 | 只改 PK 保留表、或拆分 View |
| OR REPLACE 後應用報錯 | 相依 PL/SQL 變 INVALID | 部署腳本包含批量重編譯 |
| FORCE View 長期 INVALID | 基表永未建立/拼寫錯誤 | 定期查 USER_OBJECTS WHERE STATUS='INVALID' AND OBJECT_TYPE='VIEW' |
| WITH CHECK OPTION 不生效 | 子查詢含非確定性函數/偽欄 | 簡化 WHERE 條件、移除函數 |
View 是**邏輯層封裝**利器:Simple View 給安全與簡化,Join View 給多表整合(**Key-Preserved 是靈魂**),Complex View 給報表聚合(不可 DML、慎用高頻)。掌握 OR REPLACE 保留授權、FORCE 解耦順序、WITH CHECK OPTION 守護完整性、MATERIALIZED VIEW 解決效能瓶頸、USER_UPDATABLE_COLUMNS 精準判斷 DML 能力,即可駕馭 View 全生命週期。**記住:視圖不存資料,只存邏輯;合併後的計畫才是真相。**