當對包含**運算式/虛擬欄位**的視圖執行 INSERT/UPDATE/DELETE 時,Oracle 拋出 ORA-01733: virtual column not allowed here。本文重現場景、解析原因並提供解決方案。
視圖類型 是否可 DML 原因 單表簡單視圖 (無運算式、無聚合、無 DISTINCT) ✅ 可 可直接映射到基表欄位 含運算式/虛擬欄位視圖 ❌ 不可 目標欄位非實際儲存欄位,無法反向映射 UNION/UNION ALL 視圖 ❌ 不可 (12c 前) 無法判斷資料來自哪個基表 JOIN 視圖 (含鍵保護) ⚠️ 條件可 需滿足 Key-Preserved Table 條件 WITH CHECK OPTION 視圖 ✅ 可 限制 DML 符合視圖 WHERE 條件 核心規則:Oracle 要求 DML 目標欄位必須對應**基表實際儲存欄位**。視圖中的運算式結果 (如
A+B、UPPER(NAME)、UNION ALL合併欄位) 皆為虛擬欄位,不支援 DML。官方錯誤碼解釋
解決方案
方案一:直接操作基表 (標準做法)
CREATE OR REPLACE TRIGGER SYSTEM.TT_IOU INSTEAD OF UPDATE ON SYSTEM.TT FOR EACH ROW BEGIN -- 業務邏輯:假設 A>0 更新 HR.TT,否則更新 SCOTT.TT IF :NEW.A > 0 THEN UPDATE HR.TT SET A = :NEW.A WHERE A = :OLD.A; ELSE UPDATE SCOTT.TT SET A = :NEW.A WHERE A = :OLD.A; END IF; END; / -- 現在可以更新視圖 UPDATE SYSTEM.TT SET A = 3 WHERE A = 1; -- 觸發器自動路由到 HR.TT方案三:重新設計視圖結構
EDITIONABLE VIEW 配合 Edition-Based Redefinition