DB2 10.5 for Linux, UNIX, and Windows

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

CLI アプリケーションは、CALL プロシージャー・ステートメントを発行することにより、ストアード・プロシージャーを呼び出します。

始める前に

ストアード・プロシージャーを呼び出す前に、CLI 環境が初期設定されていて、データベース接続が確立されていることを確認してください。

手順

ストアード・プロシージャーを呼び出すには、以下のようにします。

  1. ストアード・プロシージャーの IN、INOUT、 および OUT パラメーターにそれぞれ対応するアプリケーション・ホスト変数を宣言します。 アプリケーション変数のデータ・タイプとデータ長が、ストアード・プロシージャーの引数のデータ・タイプとデータ長に一致することを確認してください。CLI ドライバーは、パラメーター・マーカーとして使用して、 ストアード・プロシージャーを呼び出すことをサポートしています。
  2. IN、INOUT、および OUT パラメーターにそれぞれ対応するアプリケーション変数を初期設定します。
  3. CALL SQL ステートメントを作成します。 以下に、パラメーター・マーカー引数を使用した CALL ステートメントの例を示します。
      SQLCHAR *stmt = (SQLCHAR *)"CALL OUT_LANGUAGE (?)";
    名前付きパラメーター・マーカー (:language など) を使用するには、 EnableNamedParameterSupport 構成キーワードを TRUE に設定することによって、名前付きパラメーターの処理を明示的に有効にする必要があります。
      SQLCHAR *stmt = (SQLCHAR *)"CALL OUT_LANGUAGE (:language)";
    アプリケーションのパフォーマンスを最適化するために、CALL プロシージャー・ステートメント内でパラメーター・マーカーを使用してから、ホスト変数をこれらのパラメーター・マーカーにバインドすることができます。CALL ステートメントに含まれる IN 引数にストリング・リテラルを指定するには、リテラル CALL ステートメントを ODBC 呼び出しエスケープ節の区切り文字 { } で囲みます。以下に、リテラル CALL ステートメントの例を示します。
      SQLCHAR *stmt = (SQLCHAR *)"{CALL IN_PARAM (123, 'Hello World!')}";
    CALL プロシージャー・ステートメントでストリング・リテラルおよび ODBC エスケープ節を使用する場合、ストリング・リテラルは、IN モード・ストアード・プロシージャー引数としてのみ指定できます。INOUT および OUT モード・ストアード・プロシージャー引数は、引き続きパラメーター・マーカーで指定する必要があります。
  4. オプション: SQLPrepare() 関数を呼び出して CALL ステートメントを準備します。
  5. SQLBindParameter() 関数を呼び出して、CALL プロシージャー・ステートメントの各パラメーターをバインドします。 各パラメーターが、SQL_PARAM_INPUT パラメーター・タイプ、SQL_PARAM_OUTPUT パラメーター・タイプ、または SQL_PARAM_INPUT_OUTPUT パラメーター・タイプに正しくバインドされることを確認してください。各パラメーターが対応するパラメーター・タイプに正しくバインドされない限り、CALL プロシージャー・ステートメントの処理によって予期しない結果となる可能性があります。正しくないパラメーター・バインディングの一例は、入力パラメーターが誤って SQL_PARAM_OUTPUT パラメーター・タイプにバインドされることです。
    データベース・クライアントとデータベース・サーバーとの間のネットワーク・フローを減らすには、ストアード・プロシージャーにバッチ CALL ステートメントを実行します。ストアード・プロシージャーのバッチ CALL ステートメントを作成すると、CLI アプリケーションは、異なるストアード・プロシージャー引数のセットごとにSQLExecute()関数またはSQLExecDirect()関数を繰り返し呼び出す必要がなくなります。CLI アプリケーションでバッチ CALL ステートメントを実行するには、以下の追加ステップを実行します。
    1. ストアード・プロシージャー引数の配列変数を宣言します。INPUT 引数の配列変数を宣言する場合、配列に必要なデータを設定する必要があります。INOUT タイプまたは OUT タイプのストアード・プロシージャー引数も、CALL ステートメントの実行後に配列の形でデータを取得できます。
      SQLINTEGER param1[5] = {1,2,3,4,5};
      SQLINTEGER param2[5] = {0,0,0,0,0};
    2. SQL_ATTR_PARAMSET_SIZE ステートメント属性を設定して、ストアード・プロシージャー引数に使用する配列サイズを指定します。
      // specifying batching array size of 5
      cliRC = SQLSetStmtAttr( hstmt,
                              SQL_ATTR_PARAMSET_SIZE,
                              (SQLPOINTER) 5,
                              SQL_IS_INTEGER );
    3. CALL プロシージャー・ステートメントの各パラメーターに対し、SQLBindParameter() 関数を使用して配列変数をバインドします。
      cliRC = SQLBindParameter( hstmt,
                                1,
                                SQL_PARAM_INPUT,
                                SQL_C_LONG,
                                SQL_INTEGER,
                                0, 0,
                                param1, ...);
      
      cliRC = SQLBindParameter( hstmt,
                                2,
                                SQL_PARAM_OUTPUT,
                                SQL_C_LONG,
                                SQL_INTEGER,
                                0, 0,
                                param2, ...);
    重要: バッチ呼び出しステートメントでは、以下のステートメント属性はサポートされていません。
    • SQL_ATTR_INTERLEAVED_PUTDATA
    • SQL_ATTR_INTERLEAVED_STREAM_PUTDATA
    • SQL_ATTR_INTERLEAVED_GETDATA
    • SQL_ATTR_INTERLEAVED_STREAM_GETDATA
    • SQL_ATTR_STREAM_OUTPUTLOB_ON_CALL
  6. SQLExecDirect() 関数を使用して CALL プロシージャー・ステートメントを実行するか、ステップ 4 で CALL プロシージャー・ステートメントを準備済みの場合には、SQLExecute() 関数を実行します。
    注:
    • ストアード・プロシージャーを呼び出したアプリケーションまたはスレッドが、そのストアード・プロシージャーの完了前に終了する場合、ストアード・プロシージャーの実行も終了します。ストアード・プロシージャーには、ストアード・プロシージャーが終了してしまう場合にもデータベースが一貫した状態と望ましい状態を保つようなロジックを含める必要があります。
    • CLI ドライバーは、以下の条件を満たす場合に、暗黙的な COMMIT ステートメントの送信に関連する余分なネットワーク・トラフィックの発生を回避します。
      • 接続しているデータベース・サーバーは、DB2® for z/OS® バージョン 11 (新機能モード (NFM)) である。
      • ストアード・プロシージャーを呼び出すときに、自動コミット動作が有効にされた (SQL_ATTR_AUTOCOMMIT が ON である)。
      • ストアード・プロシージャーから返された結果セット全体が単一の照会ブロック内に収まっている。デフォルトの照会ブロック・サイズは 64K ですが、FET_BUF_SIZE (db2cli.ini キーワード) または FetchBufferSize (IBM® データ・サーバー・ドライバー構成キーワード) を使用して調整できます。
  7. SQLExecDirect()関数またはSQLExecute()関数の戻りコードを確認します。 戻りコードが SQL_SUCCESS_WITH_INFO または SQL_ERROR である場合、SQLGetDiagRec() 関数およびSQLGetDiagField()関数を使用してエラーの原因を判別します。

    複数の結果セットを返すストアード・プロシージャーに対してバッチ CALL ステートメントが発行された場合、返される結果セットは、パラメーター配列に指定されたパラメーター値の順序で使用可能になります。複数のカーソルにわたる結果セットをフェッチするには、SQLMoreResults() 関数、SQLNextResult() 関数、および SQLFetch() 関数を使用できます。

タスクの結果

ストアード・プロシージャーが正常に実行された場合、OUT パラメーターとしてバインドされた変数には、そのストアード・プロシージャーが CLI アプリケーションに戻したデータが含まれます。 OUT パラメーター・データ値は、SQLGetData() 関数を使用して取得できます。 ストアード・プロシージャーが順方向カーソルを介して 1 つ以上の結果セットを返した場合には、SQLFetch() 関数を使用して結果セットを取得できます。

ストアード・プロシージャーによって返された結果セットに含まれる列の数またはタイプが CLI アプリケーションで不明である場合は、 その結果セットに対して SQLNumResultCols() 関数、SQLDescribeCol() 関数、および SQLColAttribute() 関数を (この順序で) 呼び出して、この情報を判別することができます。

ストアード・プロシージャーから DATETYPE データが返される場合、DATETYPE データはロケールに依存したフォーマットで返されます。返される DATETYPE データのフォーマットを変更するには、以下のように DB2_SQLROUTINE_PREPOPTS レジストリー変数をロケールに依存しない値 (例えば ISO) に設定します。
  db2set DB2_SQLROUTINE_PREPOPTS="DATETIME ISO"

以下に、1 つの INPUT パラメーターと 1 つの OUTPUT パラメーターを持つストアード・プロシージャーに対してバッチ CALL ステートメントを実行する例を示します。
CREATE PROCEDURE testproc (IN var1 INTEGER, OUT var2 INTEGER )
LANGUAGE SQL
BEGIN
   var2 = var1 * 10;
END
//For IN parameter var1
SQLINTEGER param1[5] = {1,2,3,4,5};

//For OUT parameter var2
SQLINTEGER param2[5] = {0,0,0,0,0};
...
cliRC = SQLPrepare( hstmt, "CALL testproc(?,?)", SQL_NTS );

cliRC = SQLBindParameter( hstmt,
                          1,
                          SQL_PARAM_INPUT,
                          SQL_C_LONG,
                          SQL_INTEGER,
                          0, 0,
                          param1, ...);

cliRC = SQLBindParameter( hstmt,
                          2,
                          SQL_PARAM_OUTPUT,
                          SQL_C_LONG,
                          SQL_INTEGER,
                          0, 0,
                          param2, ...);

// Specify batching array size of 5
cliRC = SQLSetStmtAttr( hstmt,
                        SQL_ATTR_PARAMSET_SIZE,
                        (SQLPOINTER) 5,
                        SQL_IS_INTEGER );

// The single SQLExecute() will be equivalent to making five CALL statements
cliRC = SQLExecute( hstmt );

// Print values of param2 used for OUTPUT type
for (i=0; i<5; i++)
{
    printf (“param2[%d] = %d¥n”, i, param2[i]);
}
以下に、複数の結果セットを返すストアード・プロシージャーに対してバッチ CALL ステートメントを実行する例を示します。
CREATE PROCEDURE testproc (IN var1 INTEGER)
LANGUAGE SQL
BEGIN
   INSERT INTO myTable VALUES (var1);

   DECLARE CURSOR c1 ... 
   DECLARE CURSOR c2 ...
   DECLARE CURSOR c3 ...

   OPEN c1 ...
   OPEN c2 ...
   OPEN c3 ...
END
SQLINTEGER param1[5] = {1,2,3};
...
cliRC = SQLPrepare( hstmt, "CALL testproc(?)", SQL_NTS );

cliRC = SQLBindParameter( hstmt,
                          1,
                          SQL_PARAM_INPUT,
                          SQL_C_LONG,
                          SQL_INTEGER,
                          0, 0,
                          param1, ...);

// Specify batching array size of 3
cliRC = SQLSetStmtAttr( hstmt,
                        SQL_ATTR_PARAMSET_SIZE,
                        (SQLPOINTER) 3,
                        SQL_IS_INTEGER );

// The single SQLExecute() will be equivalent to making five CALL statements
cliRC = SQLExecute( hstmt );

//Sequentially Fetch all result sets opened by cursors

//Start with first result-set
while ((cliRC = SQLFetch(hstmt)) != SQL_NO_DATA_FOUND) 
    { // Take some action }

//Done with 1st result set. Move on to next result set
cliRC=SQLMoreResults(hstmt);
 
//Start with 2nd result set
while ((cliRC = SQLFetch(hstmt)) != SQL_NO_DATA_FOUND) 
    { // Take some action }

//Done with 2nd result set. Move on to next result set
cliRC=SQLMoreResults(hstmt);

//Start with 3rd result set
while ( (cliRC = SQLFetch(hstmt)) != SQL_NO_DATA_FOUND)
    { // Take some action }
...