Microsoft SQL Server
や、Sybaseでは、こんな風にストアドプロシージャでSELECT文を実行し、その結果セットをストアドプロシージャから返すことができます。

  create procedure sp_foo
   @key nvarchar(10)
  as
    SELECT empno, ename FROM emp
    WHERE empno >= @key
  end

OracleのPL/SQLプロシージャは、結果セットを返すことはありませんが、上記に近い機能は、以下のようにカーソルを返すプロシージャを定義することで、実現できます。

  create or replace package TestPkg is
    cursor empcursor is select empno, ename from emp;
    type t_empcursor is ref cursor return empcursor%rowtype;

    procedure SelectRecords(p_key in number, p_empcursor in out t_empcursor);
  end TestPkg;

  create or replace package body TestPkg is

    procedure SelectRecords(p_key in number, p_empcursor in out t_empcursor) is
    begin
       open p_empcursor for select empno, ename from emp where key >= p_key;
    end;

  end TestPkg;

カーソル変数の出力をDelphiアプリケーションで処理する方法

TOracleQueryによる方法

すでにTOracleQueryのセクションで説明した通り、ストアドプロシージャから返されたカーソルをもう一つのTOracleQueryに割当てて、そのQueryをOpenすることでカーソルからデータをフェッチします。

  //OpenQuery.SQL = 
  //  BEGIN
  //    TestPkg.SelectRecords(:Key, :EmpCursor);
  //  END;
  //OpenQuery.Variables: の変数宣言
  //  KEY = NUMBER型の変数
  //  EMPCURSOR = CURSOR型の変数
  //として…
  //
  procedure TForm1.Button4Click(Sender: TObject);
  begin
    with OpenQuery do begin
      SetVariable('Key', 1238);
      SetComplexVariable('EmpCursor', EmpFetchQuery);
      Execute;
    end;

    with EmpFetchQuery do begin
      Execute;
      while not Eof do begin
        Memo1.Lines.Add(Field('ENAME'));
        Next;
      end;
    end;

  end;

TOracleDataSetによる方法

TOracleDataSetは、SQLプロパティにセットされたSQL文中で、カーソル型の変数が一つ定義されている場合に、そのカーソルからレコードをフェッチしたものを、自身のデータセットとして扱うようになっています。したがって、SQLで変数にカーソルを取り出すように設定するだけで、結果セットをTDataSetとしてアクセスできるようになります

  //OraDataSet.SQL = 
  //  BEGIN
  //    TestPkg.SelectRecords(:Key, :EmpCursor);
  //  END;
  //    Key=number型の変数
  //    EmpCursor=カーソル型の変数
  //として…
  //
  procedure TForm1.Button4Click(Sender: TObject);
  begin
    with OraDataSet do begin
      SetVariable('Key', 1238);
      Open;
    end;

    with OraDataSet do begin
      First;
      while not Eof do begin
        Memo1.Lines.Add(Field('ENAME'));
        Next;
      end;
    end;

  end;