機械翻訳について

2.3 ストアド・プロシージャおよびストアド・ファンクションの実行

プロシージャ機能を使用すると、ゲートウェイはSybaseデータベースで定義されたストアド・プロシージャを実行できます。 ゲートウェイを再リンクしたり、プロシージャをゲートウェイに定義する必要はありませんが、プロシージャのアクセス権限はゲートウェイによるアクセスを許可する必要があります。

Standard PL/SQL文は、ストアド・プロシージャの実行に使用されます。

ゲートウェイは、相互に排他的な3つのモードでストアド・プロシージャをサポートしています:

  • 通常モード: IN/OUT引数にのみアクセスできます

  • 戻り値モード: すべてのストアド・プロシージャの戻り値があります

  • 結果セット・モード: 出力値は、最後の結果セットとして使用できます

2.3.1 戻り値およびストアド・プロシージャ

デフォルトでは、すべてのストアド・プロシージャおよび関数は、ユーザーに戻り値を返しません。

戻り値を有効にするには、初期化パラメータ・ファイルでHS_FDS_PROC_IS_FUNCパラメータを設定します。

関連項目:

初期化パラメータ・ファイルとHS_FDS_PROC_IS_FUNCパラメータの編集の詳細は、「初期化パラメータ」を参照してください。

ノート:

HS_FDS_PROC_IS_FUNCゲートウェイ初期化パラメータを設定する場合は、既存のすべてのストアド・プロシージャのプロシージャ実行文の構文を変更する必要があります。

次の例では、従業員名JOHN SMYTHE がSybaseストアド・プロシージャREVISE_SALARYに渡されます。 ストアド・プロシージャは、Sybaseデータベースから給与値を取得し、JOHN SMYTHEの新しい年次給与を計算します。 RESULTで戻された改訂済給与は、Oracleデータベースの表でEMPを更新するために使用されます:

DECLARE
  INPUT VARCHAR2(15);
  RESULT NUMBER(8,2);
BEGIN
  INPUT := 'JOHN SMYTHE';
  RESULT := REVISE_SALARY@SYBS(INPUT);
  UPDATE EMP SET SAL = RESULT WHERE ENAME =: INPUT;
END;
/

プロシージャ機能は、Oracle以外のデータ型をPL/SQLデータ型との間で自動的に変換します。

2.3.2 結果セットとストアド・プロシージャ

Oracle Database Gateway for Sybaseは、結果セットを返すストアド・プロシージャをサポートします。

デフォルトでは、すべてのストアド・プロシージャおよび関数は、ユーザーに結果セットを返しません。 結果セットを有効にするには、初期化パラメータ・ファイルでHS_FDS_RESULTSET_SUPPORTパラメータを設定します。

関連項目:

初期化パラメータ・ファイルとHS_FDS_RESULTSET_SUPPORTパラメータの編集の詳細は、「初期化パラメータ」を参照してください。 Oracle以外のデータベースでの結果セットに対するOracleサポートの詳細は、Oracle Database異機種間接続ユーザー・ガイドを参照してください。

ノート:

HS_FDS_RESULTSET_SUPPORTゲートウェイ初期化パラメータを設定する場合は、既存のすべてのストアド・プロシージャに対してプロシージャ実行文の構文を変更する必要があります。そうしないと、エラーが発生します。

Oracle Database Gateway for Sybaseを介して結果セットを含むストアド・プロシージャにアクセスすると、異機種間サービスの順次モードになります。

Oracle Database Gateway for Sybaseは、プロシージャの説明中に異機種間サービスに次の情報を返します:

  • リモート・ストアド・プロシージャのすべての入力引数
  • 出力引数はなし
  • 参照カーソル・タイプの1つの出力引数(ストアド・プロシージャから戻される最初の結果セットに対応)

クライアント・プログラムは、仮想パッケージ関数dbms_hs_result_set.get_next_result_setを使用して、後続の結果セットの参照カーソルを取得する必要があります。 最後に返される結果セットは、プロシージャのout引数です。

結果セットへのアクセスの制限は次のとおりです:

  • リモート・ストアド・プロシージャから戻された結果セットは、送信された順に取得される必要があります
  • ストアド・プロシージャの実行時に、以前に実行されたストアド・プロシージャから戻された結果セットがすべて(データが完全に完了しているかどうかに関係なく)クローズされます

次の例では、Sybaseストアド・プロシージャを実行して、Sybaseからemp表およびdept表の内容をフェッチします:

create procedure REFCURPROC (@arg1 varchar(255), @arg2 varchar(255) output)
as
select @arg2 = @arg1
select * from EMP
select * from DEPT
go

このストアド・プロシージャは、入力パラメータarg1を出力パラメータarg2に割り当て、参照カーソルrc1で問合せSELECT * FROM EMPを開き、参照カーソルrc2で問合せSELECT * FROM DEPTを開きます。

ノート:

ストアド・プロシージャを作成する前に、チェーン・モードを設定する必要があります。 Sybaseで次のコマンドを発行: set chained on

2.3.2.1 順次モードでの結果セットからのOCIプログラム・フェッチ

結果セットから順次モードでフェッチするOCIプログラムの例。

次の例は、結果セットから順次モードでフェッチするOCIプログラムを示しています:

OCIEnv *ENVH;
OCISvcCtx *SVCH;
OCIStmt *STMH;
OCIError *ERRH;
OCIBind *BNDH[3];
OraText arg1[20];
OraText arg2[255];
OCIResult *rset;
OCIStmt *rstmt;
ub2 rcode[3];
ub2 rlens[3];
sb2 inds[3];
OraText *stmt = (OraText *) "begin refcurproc@SYBS(:1,:2,:3); end;";
OraText *n_rs_stm = (OraText *)
  "begin :ret := DBMS_HS_RESULT_SET.GET_NEXT_RESULT_SET@SYBS; end;";

/* Prepare procedure call statement */

/* Handle Initialization code skipped */
OCIStmtPrepare(STMH, ERRH, stmt, strlen(stmt), OCI_NTV_SYNTAX, OCI_DEFAULT);

/* Bind procedure arguments */
inds[0] = 0;
strcpy((char *) arg1, "Hello World");
rlens[0] = strlen(arg1);
OCIBindByPos(STMH, &BNDH[0], ERRH, 1, (dvoid *) arg1, 20, SQLT_CHR,
             (dvoid *) &(inds[0]), &(rlens[0]), &(rcode[0]), 0, (ub4 *) 0, 
             OCI_DEFAULT);
inds[1] = -1;
OCIBindByPos(STMH, &BNDH[1], ERRH, 1, (dvoid *) arg2, 20, SQLT_CHR,
             (dvoid *) &(inds[1]), &(rlens[1]), &(rcode[1]), 0, (ub4 *) 0, 
             OCI_DEFAULT);

inds[2] = 0;
rlens[2] = 0;
OCIDescriptorAlloc(ENVH, (dvoid **) &rset, OCI_DTYPE_RSET, 0, (dvoid **) 0);
OCIBindByPos(STMH, &BNDH[2], ERRH, 2, (dvoid *) rset, 0, SQLT_RSET,
             (dvoid *) &(inds[2]), &(rlens[2]), &(rcode[2]),
             0, (ub4 *) 0, OCI_DEFAULT);

/* Execute procedure */
OCIStmtExecute(SVCH, STMH, ERRH, 1, 0, (CONST OCISnapshot *) 0,
               (OCISnapshot *) 0, OCI_DEFAULT);

/* Convert result set to statement handle */
OCIResultSetToStmt(rset, ERRH);
rstmt = (OCIStmt *) rset;

/* After this the user can fetch from rstmt */
/* Issue get_next_result_set call to get handle to next_result set */
/* Prepare Get next result set procedure call */

OCIStmtPrepare(STMH, ERRH, n_rs_stm, strlen(n_rs_stm), OCI_NTV_SYNTAX,
               OCI_DEFAULT);

/* Bind return value */
OCIBindByPos(STMH, &BNDH[1], ERRH, 1, (dvoid *) rset, 0, SQLT_RSET,
             (dvoid *) &(inds[1]), &(rlens[1]), &(rcode[1]),
             0, (ub4 *) 0, OCI_DEFAULT);

/* Execute statement to get next result set*/
OCIStmtExecute(SVCH, STMH, ERRH, 1, 0, (CONST OCISnapshot *) 0,
               (OCISnapshot *) 0, OCI_DEFAULT);

/* Convert next result set to statement handle */
OCIResultSetToStmt(rset, ERRH);
rstmt = (OCIStmt *) rset;

/* Now rstmt will point to the second result set returned by the
remote stored procedure */

/* Repeat execution of get_next_result_set to get the output arguments */

2.3.2.2 PL/SQL順次モードでの結果セットからのプログラム・フェッチ

結果セットから順次モードでフェッチするPL/SQLプログラムの例。

loc_empがSybase emp表とまったく同じローカル表であるとします。 同じ仮定がloc_deptにも当てはまります。outargsは、Sybaseストアド・プロシージャのout引数に対応する列を含む表です。

create or replace package rcpackage is
  type RCTYPE is ref cursor;
end rcpackage;
/
declare
  rc1 rcpackage.rctype;
  rec1 loc_emp%rowtype;
  rc2 rcpackage.rctype;
  rec2 loc_dept%rowtype;
  rc3 rcpackage.rctype;
  rec3 outargs%rowtype;
  out_arg varchar2(255);

begin

  -- Execute procedure
  out_arg := null;  refcurproc@SYBS('Hello World', out_arg, rc1);

  -- Fetch 20 rows from the remote emp table and insert them into loc_emp
  for i in 1 .. 20 loop
    fetch rc1 into rec1;
    insert into loc_emp (rec1.empno, rec1.ename, rec1.job,
    rec1.mgr, rec1.hiredate, rec1.sal, rec1.comm, rec1.deptno);
  end loop;

  -- Close ref cursor
  close rc1;

  -- Get the next result set returned by the stored procedure
  rc2 := dbms_hs_result_set.get_next_result_set@SYBS;

  -- Fetch 5 rows from the remote dept table and insert them into loc_dept
  for i in 1 .. 5 loop
    fetch rc2 into rec2;
    insert into loc_dept values (rec2.deptno, rec2.dname, rec2.loc);
  end loop;

  --Close ref cursor
  close rc2;

  -- Get the output arguments from the remote stored procedure
  -- Since we are in sequential mode, they will be returned in the
  -- form of a result set
  rc3 := dbms_hs_result_set.get_next_result_set@SYBS;

  -- Fetch them and insert them into the outarguments table
  fetch rc3 into rec3;
  insert into outargs (rec3.outarg, rec3.retval);

  -- Close ref cursor
  close rc3;

end;
/