-- 來源表 (含更新資料)
CREATE TABLE emp1 AS SELECT * FROM emp WHERE deptno = 20;
-- 模擬更新
UPDATE emp1 SET sal = sal + 100, comm = NVL(comm,0) + 50;
-- 目標表 emp 需同步 emp1 的 sal、comm
UPDATE emp
SET (sal, comm) = (SELECT sal, comm FROM emp1 WHERE emp1.empno = emp.empno)
WHERE EXISTS (SELECT 1 FROM emp1 WHERE emp1.empno = emp.empno);
⚠ 致命陷阱:省略WHERE EXISTS子句會導致所有不匹配行的sal/comm變為NULL!Oracle UPDATE預設更新所有行,子查詢無匹配時回傳NULL而非「跳過」。
UPDATE (
SELECT a.sal AS asal, b.sal AS bsal,
a.comm AS acomm, b.comm AS bcomm
FROM emp a, emp1 b
WHERE a.empno = b.empno
)
SET asal = bsal, acomm = bcomm;
若emp1無主鍵,執行寫法二會報錯:
ORA-01779: cannot modify a column which maps to a non key-preserved table
解決:
ALTER TABLE emp1 ADD CONSTRAINT pk_emp1 PRIMARY KEY (empno);
| 維度 | 子查詢法 | 可更新視圖法 |
|---|---|---|
| 語法標準性 | ANSI SQL | Oracle擴展 |
| 可讀性 | 直觀 | 需理解Key-Preserved概念 |
| 效能 | 相近 (皆為Nested Loop) | 相近 |
| 前置條件 | 無特殊要求 | Join欄位必須唯一 (PK/UK) |
| 防NULL更新 | 靠WHERE EXISTS | 天然只更新匹配行 |
WHERE empno IN (SELECT empno FROM emp1)) 防止誤更新為NULLMERGE語句 (10g+):MERGE INTO emp USING emp1 ON (emp.empno=emp1.empno) WHEN MATCHED THEN UPDATE SET sal=emp1.sal, comm=emp1.comm