DirectoOracleAccessを使ってストアドプロシージャを呼び出します。

プロシージャ呼出の基本3パターン

以下の3つについて順に説明します。

  1. 結果を返さないプロシージャの呼び出し(INPUT変数の渡し方)
  2. プロシージャ呼出し後、OUTPUT変数からの結果の取得
  3. カーソル変数を利用したプロシージャからのレコードセットの取得

1)結果を返さない手続き型のプロシージャ

 

右のようなプロシージャを考えます(引数を10回くりかえしてDBMS_Output出力します)

create or replace procedure TestProc1(N IN NUMBER) is
  i number;
begin
  for i in 1 .. 10 loop
    dbms_output.put_line(N);
  end loop;
end TestProc1;
これを右のようなアプリケーションで呼んでみましょう
画面上のオブジェクトは左上から順に
Session: TOracleSession
Query1: TOracleQuery
Button1: TButton
Memo: TMemo
で、
SessionのユーザID/Passwd/Database
が適切に設定されてDBに接続でき
Query1.SessionがSessionになっているとします

1-1(引数なしのとき)

Query1.SQLをこのように設定して

begin
  TestProc1( 3 );
end;
Button1.Clickイベントをこう記述して
procedure TForm1.Button1Click(Sender: TObject);
var
  Status: integer;
  Line: string;
begin
  Session.DBMS_Output.Enable(100000);
  Query1.Execute;            
   
Memo.Clear; while True do begin Session.DBMS_Output.Get_Line(Line, Status); if Status <> glSuccess then Break; Memo.Lines.Add(Line); end; end;
テスト実行すると結果は
メモに数字の3が10回繰り返して表示されるはずです。

1-2(引数ありのとき)

TestProc1の引数を変数から与えるには

Query1.SQLをこのように設定して

begin
  TestProc1( :N );
end;

Query1のVariablesプロパティのプロパティエディタを開いて、「Scan SQL」を実行すると、上記SQL文中からパラメータが抽出されてVariablesとしてリストに現れます。

一番目の「:N」をクリックして、

整数型として定義します。

フォーム上にエディットボックスEdit1を置いて、
今度はButton1.Clickをこのように変えて
procedure TForm1.Button1Click(Sender: TObject);
var
  Status: integer;
  Line: string;
begin
  Session.DBMS_Output.Enable(100000);
  with Query1 do begin
    Close;
    SetVariable(★N, StrToInt(Edit1.Text)); //←ポイント
    Execute;
  end;           
   
Memo.Clear; while True do begin Session.DBMS_Output.Get_Line(Line, Status); if Status <> glSuccess then Break; Memo.Lines.Add(Line); end; end;
実行し、Edit1に数字をいれてボタンをクリックすると、結果は… Edit1に入力した数字が10回繰り返されて出力されます

2)計算結果をパラメータで返すストアドプロシージャ

 

例としてインプットを二乗して返す手続きを用意した

create or replace procedure TestProc2(
  N IN NUMBER, R OUT NUMBER) is
begin
  R := N * N;
end TestProc2;
Query1.SQLを右のようにセット
declare 
  R number;
begin
  TestProc2(6, R);
  select R into :R From Dual;
end;
Query1.Variablesプロパティのプロパティエディタを開き、出力パラメータ:Rを設定する
Button1Clickは右のようにして
procedure TForm1.Button1Click(Sender: TObject);
begin
  Query1.Execute;
  Memo.Clear;
  Memo.Lines.Add(★R =  + 
    IntToStr(Query1.GetVariable(★R)));
end;

 

実行すれば
メモに「 R = 36 」と出力される
補足

上記の例においては、Query1.SQLを以下のようにした方がもっと直接的です。

begin
  TestProc2( 6, :R);
end;

または

begin
  TestProc2( N => 6, R => :R);
end;

なお、プロシージャをパッケージ内で宣言した場合は、TOraclePackageコンポーネントが簡便です。

3)SELECT文の結果を返すストアドプロシージャ

 

右のようなパッケージを用意します

 

Sybase/SQL-Server風にいえば

create procedure
  SelectRecords as
begin
  select empno,
  ename from emp;
end;

のような感じにしたい場合の話です。

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_empcursor in out t_empcursor);
end TestPkg;
create or replace package body TestPkg is
  procedure SelectRecords(p_empcursor in out t_empcursor) is
  begin
     open p_empcursor for select empno, ename from emp;
  end;
end TestPkg;

では、このプロシージャSelectRecordsの結果セットをグリッド表示してみましょう。

先程までのテストプログラムのTQueryの代わりにTOracleDataSetを使い、MemoのかわりにDBGridを配置して右のような画面を作ります。

OracleDataSet1.SQLは次のようにセットします
begin
   TestPkg.SelectRecords( :CURSOR );
end;

※重要!トリッキーですが…※

OracleDataSet1.Variablesのプロパティエディタで Cursor型のVariableとしてCURSORを定義します

こうすると、この変数が、当データセットのためのカーソルになるのです。

Button1Clickイベントで、OracleDataset1を開くように設定しておく
procedure TForm1.Button1Click(Sender: TObject);
begin
  OracleDataSet1.Open;
end;

これを実行すると、プロシージャが実行され、出力用のカーソルの指すデータセットがグリッド表示されます。

そうです。Oracleのストアドプロシージャでselect文を実行させた、その結果をデータベース対応コンポーネントで参照・編集が可能です。

補足
カーソルの定義に、ROWIDを取得対象に含めることで、更新可能なデータセットになります。(DOAによるデータベース更新に関するトピックを参照のこと)