アプリケーションからのストアード・プロシージャーの呼び出し

ストアドプロシージャを実行するには、クライアントプログラムから呼び出すか、 Db2 command line processor から起動します。

始める前に

ストアード・プロシージャーを呼び出す前に、ストアード・プロシージャーを実行するために必要な以下の許可をすべて持っていることを確認してください。
  • CALL ステートメントで参照されるストアード・プロシージャーを実行するための許可。

    必要となる許可は、CALL ステートメントの形式が CALL procedure-name であるか、または CALL :host-variable であるかによって異なります。

  • ストアード・プロシージャーが呼び出すトリガーまたはユーザー定義関数を実行するための許可。
  • ストアード・プロシージャー・パッケージ、およびそのストアード・プロシージャー・パッケージの 下のすべてのパッケージを実行するための許可

    例えば、ストアード・プロシージャーがユーザー定義関数を呼び出す場合、それらのユーザー定義関数のパッケージを実行するための許可が必要です。

このタスクについて

ストアード・プロシージャーを呼び出すアプリケーション・プログラムは、以下のアクションを 1 つ以上実行することができます。
  • 複数のストアード・プロシージャーを呼び出す。
  • 単一のストアード・プロシージャーを、 同一レベルまたは別レベルのネストで、複数回呼び出す。 ただし、呼び出し間でストアード・プロシージャーの変数がそのまま残るとは想定しないでください。

    ストアドプロシージャがメインプログラムとして実行される場合、 Language Environment® は各呼び出し前に、ストアドプロシージャが使用するストレージを再初期化します。 ストアード・プロシージャー用のプログラム変数は、 ある呼び出しから次の呼び出しの間ではそのまま残っていません。

    ストアドプロシージャがサブプログラムとして実行される場合、 Language Environment は呼び出し間のストレージを初期化しません。 ストアード・プロシージャーのプログラム変数は、ある呼び出しから次の呼び出しの間は そのまま残しておくことができます。 しかし、以下の理由から、プログラム変数が、あるストアード・プロシージャー呼び出しから別のストアード・プロシージャー呼び出しまで使用可能であると想定すべきではありません。
    • 他のユーザーが作成したストアドプロシージャは、 Language Environment のインスタンス内で、あなたのストアドプロシージャの実行と実行の間に実行される可能性があります。
    • 1 つのストアード・プロシージャーを連続して実行すると、異なるストアード・プロシージャー・アドレス・スペースで実行される場合があります。
    • z/OS® 演算子は、ストアドプロシージャの実行の間に Language Environment を更新する可能性があります。
  • ローカル・ストアード・プロシージャーまたはリモート・ストアード・プロシージャーを呼び出す。

    クライアントとサーバーの両方のアプリケーション環境が 2 フェーズ・コミット をサポートしている場合、コーディネーターはアプリケーション、サーバー、 およびストアード・プロシージャーの間の更新を制御します。 このいずれかが 2 フェーズ・コミットをサポートしていなければ、更新は失敗します。

  • CALL ステートメントをその他の SQL ステートメントと混用する。
  • いずれかのDb2 接続機能を使用します。

Db2呼び出し側アプリケーションの Db2スレッドの下にストアドプロシージャを実行します。つまり、ストアドプロシージャは呼び出し元の作業単位の一部であることを意味します。

JDBC および アプリケーション:これらの指示は ODBC、 および アプリケーションには適用されません。 JDBC ODBC なお、これらのアプリケーションからストアード・プロシージャーを呼び出す方法については、以下の情報を参照してください。

プロシージャー

アプリケーションからストアード・プロシージャーを呼び出すには、次のようにします。

  1. IN パラメーターおよび INOUT パラメーターに値を割り当てます。
  2. オプション: アプリケーションのパフォーマンスを向上させるには、LOB出力パラメータの長さをゼロに初期化します
  3. ストアード・プロシージャーがリモート・ロケーションに存在する場合、以下のアクションを実行します。
    1. OUT パラメーターに値を割り当てます。

      リモートの場所でストアドプロシージャを呼び出すと、ローカル Db2サーバーはパラメータが入力(IN)または出力(OUTまたはINOUT)パラメータかを判断できません。 したがって、リモート・ロケーションのストアード・プロシージャーを呼び出す前に、 すべての出力パラメーターの値を初期化する必要があります。

    2. オプション: リモートサーバーに接続するための明示的なCONNECTステートメントを発行します

      明示的にこのステートメントを発行しない場合、次のステップで 3 部構成の名前を使用してストアード・プロシージャーを識別することにより暗黙的にサーバーに接続できます。

      明示的な CONNECT ステートメントを発行する利点は、次のステップで説明する CALL ステートメントを他のオペレーティング・システムに移植可能であるということです。 暗黙的に接続する利点は、この余分な CONNECT ステートメントを発行する必要がないということです。

      要件 :リモートサーバーに暗黙的または明示的に接続するかを決定する際には、ASSOCIATE LOCATORまたはDESCRIBE PROCEDURE文を実行するプログラムの要件を考慮すること。 CALL ステートメントと ASSOCIATE LOCATORS または DESCRIBE PROCEDURE ステートメントで、同じ形式のプロシージャー名を使用する必要があります。
  4. SQL CALL ステートメントを使ってストアード・プロシージャーを呼び出します。 必ず互換性があるパラメーター・データ・タイプを渡してください。

    ストアード・プロシージャーがリモート・サーバーに存在し、明示的な CONNECT ステートメントを発行しなかった場合、3 部構成の名前を指定してストアード・プロシージャーを識別し、そのストアード・プロシージャーがあるサーバーに暗黙的に接続します。

    ネイティブ SQL プロシージャーの場合、デフォルトでストアード・プロシージャーのアクティブ・バージョンが呼び出されます。 オプションで、アクティブ・バージョン以外のストアード・プロシージャーのバージョンを指定できます。

    パラメーターに NULL 値を使用できるようにするには、標識変数を使用します。

  5. オプション: 手続きのステータスを取得します
  6. OUT パラメーターと INOUT パラメーターを組み込んで、出力を処理します。
  7. ストアード・プロシージャーが複数の結果セットを返す場合は、それらの結果セットを取得します。
    推奨: 結果セットを取得したらすぐに閉じ、頻繁にコミットを発行して、 Db2 のストレージ不足やEDM POOL FULLの状態を回避します。
  8. PL/I アプリケーションの場合、以下のアクションも実行します。
    1. ソース・コードにランタイム・オプション NOEXECOPS を組み込みます。
    2. コンパイル時オプション SYSTEM( MVS ) を指定してください。
    これらの追加手順により、 z/OS においてリンキング規約が正しく機能することが保証されます。
  9. C アプリケーションの場合、ソース・コードに次の行を組み込みます。
    #pragma runopts(PLIST(OS))

    このコードにより、 z/OS においてリンクの規約が正しく機能することが保証されます。

    このオプションは、その他のオペレーティング・システムには適用できません。 z/OS 以外の他のプラットフォームで C ストアドプロシージャを使用する場合は、次の例に示す条件付きコンパイルの形式のいずれかを使用して、 z/OS でコンパイルする場合のみこのオプションを含めます。

    形式 1
    #ifdef MVS
     #pragma runopts(PLIST(OS))
    #endif
    
    形式 2
    #ifndef WKSTN
     #pragma runopts(PLIST(OS))
    #endif
  10. アプリケーションをプリコンパイル、コンパイル、およびリンク・エディットして DBRM をバインドすることにより、その他のアプリケーションの場合と同様にアプリケーションを準備します。

    アプリケーションがリモート・ストアード・プロシージャーを呼び出す場合、DBRM をバインドするときに以下の追加の手順を実行します。

    • DBRM をローカル Db2 サーバーのパッケージにバインドします。 bindオプションにDBPROTOCOL(DRDA)を使用します。 ストアード・プロシージャー名を実行時まで解決できない場合は、バインド・オプション VALIDATE(RUN) も指定します。 ストアード・プロシージャー名に変数を使用する場合、またはストアード・プロシージャーがリモート・サーバーに存在する場合は、ストアード・プロシージャー名を実行時に解決できない可能性があります。
    • リモート Db2 サーバーでDBRM をパッケージにバインドします。 クライアント・プログラムが複数のサーバーにアクセスする場合は、それぞれのサーバーでプログラムをバインドします。
    • すべてのパッケージをローカル Db2 サーバーの計画にバインドします。 bindオプションにDBPROTOCOL(DRDA)を使用します。
  11. ストアード・プロシージャーが正常に完了したことを確認します。
    ストアード・プロシージャーが異常終了すると、 Db2 は以下のアクションを実行します。
    • 呼び出し側プログラムは、ストアード・プロシージャーが失敗した ことを知らせる SQL エラーを受け取ります。
    • Db2 は、呼び出し側プログラムの作業単位を、ロールバックの状態にします。
    • Db2 は、以下条件のいずれかの場合、ストアード・プロシージャーを停止し、後続の呼び出しは失敗します。
      • 異常終了回数が、ストアード・プロシージャーの STOP AFTER n FAILURES 値に等しい。
      • 異常終了回数が、サブシステムのデフォルトの MAX ABEND COUNT 値に等しい。
    • このストアドプロシージャは異常終了状態を処理せず、 Language Environment がアプリケーションが使用するストレージを回復できるよう環境をリフレッシュします。 Db2 ほとんどの場合、環境を再始動する必要はありません。
    • ストアード・プロシージャー・アドレス・スペースを開始する JCL プロシージャーの DD ステートメント CEEDUMP でデータ・セットが割り振られます。 この場合、 Language Environment はこのデータセットに小さな診断ダンプを出力します。 ダンプ内の情報を使用してストアード・プロシージャーをデバッグします。
    • データ共有環境では、ストアード・プロシージャーが STOPABN 状況に設定されるのは、異常終了が発生したメンバーに対してのみです。 呼び出し側プログラムは、データ共有グループの他のメンバーからストアード・プロシージャーを呼び出すことができます。 他のすべてのメンバーの状況は STARTED です。

例 1: 簡単なCALL ステートメント
次の例は、ストアード・プロシージャー A を呼び出すために使用する単純な CALL ステートメントを示しています。
EXEC SQL CALL A (:EMP, :PRJ, :ACT, :EMT, :EMS, :EME, :TYPE, :CODE);
この例において、:EMP 、:PRJ、:ACT、:EMT、:EMS、:EME、:TYPE、および :CODE は、 アプリケーション・プログラムで前に宣言したホスト変数です。
例2:複数のパラメータ値のホスト構造の使用
単純な CALL ステートメントの例で示したように、各パラメーターを別々に渡す代わりに、それらをホスト構造としてまとめて渡すことができます。 例えば、アプリケーション内で次のホスト構造を定義したとします。
struct {
  char EMP[7];
  char PRJ[7];
  short ACT;
  short EMT;
  char  EMS[11];
  char  EME[11];
} empstruc;
その後、次の CALL ステートメントを発行してストアード・プロシージャー A を呼び出すことができます。
EXEC SQL CALL A (:empstruc, :TYPE, :CODE);
例 3: リモート・ストアード・プロシージャーの呼び出し
  • 次の例は、明示的に LOCA に接続してから CALL ステートメントを発行する方法を示しています。
    EXEC SQL CONNECT TO LOCA;
    EXEC SQL CALL SCHEMAA.A (:EMP, :PRJ, :ACT, :EMT, :EMS, :EME,
      :TYPE, :CODE);
  • 次の例は、CALL ステートメントでストアード・プロシージャー A の 3 部構成の名前を指定することにより、暗黙的に LOCA に接続する方法を示しています。
    EXEC SQL CALL LOCA.SCHEMAA.A (:EMP, :PRJ, :ACT, :EMT, :EMS,
      :EME, :TYPE, :CODE);
例 4: NULL 値を持つ可能パラメーターの引き渡し
上記の例では、入力パラメーターはいずれも NULL 値を持てないものとしています。 次の例は、パラメーター・リストで標識変数を渡すことにより、パラメーターに NULL 値を使用できるようにする方法を示しています。
EXEC SQL CALL A (:EMP :IEMP, :PRJ :IPRJ, :ACT :IACT,
                 :EMT :IEMT, :EMS :IEMS, :EME :IEME,
                 :TYPE :ITYPE, :CODE :ICODE);
この例で、:IEMP、:IPRJ、:IACT、:IEMT、:IEMS、:IEME、:ITYPE、および :ICODE は、パラメーターの標識変数です。
例 5: 文字列定数と NULL 値を渡す
次の CALL ステートメントの例は、整数と文字ストリングの定数、NULL 値、およびいくつかのホスト変数を渡します。
EXEC SQL CALL A ('000130', 'IF1000', 90, 1.0, NULL, '2009-10-01',
                 :TYPE, :CODE);
例 6: ストアード・プロシージャー名にホスト変数を使用します。
次の CALL ステートメントの例では、ストアード・プロシージャーの名前にホスト変数を使用します。
EXEC SQL CALL :procnm (:EMP, :PRJ, :ACT, :EMT, :EMS, :EME,
  :TYPE, :CODE);

ストアード・プロシージャー名はAであるとします。 ホスト変数 procnm は、長さが 255 以下の文字変数で、値「A」が含まれている文字変数です。 この方法を使用するのは、ストアード・プロシージャーの名前が事前には不明であるが、パラメーター・リスト規則は判明している場合です。

例 7: SQLDA を使って、パラメーターを単一の構造で渡します。
次の CALL ステートメントの例は、別々のホスト変数としてではなく、単一構造 SQLDA でパラメーターを渡す方法を示しています。
EXEC SQL CALL A USING DESCRIPTOR :sqlda;

sqlda は SQLDA の名前です。

SQLDA を使用することのメリットの 1 つは、ストアード・プロシージャー・パラメーター値のコード化スキームを変更できることです。 例えば、ストアード・プロシージャーが実行されるサブシステムが EBCDIC コード化スキームを使用している場合に、データを ASCII CCSID 437 で取り出すには、出力パラメーターの CCSID を SQLDA の SQLVAR フィールドに指定できます。

パラメーターの CCSID をオーバーライドする手法は、変数の CCSID をオーバーライドする手法と同じです。 この手法では、プログラムに可変リスト SELECT ステートメント用の動的 SQL を組み込みます。 この技法を使用する場合は、 パラメーターに対して定義したコード化スキームが SQLDA に指定したコード化スキームとは 異なっている必要があります。 それ以外の場合、変換は行われません。

パラメーターに対して定義されたコード化スキームとは、CREATE PROCEDURE ステートメントで指定したコード化スキームです。 このステートメントでコード化スキームを指定しなかった場合、パラメーターに対して定義されたコード化スキームが、サブシステムのデフォルトのコード化スキームになります。

例8: 再使用可能な CALL ステートメント
次の CALL ステートメントの例は、ストアード・プロシージャーにホスト変数名、パラメーター・リストに SQLDA を使用するため、異なるパラメーター・リストを使用する異なるストアード・プロシージャーの呼び出しに再利用できます。
EXEC SQL CALL :procnm USING DESCRIPTOR :sqlda;

クライアント・プログラムは、ストアード・プロシージャー名をホスト変数 procnm に割り当てて、SQL CALL ステートメントを発行する前に SQLDA を パラメーター情報とともにロードしなければなりません。