在 Oracle 10g 之前,PL/SQL 開發者在使用 FORALL 陳述式進行批量 DML 操作時,面臨著兩大限制:無法刪除集合中間的元素,以及集合索引必須連續。這迫使開發者在處理稀疏集合時,不得不採用迴圈逐筆處理,嚴重影響效能。Oracle 10g 引入了 INDICES OF 和 VALUES OF 兩個子句,徹底解決了這些痛點,讓批量操作更加靈活強大。
INDICES OF 子句允許開發者指定一個集合的所有有效索引值,即使這些索引值之間存在間隔(即非連續)。語法結構如下:
FORALL index_name IN INDICES OF collection_name
[BETWEEN lower_bound AND upper_bound]
sql_statement;
這裡的 collection_name 必須是一個嵌套表或關聯陣列。BETWEEN 子句為可選項,用於進一步限制處理範圍。這意味著,即使集合中因刪除操作導致索引不連續,FORALL 依然能精準地針對現有元素執行批量 SQL,無需補齊索引。
VALUES OF 提供了更高層次的控制力。它接受一個「索引集合」(集合中的元素為索引值),按照該集合定義的順序和選擇的索引,對主集合執行批量操作。語法如下:
FORALL index_name IN VALUES OF index_collection
sql_statement;
這在需要按特定業務邏輯順序處理資料、或僅處理符合條件的子集時極為實用。例如,先查詢符合條件的記錄索引並存入索引集合,再透過 VALUES OF 一次性完成批量更新或插入。
假設我們將 HR 模式的部門名稱載入嵌套表,需找出所有與「IT」相關的部門並插入日誌表。傳統寫法需迴圈判斷,但利用 VALUES OF 可優化為:
dept_tab 及索引集合 idx_tab(型別為 SYS.ODCINUMBERLIST 或自定義集合型別)。dept_tab,若部門名稱含「IT」,將其索引 APPEND 至 idx_tab。FORALL i IN VALUES OF idx_tab INSERT INTO dept_log VALUES (dept_tab(i).dept_id, ...);此做法將多次 INSERT 合併為單次批量操作,大幅降低 Context Switch 開銷。雖然單一 SQL 配合 WHERE 子句也能達到同樣結果,但此範例展示了在複雜 PL/SQL 邏輯中(如需先在記憶體中運算、轉換資料)如何高效落地批量 DML。
Oracle 10g 的 INDICES OF 與 VALUES OF 為 FORALL 注入了處理非連續、自定義順序集合的能力,是 PL/SQL 高效能批量處理的關鍵進化。善用這兩個子句,能讓開發者在保持程式碼簡潔的同時,榨乾資料庫批量操作的效能潛力。