Oracle Collection 型別 (VARRAY、Nested Table) 在 PL/SQL 與應用層交互時常見。ODAC 提供 TArrayField、TOraArray 等機制映射集合元素,但大型陣列會產生大量 TField 導致效能下降。本文說明 ODAC 陣列存取限制、三種存取模式、參數綁定與效能優化策略。
TOraArray 物件存取完整元素。CREATE TYPE tdac_array1 AS VARRAY(5) OF NUMBER;
CREATE TYPE tdac_array2 AS VARRAY(4) OF CHAR(10);
CREATE TABLE odac_array (
code NUMBER,
title VARCHAR2(10),
arr1 tdac_array1,
arr2 tdac_array2
);
// 存取 arr1 第 1 個元素 (0-based)
var
v: Integer;
begin
v := Query.FieldByName('Arr1[0]').AsInteger; // 簡單直接
end;
var
v: Integer;
arrField: TArrayField;
begin
arrField := TArrayField(Query.FieldByName('Arr1'));
v := arrField.Fields[0].AsInteger; // Fields 為 TField 陣列
end;
var
v: Integer;
oraArr: TOraArray;
begin
oraArr := Query.GetArray('Arr1'); // 取得 TOraArray 物件
v := oraArr.ItemAsInteger[0]; // 強型別索引器
// 或動態名稱存取
v := oraArr.AttrAsInteger['[1]'];
end;
優勢:TOraArray直接操作底層 OCI 集合控制碼,避免建立大量TField物件,記憶體佔用低、存取速度快。
Query.SparseArray := True; -- 僅在存取時載入該元素
// 配合 TArrayField.Fields[Index] 使用
v := TArrayField(Query.FieldByName('Arr1')).Fields[100].AsInteger; // 只載入第 101 個
var
OraSQL: TOraSQL;
begin
OraSQL.SQL.Text := 'INSERT INTO odac_array (Code, Arr1, Arr2) VALUES (:Code, :Arr1, :Arr2)';
OraSQL.ParamByName('Code').AsInteger := 10;
// 綁定 Arr1 (NUMBER VARRAY)
with OraSQL.ParamByName('Arr1').AsArray do begin
AllocObject(OraSession.OCISvcCtx, 'TDAC_ARRAY1'); // 指定資料庫型別名
ItemAsInteger[0] := 12;
AttrAsInteger['[1]'] := 10; // 別名索引
ItemAsInteger[3] := 133;
end;
// 綁定 Arr2 (CHAR VARRAY)
with OraSQL.ParamByName('Arr2').AsArray do begin
OCISvcCtx := OraSession.OCISvcCtx;
AllocObject('TDAC_ARRAY2');
AttrAsString['[2]'] := 'eeee';
ItemAsString[0] := 'FFFFF';
end;
OraSQL.Execute;
end;
| 屬性/方法 | 用途 | 適用型別 |
|---|---|---|
| AsArray | 取得集合參數介面 | dtArray |
| AllocObject(SvcCtx, TypeName) | 在 Server 端分配集合物件實例 | 所有 |
| ItemAsInteger[Index] | 強型別整數索引存取 | NUMBER VARRAY |
| ItemAsString[Index] | 強型別字串索引存取 | CHAR/VARCHAR2 VARRAY |
| AttrAsInteger['[Index]'] | 字串鍵名動態索引存取 | NUMBER VARRAY |
| AttrAsString['[Index]'] | 字串鍵名動態索引存取 | CHAR/VARCHAR2 VARRAY |
GetArray + TOraArray,避免 TField 爆炸。Query.SparseArray := True。TOraSQL / TOraQuery 支援陣列 DML (Execute(Iters)),單次網路往返插入多筆含集合的記錄。AllocObject 的型別名稱 (如 'TDAC_ARRAY1') 為資料庫型別名稱 (大小寫敏感),建議常數化管理。ODAC 透過 TArrayField (設計時友善) 與 TOraArray (運行時高效) 雙軌支援 VARRAY 存取。核心決策樹:元素數 ≤ 20 且全量存取 → FieldByName/TArrayField;元素數大/稀疏存取/高效能需求 → TOraArray + SparseArray。參數綁定時務必正確呼叫 AllocObject 指定 Server 端型別,並區分 ItemAsXxx (整數索引) 與 AttrAsXxx (字串鍵) 兩種存取介面。