FireDAC での Oracle の利用

提供: RAD Studio
移動先: 案内検索

DBMS での作業(FireDAC) への移動


Oracle の高度なデータ型

PL/SQL テーブル

FireDAC では、Oracle PL/SQL の無名ブロック、ストアド プロシージャ、関数のパラメータとして PL/SQL テーブルをサポートしています。なお、PL/SQL テーブルは VARRAY(可変長配列)やコレクションとは異なります。この最後の 2 つは FireDAC ではサポートされていません。

パラメータを PL/SQL テーブルとしてセットアップするには、TFDParam.ArrayType = atPLSQLTable と指定します。ExecProc を呼び出す前に、ArraySize をテーブルの最大サイズに設定します。INOUT および OUT パラメータの ArraySize が、サーバー側で割り当てられたテーブル要素数より小さい場合は、次のような例外が発生します。

[FireDAC][Phys][Ora] ORA-06513: PL/SQL: index for PL/SQL table out of range for host language array
ORA-06512: at line 2

パラメータ値を読み書きするには、TFDParam.AsXxxs[<インデックス>] プロパティを使用します。このインデックスが 0 から始まるのに対して、サーバー側ではインデックスは 1 から始まります。空の要素は NULL 値を持ち、TFDParam.IsNulls[<インデックス>] を使って、空かどうかをテストすることができます。

サーバー側スクリプトの例を次に示します。

CREATE OR REPLACE PACKAGE FDQA_TestPack AS
  TYPE TVC2Tbl IS TABLE OF VARCHAR2(50) INDEX BY BINARY_INTEGER;
  PROCEDURE TestPLSQLArray(ATable in out TVC2Tbl);
END ADQA_testpack;
/

CREATE OR REPLACE PACKAGE BODY FDQA_TestPack AS
  PROCEDURE TestPLSQLArray(ATable IN OUT TVC2Tbl) IS
  BEGIN
    for i in ATable.First .. ATable.Last loop
      ATable(i) := '*' || ATable(i) || '*';
    end loop;
  END;
END FDQA_testpack;
/

また、テーブル パラメータに数行のメモを割り当て、プロシージャを実行し、テーブル項目を読み取り、メモに入力するクライアント側コードの例を次に示します。

var
  i: Integer;

FDStoredProc1.PackageName := 'FDQA_TESTPACK';
FDStoredProc1.StoredProcName := 'TESTPLSQLARRAY';
FDStoredProc1.Prepare;

FDStoredProc1.Params[0].ArraySize := Memo1.Lines.Count;
for i := 0 to Memo1.Lines.Count - 1 do
  FDStoredProc1.Params[0].AsStrings[i] := Memo1.Lines[i];
Memo1.Lines.Clear;

FDStoredProc1.ExecProc;
for i := 0 to FDStoredProc1.Params[0].ArraySize - 1 do
  Memo1.Lines.Add(FDStoredProc1.Params[0].AsStrings[i]);

FireDAC\Samples\DBMS Specific\Oracle\PLSQLAssocArray デモも参照してください。

PL/SQL レコード

FireDAC では、ストアド プロシージャおよび関数のパラメータとして Oracle PL/SQL レコードをサポートしています。なお、PL/SQL レコードはオブジェクトとは異なります。Oracle オブジェクトは FireDAC ではサポートされていません。

そのようなパラメータを正しくセットアップできるのは、fiMetaTFDStoredProc.FetchOptions.Items に含まれており、かつ ParamBindMode = pbByName の場合だけです。その場合、FireDAC はこのレコードを、対応する Params 項目の単純なリストに展開します。各項目は <パラメータ名>$<レコード フィールド名> という名前になっています。

サーバー側スクリプトの例を次に示します。

CREATE OR REPLACE PACKAGE ClientPack IS
  TYPE t_clnt_data IS RECORD (
       client_id numeric,
       name varchar2(10),
       act boolean
  );
  PROCEDURE ClntProc(ARec IN t_clnt_data);
END ClientPack;
/

また、パラメータ値を割り当てるクライアント側コードの例を次に示します。

FDStoredProc1.PackageName := 'MYPACK';
FDStoredProc1.StoredProcName := 'CLNTPROC';
FDStoredProc1.Prepare;
FDStoredProc1.ParamByName('AREC$CLIENT_ID').Value := 100;
FDStoredProc1.ParamByName('AREC$NAME').Value := 'Client 1';
FDStoredProc1.ParamByName('AREC$ACT').Value := True;
FDStoredProc1.ExecProc;

FireDAC\Samples\DBMS Specific\Oracle\PLSQLRecs デモも参照してください。

Oracle の高度なカーソル

Oracle REF CURSOR の操作

FireDAC では、Oracle PL/SQL の無名ブロック、ストアド プロシージャ、関数から返される Oracle REF CURSOR(Oracle 12c の暗黙的な結果を含む)をサポートしています。最初のカーソルを開くには Open メソッドを呼び出し、後続のカーソルに切り替えるには NextRecordSet メソッドを使用します。次のカーソルに切り替えた後は、前のカーソルにはもうアクセスできません。詳細は、「コマンド バッチ」を参照してください。

以下に例を示します。

CREATE PROCEDURE TestRefCrs (ACrs1 IN OUT SYS_REFCURSOR, ACrs2 IN OUT SYS_REFCURSOR) AS
BEGIN
  OPEN ACrs1 FOR SELECT * FROM "Orders";
  OPEN ACrs2 FOR SELECT * FROM "Order Details";
END;

TFDStoredProc を使用する場合:

FDStoredProc1.FetchOptions.AutoClose := False;
FDStoredProc1.StoredProcName := 'TESTREFCRS';
FDStoredProc1.Open;
// work with "Orders" table data
FDStoredProc1.NextRecordSet;
// work with "Order Details" table data
FDStoredProc1.Close;

TFDQuery を使用する場合:

FDQuery1.FetchOptions.AutoClose := False;
FDQuery1.Open('BEGIN TestRefCrs(:p1, :p2); END;');
// work with "Orders" table data
FDQuery1.NextRecordSet;
// work with "Order Details" table data
FDQuery1.Close;

メモ: REF CURSOR が動的 SQL コマンド テキストを使って開かれる場合は、後続の Open 呼び出しの前に Disconnect メソッドを呼び出さなければなりません。これは、FireDAC ではデータセットを準備された状態にしておき、最初の Open 呼び出し時と同じカーソル構造を想定しているからです。

以下に例を示します。

CREATE PROCEDURE TestDynCrs (ASQL IN VARCHAR2, ACrs OUT SYS_REFCURSOR) AS
BEGIN
  OPEN ACrs FOR ASQL;
END;

TFDQuery を使用する場合:

FDQuery1.FetchOptions.AutoClose := False;
FDQuery1.SQL.Text := 'BEGIN TestDynCrs(:p1, :p2); END;';

FDQuery1.Params[0].AsString := 'SELECT * FROM "Orders"';
FDQuery1.Open;
// work with "Orders" table data
FDQuery1.Close;

FDQuery1.Params[0].AsString := 'SELECT * FROM "Order Details"';
FDQuery1.Disconnect;
FDQuery1.Open;
// work with "Order Details" table data
FDQuery1.Close;

Oracle のネストしたカーソルの操作

FireDAC では、SELECT リストで CURSOR 型の列を使用できます。リストに複数の CURSOR があってもかまいません。しかし、CURSOR 内にネストした CURSOR はサポートされていません。FireDAC では、このような列を dtRowSetRef に設定し、それらの TDataSetField を作成します。アプリケーションでそれらの行セットを処理するには、TFDMemTable を使用し、その DataSetField プロパティを TDataSetField 参照に設定しなければなりません。

アプリケーションでメイン データセット内をナビゲートすると、ネストしたデータセットが自動的に開かれ更新されて、メイン データセットの現在のレコードに対応するネストしたカーソル レコードが提供されます。

例については、FireDAC\Samples\DBMS Specific\Oracle\NestedCursors デモを参照してください。

カーソル データの更新

アプリケーションで REF CURSOR やネストしたカーソル レコードを更新するには、メイン クエリを再実行する必要があります。

アプリケーションで REF CURSOR やネストしたカーソル レコードを編集するには、更新のポストをオーバーライドする必要があります。

暗黙の ROWID

Oracle では ROWID の暗黙の取得をサポートしています。SELECT FOR UPDATE クエリを実行すると、Oracle によって ROWID 疑似列が暗黙的に結果に含められます。

FireDAC データセットでは、暗黙の ROWID フィールドは非表示の列として表現されます。暗黙の ROWID フィールドは、Fields プロパティでは使用できませんが、Table プロパティから読み取ることができます。

Fields プロパティに含められるよう ROWID 疑似列を明示的に取得したい場合には、ROWID を SELECT フィールド リストに追加する必要があります(SELECT <他のフィールド>, ROWID FROM ...)。

サーバー フィードバックの提供

Oracle バックエンド アプリケーションでは、DBMS_OUTPUT パッケージを使って、フロントエンド アプリケーションにフィードバックを送信できます。FireDAC を使用する場合は、DBMS_OUTPUT の内容を自動的に受信できます。

オプションで、TFDConnection の ResourceOptions.ServerOutputSize をバッファの最大サイズに設定することもできます。DBMS_OUTPUT を有効にするには、ResourceOptions.ServerOutputTrue に設定します。SQL コマンドの実行後、アプリケーションでは Messages を使って DBMS_OUTPUT フィードバックを処理できます。なお、DBMS_OUTPUT の処理はパフォーマンスに影響するので、通常は無効にしておく必要があります。

以下に例を示します。

var
  i: Integer;
...
FDConnection1.ResourceOptions.ServerOutput := True;
with FDQuery1.SQL do begin
  Clear;
  Add('begin');
  Add('  dbms_output.put_line(''Hello World !'');');
  Add('end;');
end;
FDQuery1.ExecSQL;
if FDConnection1.Messages <> nil then begin
  Memo1.Lines.Clear;
  for i := 0 to FDConnection1.Messages.ErrorCount - 1 do
    Memo1.Lines.Add(FDConnection1.Messages[i].Message);
end;

Oracle データベース インスタンスの管理

TFDOracleAdmin サービス コンポーネントを使用して Oracle データベース インスタンスを管理することができます。

TFDOracleAdmin.Startup および TFDOracleAdmin.Shutdown を使用して、Oracle データベース インスタンスの起動や停止を行ったり、プラグイン可能なデータベース(PDB)を開いたり閉じることができます。

関連項目