| 類型 | 特徵 | 索引 | 適用場景 |
|---|---|---|---|
| 關聯陣列 | 稀疏、無上限、僅 PL/SQL 可用 | BINARY_INTEGER / PLS_INTEGER / VARCHAR2 | 暫存查詢結果、查找表、快取 |
| 巢狀表 | 可持久化至資料表、支援多集合操作 | 連續整數從 1 開始 | 資料欄位型別、大量資料搬運 |
| VARRAY | 固定上限、有序、儲存連續 | 連續整數從 1 開始 | 小型固定集合、物件屬性 |
-- 1. 純量型別陣列
TYPE arr_str IS TABLE OF VARCHAR2(5) INDEX BY BINARY_INTEGER;
-- 2. 記錄型別陣列(搭配游標 %ROWTYPE)
TYPE v_table1 IS TABLE OF cur1%ROWTYPE INDEX BY PLS_INTEGER;
| 特性 | BINARY_INTEGER | PLS_INTEGER |
|---|---|---|
| 執行引擎 | Oracle 軟體模擬 | 硬體原生(CPU 整數運算) |
| 溢位行為 | 自動轉 NUMBER 不報錯 | **溢位報錯**(-2^31 ~ 2^31-1) |
| 效能 | 較慢 | **快 2~3 倍** |
| 建議 | 相容舊代碼 | **新代碼首選** |
**結論**:索引、迴圈計數器、整數運算**一律用 PLS_INTEGER**。
DECLARE
CURSOR cur1 IS SELECT empno, ename, sal FROM emp WHERE deptno = 10;
-- 陣列元素型別直接綁定游標列定義
TYPE emp_arr IS TABLE OF cur1%ROWTYPE INDEX BY PLS_INTEGER;
v_emps emp_arr;
v_idx PLS_INTEGER := 0;
BEGIN
FOR r IN cur1 LOOP
v_idx := v_idx + 1;
v_emps(v_idx) := r; -- 整筆記錄賦值
END LOOP;
-- 陣列遍歷
FOR i IN 1..v_idx LOOP
DBMS_OUTPUT.PUT_LINE(v_emps(i).ename || ':' || v_emps(i).sal);
END LOOP;
END;
/
%ROWTYPE:自動適應游標/表欄位變更,**免維護**。v_emps(v_idx) := r 整筆寫入。
DECLARE
TYPE id_arr IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
v_ids id_arr;
BEGIN
-- 一次性抓取至陣列,減少 Context Switch
SELECT empno BULK COLLECT INTO v_ids FROM emp WHERE deptno = 20;
-- 批次更新,單次 SQL 引擎往返
FORALL i IN v_ids.FIRST..v_ids.LAST
UPDATE emp SET sal = sal * 1.1 WHERE empno = v_ids(i);
DBMS_OUTPUT.PUT_LINE('Updated ' || SQL%ROWCOUNT || ' rows');
END;
/
效能提升:10,000 筆資料,FOR LOOP ~ 8 秒 → BULK COLLECT + FORALL ~ 0.3 秒。
arr(1) := 'a',無需 NEW 或 EXTEND(巢狀表/VARRAY 需)。INDEX BY PLS_INTEGER 卻用 VARCHAR2 索引 → 編譯錯誤。PLS_INTEGER 迴圈超過 21 億報錯,大量資料用 NUMBER 索引或分批。FORALL **不支援** WHERE CURRENT OF、RETURNING(11g+ 支援 RETURNING BULK COLLECT)。掌握 關聯陣列 + %ROWTYPE + PLS_INTEGER 黃金組合,配合 BULK COLLECT / FORALL,是 PL/SQL 高效能批次處理的核心技能。記住:**索引用 PLS_INTEGER、型別用 %ROWTYPE、批次用 FORALL**,即可寫出既簡潔又極速的資料處理邏輯。