4.3 ゲートウェイによるDRDAサーバーのストアド・プロシージャの使用
ゲートウェイのプロシージャ機能により、DRDAサーバーのネイティブ・ストアド・プロシージャを起動できます。
ストアド・プロシージャがDRDAサーバーに定義されると、ゲートウェイは既存のDRDAサーバー定義を使用してプロシージャを実行できます。 ゲートウェイでは、DB2ストアド・プロシージャをコールするための特別な定義は必要ありません。 Standard Oracle PL/SQLは、ストアド・プロシージャを実行するためにOracleアプリケーションで使用されます。
「図4-2」では、Oracleアプリケーションは、DRDAサーバーに定義されている empproc ストアド・プロシージャをコールします(たとえば、z/OSの場合はDB2 UDB)。
図4-2 DRDAサーバーのストアド・プロシージャの実行

「図4-2 DRDAサーバーのストアド・プロシージャの実行」の説明
アプリケーションの観点からすると、DB2ストアド・プロシージャを実行することは、リモートOracle Databaseインスタンスでストアド・プロシージャを起動することと変わりません。
- 「OracleアプリケーションおよびDRDAサーバーのストアド・プロシージャの完了」
OracleアプリケーションでDB2ストアド・プロシージャをコールするには、まず、DB2 SQLのIBMリファレンス・ドキュメントに記載されているプロシージャを使用して、DB2システムにDB2ストアド・プロシージャを作成する必要があります。 - 「DB2でのプロシージャ機能の考慮事項」
ゲートウェイでのプロシージャ機能の使用には、特別な考慮事項があります。 - 「結果セットとストアド・プロシージャ」
Oracle Database Gateway for DRDAは、結果セットを返すストアド・プロシージャをサポートします。
親トピック: アプリケーションの開発
4.3.1 OracleアプリケーションおよびDRDAサーバーのストアド・プロシージャの完了
OracleアプリケーションでDB2ストアド・プロシージャをコールするには、まず、DB2 SQLのIBMリファレンス・ドキュメントに記載されているプロシージャを使用して、DB2システムにDB2ストアド・プロシージャを作成する必要があります。
DB2でストアド・プロシージャが定義されると、ゲートウェイでは標準のPL/SQLコールを使用してデータにアクセスできます。 たとえば、従業員名John Smytheは、DB2ストアド・プロシージャREVISE_SALARYに渡されます。 DB2ストアド・プロシージャは、John Smytheの新しい年次給与を計算するために、DB2データベースから給与値を取得します。 結果として戻される改訂済給与は、OracleデータベースのEMP表を更新するために使用されます:
DECLARE INPUT VARCHAR2(15); RESULT NUMBER(8,2); BEGIN INPUT := âJOHN SMYTHE'; REVISE_SALARY@DB2(INPUT, RESULT); UPDATE EMP SET SAL = RESULT WHERE ENAME = INPUT; END;
ゲートウェイは、DRDAサーバーでストアド・プロシージャを実行するためのコールを受信すると、まずサーバー・カタログでプロシージャ名を検索します。 ストアド・プロシージャを定義する情報は、各DRDAサーバーの様々な形式で格納されます。 たとえば、iSeriesのDB2 UDBでは、表QSYS2.SYSPROCSおよびQSYS2.SYSPARMSが使用されます。 ゲートウェイには、アクセスしているDRDAサーバーに応じて、検索する既知のカタログのリストがあります。
カタログの検索順序は、カタログがロケーション指標(SYSIBM.SYSPROCEDURESのLUNAMEなど)、認可IDまたは所有者ID (SYSIBM.SYSPROCEDURESのAUTHID、SYSIBM.SYSROUTINESのOWNERなど)をサポートしているかどうかによって異なります。
一部のDRDAサーバーでは、空白またはパブリックの権限修飾子が許可されます。 現在接続されているDRDAサーバーでこの形式の修飾がサポートされている場合、ゲートウェイは、カタログ内のプロシージャ名を検索するときにそれらの命名規則を適用します。
一致規則では、最初にパブリック定義が検索され、次に所有者で修飾されたプロシージャ名が検索されます。 詳細は、DB2 SQLのIBMリファレンス・ドキュメントを参照してください。
4.3.2 DB2でのプロシージャ機能の考慮事項
ゲートウェイでのプロシージャ機能の使用には、特別な考慮事項があります。
たとえば:
- PL/SQLレコードは、DB2ストアド・プロシージャの起動時にパラメータとして渡すことはできません。
- ゲートウェイは、DB2ストアド・プロシージャの
GENERALおよびDB2SQLリンケージ規則をサポートしています。 どちらのリンケージ規則も、DB2ストアド・プロシージャとの間で渡されるパラメータをNULLにすることはできません。
4.3.3 結果セットとストアド・プロシージャ
Oracle Database Gateway for DRDAは、結果セットを返すストアド・プロシージャをサポートします。
デフォルトでは、すべてのストアド・プロシージャおよび関数は、ユーザーに結果セットを返しません。 結果セットを有効にするには、初期化パラメータ・ファイルでHS_FDS_RESULTSET_SUPPORTパラメータを設定します。
関連項目:
初期化パラメータ・ファイルおよびHS_FDS_RESULTSET_SUPPORTパラメータの編集の詳細は、「初期化パラメータ」を参照してください。 Oracle以外のデータベースでの結果セットに対するOracleサポートの詳細は、「Oracle Database異機種間接続ユーザー・ガイド」を参照してください。
ノート:
HS_FDS_RESULTSET_SUPPORTゲートウェイ初期化パラメータを設定する場合は、既存のすべてのストアド・プロシージャに対してプロシージャ実行文の構文を変更する必要があります。そうしないと、エラーが発生します。
Oracle Database Gateway for DRDAを介して結果セットを含むストアド・プロシージャにアクセスすると、異機種間サービスの順次モードになります。 ゲートウェイは、手順の説明中に異機種間サービスに次の情報を返します:
- リモート・ストアド・プロシージャのすべての入力引数
- 出力引数はなし
- 参照カーソル・タイプの1つの出力引数(ストアド・プロシージャから戻される最初の結果セットに対応)
クライアント・プログラムは、仮想パッケージ関数DBMS_HS_RESULT_SET.GET_NEXT_RESULT_SETを使用して、後続の結果セットの参照カーソルを取得する必要があります。 最後に返される結果セットは、プロシージャのout引数です。
結果セットへのアクセスの制限は次のとおりです:
- リモート・ストアド・プロシージャから戻された結果セットは、送信された順に取得される必要があります。
- ストアド・プロシージャを実行すると、データが完全に取得されたかどうかに関係なく、以前に実行されたストアド・プロシージャから戻された結果セットがすべてクローズされます。
次の例では、UDBストアド・プロシージャを実行して、UDBからEMPおよびDEPT表の内容をフェッチします:
CREATE PROCEDURE REFCURPROC (IN STRIN VARCHAR(255), OUT STROUT VARCHAR(255) )
RESULT SETS 3 LANGUAGE SQL
BEGIN
DECLARE TEMP CHAR (20);
DECLARE C1 CURSOR WITH RETURN TO CALLER FOR
SELECT * FROM TKHOEMP;
DECLARE C2 CURSOR WITH RETURN TO CALLER FOR
SELECT * FROM TKHODEPT;
OPEN C1;
OPEN C2;
SET STROUT = STRIN;
END
- 「順次モードでの結果セットからのOCIプログラム・フェッチ」
この例では、結果セットから順次モードでフェッチするOCIプログラムを示します。 - 「PL/SQL順次モードでの結果セットからのプログラム・フェッチ」
この例は、結果セットから順次モードでフェッチするPL/SQLプログラムを示しています。
4.3.3.1 順次モードでの結果セットからの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@UDB(:1,:2,:3); end;";
OraText *n_rs_stm = (OraText *)
"begin :ret := DBMS_HS_RESULT_SET.GET_NEXT_RESULT_SET@UDB; 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 */
親トピック: 結果セットとストアド・プロシージャ
4.3.3.2 PL/SQL順次モードでの結果セットからのプログラム・フェッチ
この例は、結果セットから順次モードでフェッチするPL/SQLプログラムを示しています。
表LOC_EMPは、UDB EMP表とまったく同じローカル表であるとします。 LOC_DEPTと同じ仮定が適用されます。 OUTARGS は、SQL Serverストアド・プロシージャの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@UDB('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@UDB;
-- 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@UDB;
-- 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;
/
親トピック: 結果セットとストアド・プロシージャ