DB2 CLI、ODBC、JDBC、または SQLJ クライアント・アプリケーションに 1 つまたは複数の結果セットを戻すように、ストアード・プロシージャーをコーディングすることができます。このサポートには以下のものが含まれます。
結果セットの処理についての追加情報は、以下を参照してください。
このストアード・プロシージャーの例では、以下のサポートされている言語で結果セットをクライアント・アプリケーションに戻す方法を示しています。
このストアード・プロシージャーの例は、 IN パラメーターを 1 つ受け入れ、 OUT パラメーター 1 つと結果セット 1 つを戻します。ストアード・プロシージャーでは IN パラメーターが使用されて、 STAFF 表で SALARY が IN パラメーターよりも大きい行の NAME、 JOB、SALARY 列の値を含む結果セットが作成されます。
CREATE PROCEDURE RESULT_SET_CLIENT (IN salValue DOUBLE, OUT sqlCode INTEGER) DYNAMIC RESULT SETS 1 LANGUAGE C PARAMETER STYLE GENERAL NO DBINFO FENCED READS SQL DATA PROGRAM TYPE SUB EXTERNAL NAME 'spserver!one_result_set_to_client'
SQL_API_RC SQL_API_FN one_result_set_to_client (double *insalary, sqlint32 *out_sqlerror) { EXEC SQL INCLUDE SQLCA; EXEC SQL WHENEVER SQLERROR GOTO return_error; l_insalary = *insalary; *out_sqlerror = 0; EXEC SQL DECLARE c3 CURSOR FOR (2) SELECT name, job, CAST(salary AS INTEGER) FROM staff WHERE salary > :l_insalary ORDER BY salary; EXEC SQL OPEN c3; (2) /* Leave cursor open to return result set */ return (0); (3) /* Copy SQLCODE to OUT parameter if SQL error occurs */ return_error: { *out_sqlerror = SQLCODE; EXEC SQL WHENEVER SQLERROR CONTINUE; return (0); } } /* end one_result_set_to_client function */
public static void resultSetToClient (double inSalaryThreshold, // double input int[] errorCode, // SQLCODE output ResultSet[] rs) // ResultSet output (4) throws SQLException { errorCode[0] = 0; // SQLCODE = 0 unless SQLException occurs try { // Get caller's connection to the database Connection con = DriverManager.getConnection("jdbc:default:connection"); // get salary result set using a parameter marker String query = "SELECT name, job, CAST(salary AS DOUBLE) " + "FROM staff " + "WHERE salary > ? " + "ORDER BY salary"; // prepare the SQL statement PreparedStatement stmt = con.prepareStatement(query); // set the value of the parameter marker (?) stmt.setDouble(1, inSalaryThreshold); // get the result set that will be returned to the client rs[0] = stmt.executeQuery(); (2) // to return a result set to the client, do not close ResultSet con.close(); (3) } catch (SQLException sqle) { errorCode[0] = sqle.getErrorCode(); } }
このクライアント・アプリケーションの例では、以下のサポートされている言語でストアード・プロシージャーからの結果セットを受け入れる方法が示されています。
このクライアント・アプリケーションの例は、 RESULT_SET_CLIENT ストアード・プロシージャーを呼び出し、 1 つの結果セットを受け入れます。それから、クライアント・アプリケーションは結果セットの内容を表示します。
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <sqlcli1.h> #include <sqlca.h> #include "utilcli.h" /* Header file for CLI sample code */ SQLCHAR stmt[50]; SQLINTEGER out_sqlcode; char out_buffer[33]; SQLINTEGER indicator; struct sqlca sqlca; SQLRETURN rc,rc1 ; char procname[254]; SQLHANDLE henv; /* environment handle */ SQLHANDLE hdbc; /* connection handle */ SQLHANDLE hstmt1; /* statement handle */ SQLHANDLE hstmt2; /* statement handle */ SQLRETURN sqlrc = SQL_SUCCESS; double out_median; int oneresultset1(SQLHANDLE); int main(int argc, char *argv[]) { SQLHANDLE hstmt; /* statement handle */ SQLHANDLE hstmt_oneresult; /* statement handle */ char dbAlias[SQL_MAX_DSN_LENGTH + 1] ; char user[MAX_UID_LENGTH + 1] ; char pswd[MAX_PWD_LENGTH + 1] ; /* Declare variables for passing data to INOUT_PARAM */ double inout_median; /* checks the command line arguments */ rc = CmdLineArgsCheck1( argc, argv, dbAlias, user, pswd ); if ( rc != 0 ) return( 1 ) ; /* allocate an environment handle */ printf("\n Allocate an environment handle.\n"); sqlrc = SQLAllocHandle( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv ) ; if ( sqlrc != SQL_SUCCESS ) { printf( "\n--ERROR while allocating the environment handle.\n" ) ; printf( " sqlrc = %d\n", sqlrc); printf( " line = %d\n", __LINE__); printf( " file = %s\n", __FILE__); return( 1 ) ; } /* allocate a database connection handle */ printf(" Allocate a database connection handle.\n"); sqlrc = SQLAllocHandle( SQL_HANDLE_DBC, henv, &hdbc ) ; HANDLE_CHECK( SQL_HANDLE_ENV, henv, sqlrc, &henv, &hdbc ) ; /* connect to the database */ printf( " Connecting to the database %s ...\n", dbAlias ) ; sqlrc = SQLConnect( hdbc, (SQLCHAR *)dbAlias, SQL_NTS, (SQLCHAR *)user, SQL_NTS, (SQLCHAR *)pswd, SQL_NTS ) ; HANDLE_CHECK( SQL_HANDLE_DBC, hdbc, sqlrc, &henv, &hdbc ) ; printf( " Connected to the database %s.\n", dbAlias ) ; /* set AUTOCOMMIT off */ sqlrc = SQLSetConnectAttr( hdbc, SQL_ATTR_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF, SQL_NTS) ; HANDLE_CHECK( SQL_HANDLE_DBC, hdbc, sqlrc, &henv, &hdbc ) ; /* allocate one or more statement handles */ printf(" Allocate a statement handle.\n"); sqlrc = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ; HANDLE_CHECK( SQL_HANDLE_DBC, hdbc, sqlrc, &henv, &hdbc ) ; sqlrc = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt_oneresult ) ; HANDLE_CHECK( SQL_HANDLE_DBC, hdbc, sqlrc, &henv, &hdbc ) ; /********************************************************\ * Call oneresultsettocaller stored procedure * \********************************************************/ rc = oneresultset1(hstmt_oneresult); rc = SQLFreeHandle( SQL_HANDLE_STMT, hstmt_oneresult ) ; HANDLE_CHECK( SQL_HANDLE_DBC, hdbc, rc, &henv, &hdbc ) ; /* ROLLBACK, free resources, and exit */ rc = SQLEndTran( SQL_HANDLE_DBC, hdbc, SQL_COMMIT ) ; HANDLE_CHECK( SQL_HANDLE_DBC, hdbc, rc, &henv, &hdbc ) ; printf("\nStored procedure rolled back.\n\n"); /* Disconnect from Remote Database */ rc = SQLFreeHandle( SQL_HANDLE_STMT, hstmt ) ; HANDLE_CHECK( SQL_HANDLE_DBC, hdbc, rc, &henv, &hdbc ) ; printf( "\n>Disconnecting .....\n" ) ; rc = SQLDisconnect( hdbc ) ; HANDLE_CHECK( SQL_HANDLE_DBC, hdbc, rc, &henv, &hdbc ) ; rc = SQLFreeHandle( SQL_HANDLE_DBC, hdbc ) ; HANDLE_CHECK( SQL_HANDLE_DBC, hdbc, rc, &henv, &hdbc ) ; rc = SQLFreeHandle( SQL_HANDLE_ENV, henv ) ; if ( rc != SQL_SUCCESS ) return( SQL_ERROR ) ; return( SQL_SUCCESS ) ; } int oneresultset1(hstmt) SQLHANDLE hstmt; /* statement handle */ { /********************************************************\ * Call one_result_set_to_client stored procedure * \********************************************************/ double insalary = 20000; SQLINTEGER salary_int; SQLSMALLINT num_cols; char name[40]; char job[10]; strcpy(procname, "RESULT_SET_CALLER"); (1) printf("\nCALL stored procedure: %s\n", procname); strcpy((char*)stmt,"CALL RESULT_SET_CALLER ( ?,? )"); rc = SQLPrepare(hstmt, stmt, SQL_NTS); STMT_HANDLE_CHECK( hstmt, rc); /* Bind the parameter to application variables () */ rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE,0, 0, &insalary, 0, NULL); rc = SQLBindParameter(hstmt, 2, SQL_PARAM_OUTPUT, SQL_C_LONG, SQL_INTEGER,0, 0, &out_sqlcode, 0, NULL); STMT_HANDLE_CHECK( hstmt, rc); rc = SQLExecute(hstmt); rc1 = SQLGetSQLCA(henv, hdbc, hstmt, &sqlca); STMT_HANDLE_CHECK( hstmt, rc); rc = SQLNumResultCols( hstmt, &num_cols ) ; STMT_HANDLE_CHECK( hstmt, rc); printf("Result set returned %d columns\n", num_cols); /* bind columns to variables */ rc = SQLBindCol( hstmt, 1, SQL_C_CHAR, name, 40, &indicator); STMT_HANDLE_CHECK( hstmt, rc); rc = SQLBindCol( hstmt, 2, SQL_C_CHAR, job, 10, &indicator); STMT_HANDLE_CHECK( hstmt, rc); rc = SQLBindCol( hstmt, 3, SQL_C_LONG, &salary_int, 0, &indicator); STMT_HANDLE_CHECK( hstmt, rc); /* fetch result set returned from stored procedure */ rc = SQLFetch( hstmt ); (2) rc1 = SQLGetSQLCA(henv, hdbc, hstmt, &sqlca); STMT_HANDLE_CHECK( hstmt, rc); printf("\n--------Name---------, --JOB--, ---Salary-- \n"); while (rc == SQL_SUCCESS && rc != SQL_NO_DATA_FOUND ) (3) { printf("%20s,%10s, %d\n",name,job,salary_int); rc = SQLFetch( hstmt ); } STMT_HANDLE_CHECK( hstmt, rc); /* Check that the stored procedure executed successfully */ if (rc == SQL_SUCCESS) { printf("Stored procedure returned successfully.\n"); } else { printf("Stored procedure returned SQLCODE %d\n", out_sqlcode); } rc = SQLCloseCursor(hstmt); return(rc); }
// prepare the CALL statement for RESULT_SET_CLIENT procName = "RESULT_SET_CLIENT"; sql = "CALL " + procName + "(?, ?)"; (1) callStmt = con.prepareCall(sql); // set input parameter to median value passed back by OUT_PARAM callStmt.setDouble (1, outMedian); // register the output parameter callStmt.registerOutParameter (2, Types.INTEGER); // call the stored procedure System.out.println ("\nCall stored procedure named " + procName); callStmt.execute(); // retrieve output parameter outErrorCode = callStmt.getInt(2); if (outErrorCode == 0) { System.out.println(procName + " completed successfully"); ResultSet rs = callStmt.getResultSet(); (2) while (rs.next()) { fetchAll(rs); (3) } // close ResultSet rs.close(); } else { // stored procedure failed System.out.println(procName + " failed with SQLCODE " + outErrorCode); }
ストアード・プロシージャー・アプリケーションが適正に実行されない場合には、以下のことを確認してください。
たとえば、OS/2 環境では、 FENCED ストアード・プロシージャーの動的リンク・ライブラリーは、データベース・サーバー上の instance_name\function ディレクトリーにあります。
たとえば、データベース・マネージャーは、 Windows 32 ビット オペレーティング・システムのライブラリー myfunc.dll に含まれているストアード・プロシージャー myfunc を、DB2DARI 関数として実行します。この場合、そのストアード・プロシージャーに関連付けられた CREATE PROCEDURE ステートメントにどんな値が指定されていてもかまいません。
注: | Java ストアード・プロシージャーのデバッグの詳細については、 Java でのストアード・プロシージャーのデバッグを参照してください。 |
コンパイラーに付属するデバッガーを使用して、他のアプリケーションと同じようにローカルな FENCED ストアード・プロシージャーをデバッグできます。提供されるデバッガーの使用法については、コンパイラーの資料をご覧ください。
たとえば、Windows NT 上の Visual Studio(TM) に付属するデバッガーを使用するには、以下のステップを実行してください。
ステップ 1. | DB2_STPROC_ALLOW_LOCAL_FENCED レジストリー変数を true に設定する。 |
ステップ 2. | -Zi および -Od フラグを指定して、ストアード・プロシージャー DLL のソース・ファイルをコンパイルし、 -DEBUG オプションを使ってその DLL をリンクする。 |
ステップ 3. | 作成された DLL をサーバーの instance_name \function ディレクトリーに複写する。 |
ステップ 4. | Visual Studio デバッガーを使って、サーバー上のクライアント・アプリケーションを呼び出す。クライアント・アプリケーション outcli.exe の場合は、次のコマンドを入力します。 msdev spclient.exe |
ステップ 5. | 「Visual Studio デバッガー (Visual Studio debugger)」ウィンドウがオープンしたら、 「プロジェクト (Project)」-->「設定 (Settings)」を選択する。 |
ステップ 6. | 「デバッグ (Debug)」タブをクリックする。 |
ステップ 7. | 「カテゴリ (Category)」の矢印をクリックして、「追加の DLL (Additional DLLs)」を選択する。 |
ステップ 8. | 「新規 (New)」ボタンをクリックして、新規モジュールを作成する。 |
ステップ 9. | 「ブラウズ (Browse)」ボタンをクリックして、「ブラウズ (Browse)」ウィンドウをオープンする。 |
ステップ 10. | モジュール spserver.dll を選択して、「OK」をクリックし、「設定 (Settings)」ウィンドウをクローズする。 |
ステップ 11. | ストアード・プロシージャーのソース・ファイルをオープンして、ブレークポイントを設定する。 |
ステップ 12. | 「実行 (Go)」ボタンをクリックする。ストアード・プロシージャーが呼び出されると、Visual Studio デバッガーは停止します。 |
ステップ 13. | この時点で、Visual Studio デバッガーを使って、ストアード・プロシージャーをデバッグすることができます。
|
Visual Studio デバッガーの使用に関する詳細については、 Visual Studio の製品資料を参照してください。