MERGE (Oracle 9i 引入) 允許根據來源資料與目標表比對,單次執行即可完成「存在則更新、不存在則插入」(UPSERT) 邏輯,避免分開執行的競態條件與效能損耗。
MERGE INTO 目標表 T
USING 來源資料 S
ON (T.KEY = S.KEY)
WHEN MATCHED THEN
UPDATE SET T.COL = S.COL ...
WHEN NOT MATCHED THEN
INSERT (COL...) VALUES (S.COL...);
ON (1=0) 強制全量插入,無需連接LOG ERRORS 子句將 DML 錯誤導向錯誤表CREATE TABLE PRODUCTS (
PRODUCT_ID INTEGER PRIMARY KEY,
PRODUCT_NAME VARCHAR2(60),
CATEGORY VARCHAR2(60)
);
CREATE TABLE NEWPRODUCTS (
PRODUCT_ID INTEGER,
PRODUCT_NAME VARCHAR2(60),
CATEGORY VARCHAR2(60)
);
-- 初始資料
INSERT INTO PRODUCTS VALUES (1501, 'VIVITAR 35MM', 'ELECTRNCS');
INSERT INTO PRODUCTS VALUES (1502, 'OLYMPUS IS50', 'ELECTRNCS');
INSERT INTO PRODUCTS VALUES (1600, 'PLAY GYM', 'TOYS');
INSERT INTO PRODUCTS VALUES (1601, 'LAMAZE', 'TOYS');
INSERT INTO PRODUCTS VALUES (1666, 'HARRY POTTER', 'DVD');
INSERT INTO NEWPRODUCTS VALUES (1502, 'OLYMPUS CAMERA', 'ELECTRNCS');
INSERT INTO NEWPRODUCTS VALUES (1601, 'LAMAZE', 'TOYS');
INSERT INTO NEWPRODUCTS VALUES (1666, 'HARRY POTTER', 'TOYS');
INSERT INTO NEWPRODUCTS VALUES (1700, 'WAIT INTERFACE', 'BOOKS');
COMMIT;
MERGE INTO PRODUCTS P
USING NEWPRODUCTS NP
ON (P.PRODUCT_ID = NP.PRODUCT_ID)
WHEN MATCHED THEN
UPDATE SET P.PRODUCT_NAME = NP.PRODUCT_NAME, P.CATEGORY = NP.CATEGORY;
-- 結果:1502,1601,1666 更新;1700 未插入
MERGE INTO PRODUCTS P
USING NEWPRODUCTS NP
ON (P.PRODUCT_ID = NP.PRODUCT_ID)
WHEN NOT MATCHED THEN
INSERT VALUES (NP.PRODUCT_ID, NP.PRODUCT_NAME, NP.CATEGORY);
-- 結果:1700 插入;既有行不動
MERGE INTO PRODUCTS P
USING NEWPRODUCTS NP
ON (P.PRODUCT_ID = NP.PRODUCT_ID)
WHEN MATCHED THEN
UPDATE SET P.PRODUCT_NAME = NP.PRODUCT_NAME, P.CATEGORY = NP.CATEGORY
WHERE P.CATEGORY = 'DVD' -- 僅更新 DVD 類
WHEN NOT MATCHED THEN
INSERT VALUES (NP.PRODUCT_ID, NP.PRODUCT_NAME, NP.CATEGORY)
WHERE NP.CATEGORY != 'BOOKS'; -- 排除 BOOKS 類
MERGE INTO PRODUCTS P
USING NEWPRODUCTS NP
ON (1=0) -- 永不匹配,強制走 NOT MATCHED
WHEN NOT MATCHED THEN
INSERT VALUES (NP.PRODUCT_ID, NP.PRODUCT_NAME, NP.CATEGORY)
WHERE NP.CATEGORY = 'BOOKS'; -- 僅插入 BOOKS
MERGE INTO PRODUCTS P
USING NEWPRODUCTS NP
ON (P.PRODUCT_ID = NP.PRODUCT_ID)
WHEN MATCHED THEN
UPDATE SET P.PRODUCT_NAME = NP.PRODUCT_NAME, P.CATEGORY = NP.CATEGORY
DELETE WHERE (P.CATEGORY = 'ELECTRNCS') -- 更新後刪除電子類
WHEN NOT MATCHED THEN
INSERT VALUES (NP.PRODUCT_ID, NP.PRODUCT_NAME, NP.CATEGORY);
執行邏輯:1502 同時匹配 ON 與 DELETE 條件 → 刪除;1501 僅匹配 DELETE 不匹配 ON → 保留;1700 不匹配 ON → 插入;1601/1666 匹配 ON 不匹配 DELETE → 更新。
MERGE /*+ PARALLEL(4) */ INTO ...LOG ERRORS INTO ERR_TABLE REJECT LIMIT UNLIMITED| 錯誤代碼 | 原因 | 解決 |
|---|---|---|
| ORA-01779 | 非鍵保留表無法修改 | 確保 ON 條件涵蓋目標表主鍵/唯一鍵 |
| ORA-01427 | 單行子查詢返回多行 | 來源資料去重或加聚合 |
| ORA-30926 | 穩定集合問題 | 來源資料在 MERGE 期間被修改 |