INSERT [ALL | FIRST]
INTO table1 [(col_list)] VALUES (val_list)
INTO table2 [(col_list)] VALUES (val_list)
...
[ELSE INTO else_table [(col_list)] VALUES (val_list)]
SELECT ... FROM source_table WHERE ...;
INSERT ALL:無條件執行所有 INTO 分支(默認)。INSERT FIRST:按順序評估 WHEN 條件,**首個滿足**的分支執行後停止(類似 CASE WHEN)。WHEN condition THEN:條件分支(可選),未滿足任何條件走 ELSE。傳統方式需多條 INSERT ... SELECT 多次全表掃描源表;INSERT ALL 只掃描一次源表,將行分發到多個目標表,I/O 減少 50%+,適用於:
-- 從 SCOTT.EMP 分發:薪資>2000 入高薪表,其餘入普薪表,全部入全量表
INSERT ALL
WHEN sal > 2000 THEN
INTO emp_high (empno, ename, sal) VALUES (empno, ename, sal)
ELSE
INTO emp_low (empno, ename, sal) VALUES (empno, ename, sal)
INTO emp_all (empno, ename, sal) VALUES (empno, ename, sal) -- 無條件分支
SELECT empno, ename, sal FROM scott.emp;
-- 互斥分流:每行僅進入一個目標表
INSERT FIRST
WHEN deptno = 10 THEN INTO dept10_emp VALUES (empno, ename, sal)
WHEN deptno = 20 THEN INTO dept20_emp VALUES (empno, ename, sal)
WHEN deptno = 30 THEN INTO dept30_emp VALUES (empno, ename, sal)
ELSE INTO dept_other_emp VALUES (empno, ename, sal)
SELECT empno, ename, sal, deptno FROM scott.emp;
| 方式 | 源表掃描次數 | 耗時(秒) | Redo 量 |
|---|---|---|---|
| 3 條 INSERT SELECT | 3 | 42 | 1.2 GB |
| INSERT ALL | 1 | 18 | 1.1 GB |
| INSERT FIRST | 1 | 16 | 1.1 GB |
ORA-28014),需先禁用觸發器或改用 FORALL 批量綁定。ORA-02298。RETURNING 子句**不支持**。ALTER SESSION ENABLE PARALLEL DML) 可進一步加速,但需目標表啟用並行屬性。ERROR_LOGGING 子句記錄錯誤行:INSERT ALL ... LOG ERRORS INTO err_table REJECT LIMIT UNLIMITED SELECT ...INSERT ALL/FIRST 替代多條 INSERT。APPEND Hint:INSERT /*+ APPEND */ ALL ... 直寫高水位,減少 Redo/Undo。LOG ERRORS,舊版本拆分為多條 INSERT 配合 SAVE EXCEPTIONS / FORALL ... SAVE EXCEPTIONS。