PL/SQLストアドプロシージャは、引数にPL/SQLテーブルと呼ばれる、配列データをとることができま、DOAを用いれば、一次元配列データをパラメータとして受け渡しすることが可能になります。
OracleのPL/SQLで利用できるコレクション型には、
PL/SQL表(索引付き表)、NESTED TABLE、vararray の3種類がありますが、このうちの
PL/SQL表型のパラメータを、DOAを用いることでDelphiアプリケーションから操作することができます。3種類のコレクション型の中で、PL/SQLが索引付き表とホストアプリケーションの配列データとの間の暗黙の型変換をサポートしているためです。
なお、DOAがサポートするのは、string, integer, float, date
型の配列に限られます。(OracleではVARCHAR2, NUMBER, DATEに相当します)
PL/SQLテーブルを引数に持つプロシージャの作り方
PL/SQL表を使うには、PL/SQL表を型として宣言する必要があります。
パッケージプロシージャを宣言する場合には、パッケージの宣言部において型を宣言し、パッケージプロシージャの引数に使い、パッケージに属さないプロシージャを宣言する場合には、PL/SQL表型を宣言するためのパッケージを使います。以下に例示します。
//例1) パッケージプロシージャが引数にPL/SQL表をとる例 create or replace package EmpPackage as type t_EmpNoTable is table of emp.empno%type index by binary_integer; type t_ErrorTable is table of varchar2(200) index by binary_integer; procedure DeleteEmployees(p_EmpNoTable in t_EmpNoTable; end; create or replace package body EmpPackage as procedure DeleteEmployees(p_EmpNoTable in t_EmpNoTable, p_ErrorTable out t_ErrorTable, p_Deleted out integer) as DeletedCount integer; i integer; begin i := 0; DeletedCount := 0; loop begin i := i + 1; delete emp where empno = p_EmpNoTable(i); p_ErrorTable(i) := 'Okay'; DeletedCount := DeletedCount + 1; exception when no_data_found then exit; when others then p_ErrorTable(i) := sqlerrm; end; end loop; p_Deleted := DeleteCount; end; end;
//例2)パッケージの外でプロシージャを定義する場合(型宣言用のパッケージを作ります) create or replace package EmpType as type t_EmpNoTable is table of emp.empno%type index by binary_integer; type t_ErrorTable is table of varchar2(200) index by binary_integer; end; create or replace procedure DeleteEmployees( p_EmpNoTable in EmpType.t_EmpNoTable, p_ErrorTable out EmpType.t_ErrorTable, p_Deleted out integer ) as DeletedCount integer; i integer; egin i := 0; DeletedCount := 0; loop begin i := i + 1; delete emp where empno = p_EmpNoTable(i); p_ErrorTable(i) := 'Okay'; DeletedCount := DeletedCount + 1; exception when no_data_found then exit; when others then p_ErrorTable(i) := sqlerrm; end; end loop; p_Deleted := DeleteCount; end;
DelphiからPL/SQL表をパラメータにストアドプロシージャを実行する方法
TOracleQueryコンポーネント(DelteEmployeesQuery)のSQLプロパティを以下のようにセットします
begin EmpPackage.DeleteEmployees(:p_EmpNoTable, :p_ErrorTable, :p_Deleted); end;
TOracleQueryコンポーネント(DelteEmployeesQuery)のVariablesプロパティエディタで、以下のように変数を宣言します
- p_EmpNoTableはinteger型のPL/SQL表
- p_ErrorTableはstring型のPL/SQL表
- p_Deletedはinteger
そのうえで以下ようなのコードで、EmpNoが7839,7369,7788の3件のDELETE操作を行うことができます
var EmpNoTable : Variant; with DeleteEmployeesQuery do begin EmpNoTable := VarArrayCreate([0, 2], varVariant); EmpNoTable[0] := 7839; EmpNoTable[1] := 7369; EmpNoTable[2] := 7788; SetVariable('p_EmpNoTable', EmpNoTable); Execute; Session.Commit; ErrorTable := GetVariable('p_ErrorTable'); s := string(GetVariable('p_Deleted')) + ' record(s) deleted'#13#10; for i := 0 to 2 do s := s + string(EmpNoTable[i]) + ' - ' + string(ErrorTable[i]) + #13#10; ShowMessage(s); end;
-
TOracleQuery
-
Variables: PL/SQL表型の変数を、
Variant配列のVariant変数にバインドできます
-
Variables: PL/SQL表型の変数を、
Variant以外の配列のVariant変数や、配列変数をバインドすることはできないので注意が必要です。すなわち、PL/SQL表にバインドする変数は、Delphi側では常に
Variantとして宣言する必要があり、VarArrayCreate([0, N], VarType)のVarTypeは
varVariantでなければなりません