次の方法で共有


SQLGetData を使用した出力パラメーターの取得

ODBC 3.8 より前のバージョンでは、アプリケーションはバインドされた出力バッファーを持つクエリの出力パラメーターのみを取得できました。 ただし、パラメーター値のサイズが非常に大きい場合 (たとえば、大きな画像) では、非常に大きなバッファーを割り当てることは困難です。 ODBC 3.8 では、パーツ内の出力パラメーターを取得する新しい方法が導入されています。 アプリケーションは、小さなバッファーを使用して SQLGetData を複数回呼び出して、大きなパラメーター値を取得できるようになりました。 これは、大きな列データを取得するのと似ています。

部分で取得する出力パラメーターまたは入力/出力パラメーターをバインドするには、InputOutputType 引数をSQL_PARAM_OUTPUT_STREAMまたはSQL_PARAM_INPUT_OUTPUT_STREAMに設定して SQLBindParameter を呼び出します。 SQL_PARAM_INPUT_OUTPUT_STREAMでは、アプリケーションは SQLPutData を使用してパラメーターにデータを入力し、 SQLGetData を 使用して出力パラメーターを取得できます。 入力データは、事前に割り当てられたバッファーにバインドするのではなく、 SQLPutData を使用して、実行時データ (DAE) 形式である必要があります。

この機能は、ODBC 3.8 アプリケーションまたは再コンパイルされた ODBC 3.x および ODBC 2.x アプリケーションで使用できます。これらのアプリケーションには、 SQLGetData と ODBC 3.8 ドライバー マネージャーを使用した出力パラメーターの取得をサポートする ODBC 3.8 ドライバーが必要です。 古いアプリケーションで新しい ODBC 機能を使用できるようにする方法については、「 互換性マトリックス」を参照してください。

使用例

たとえば、ストアド プロシージャ {CALL sp_f(?,?)} を実行すると、両方のパラメーターがSQL_PARAM_OUTPUT_STREAMとしてバインドされ、ストアド プロシージャは結果セットを返しません (このトピックの後半では、より複雑なシナリオが見つかります)。

  1. 各パラメーターに対して、InputOutputType を SQL_PARAM_OUTPUT_STREAM に設定し、ParameterValuePtr をトークンに設定して SQLBindParameter を呼び出します (パラメーター番号、データへのポインター、入力パラメーターのバインドにアプリケーションが使用する構造体へのポインターなど)。 この例では、パラメーターの序数をトークンとして使用します。

  2. SQLExecDirect または SQLExecute を使用してクエリ実行します。 SQL_PARAM_DATA_AVAILABLEが返され、取得に使用できるストリーム出力パラメーターがあることを示します。

  3. SQLParamData を呼び出して、取得可能なパラメーターを取得します。 SQLParamData は、 SQLBindParameter で設定されている最初の使用可能なパラメーターのトークンを使用してSQL_PARAM_DATA_AVAILABLEを返します (手順 1)。 トークンは、 ValuePtrPtr が指すバッファーで返されます。

  4. 引数 Col_or_Param_Num をパラメーター序数に設定して SQLGetData を呼び出して、使用可能な最初のパラメーターのデータを取得します。 SQLGetData が SQL_SUCCESS_WITH_INFO および SQLState 01004 (データが切り捨てられた) を返し、その型がクライアントとサーバーの両方で可変長である場合は、最初に使用可能なパラメーターから取得するデータが増えます。 SQLGetData は、別の SQLState でSQL_SUCCESSまたはSQL_SUCCESS_WITH_INFOを返すまで引き続き呼び出すことができます。

  5. 手順 3 と手順 4 を繰り返して、現在のパラメーターを取得します。

  6. SQLParamData をもう一度呼び出します。 SQL_PARAM_DATA_AVAILABLEを除く何かを返す場合、取得するストリーミング パラメーター データはこれ以上なく、戻りコードは実行される次のステートメントのリターン コードになります。

  7. SQLMoreResults を呼び出して、SQL_NO_DATAを返すまで、次のパラメーター セットを処理します。 ステートメント属性SQL_ATTR_PARAMSET_SIZEが 1 に設定されている場合、SQLMoreResults は、この例のSQL_NO_DATAを返します。 それ以外の場合、 SQLMoreResults はSQL_PARAM_DATA_AVAILABLEを返し、次に取得するパラメーターのセットで使用できるストリーム出力パラメーターがあることを示します。

DAE 入力パラメーターと同様に、SQLBindParameter (手順 1) の引数 ParameterValuePtr で使用されるトークンは、パラメーターの序数と、必要に応じてより多くのアプリケーション固有の情報を含むアプリケーション データ構造を指すポインターにすることができます。

返されるストリーム出力または入力/出力パラメーターの順序はドライバー固有であり、クエリで指定された順序と常に同じとは限りません。

手順 4 でアプリケーションが SQLGetData を呼び出さない場合、パラメーター値は破棄されます。 同様に、すべてのパラメーター値が SQLGetData によって読み取られた前にアプリケーションが SQLParamData を呼び出した場合、値の残りの部分は破棄され、アプリケーションは次のパラメーターを処理できます。

すべてのストリーム出力パラメーターが処理される前にアプリケーションが SQLMoreResults を呼び出した場合 (SQLParamData は引き続きSQL_PARAM_DATA_AVAILABLEを返します)、残りのパラメーターはすべて破棄されます。 同様に、すべてのパラメーター値が SQLGetData によって読み取られた前にアプリケーションが SQLMoreResults を呼び出した場合、残りの値と残りのすべてのパラメーターは破棄され、アプリケーションは次のパラメーター セットの処理を続行できます。

アプリケーションでは、 SQLBindParameterSQLGetData の両方で C データ型を指定できることに注意してください。 SQLGetData で指定された C データ型は、SQLGetData で指定された C データ型がSQL_APD_TYPEされていない限り、SQLBindParameter で指定された C データ型をオーバーライドします。

ストリーム出力パラメーターは、出力パラメーターのデータ型が BLOB 型の場合に便利ですが、この機能は任意のデータ型でも使用できます。 ストリーム出力パラメーターでサポートされるデータ型は、ドライバーで指定されます。

処理するパラメーター SQL_PARAM_INPUT_OUTPUT_STREAMがある場合、 SQLExecute または SQLExecDirect は最初にSQL_NEED_DATA返します。 アプリケーションは 、SQLParamDataSQLPutData を呼び出して DAE パラメーター データを送信できます。 すべての DAE 入力パラメーターが処理されると、 SQLParamData はストリーム出力パラメーターが使用可能であることを示すSQL_PARAM_DATA_AVAILABLEを返します。

ストリーム出力パラメーターとバインドされた出力パラメーターが処理される場合、ドライバーは出力パラメーターの処理順序を決定します。 そのため、出力パラメーターがバッファーにバインドされている場合 ( SQLBindParameter パラメーター InputOutputType が SQL_PARAM_INPUT_OUTPUT または SQL_PARAM_OUTPUT に設定されている場合)、 SQLParamData がSQL_SUCCESSまたはSQL_SUCCESS_WITH_INFOを返すまで、バッファーに値が設定されない可能性があります。 アプリケーションは、 SQLParamData がすべてのストリーム出力パラメーターの処理後にSQL_SUCCESSまたはSQL_SUCCESS_WITH_INFOを返した後にのみ、バインドされたバッファーを読み取る必要があります。

データ ソースは、ストリーム出力パラメーターに加えて、警告と結果セットを返すことができます。 一般に、警告と結果セットは、 SQLMoreResults を呼び出すことによって、ストリーム出力パラメーターとは別に処理されます。 ストリーム出力パラメーターを処理する前に、警告と結果セットを処理します。

次の表では、サーバーに送信される 1 つのコマンドのさまざまなシナリオと、アプリケーションの動作方法について説明します。

Scenario SQLExecute または SQLExecDirect からの戻り値 次の操作
ストリーミングされた出力パラメーターのみを含むデータ Not necessary as it adheres to the convention of keeping known technical constants and parameters in their original form for clarity and accuracy in the technical domain. SQLParamDataSQLGetData を使用して、ストリーム出力パラメーターを取得します。
データには、結果セットとストリーム出力パラメーターが含まれます SQL_SUCCESS SQLBindColSQLGetData を使用して結果セットを取得します。

SQLMoreResults を呼び出して、ストリーム出力パラメーターの処理を開始します。 SQL_PARAM_DATA_AVAILABLEを返す必要があります。

SQLParamDataSQLGetData を使用して、ストリーム出力パラメーターを取得します。
データには警告メッセージとストリーム出力パラメーターが含まれます SQL_SUCCESS_WITH_INFO 警告メッセージを処理するには、 SQLGetDiagRecSQLGetDiagField を使用します。

SQLMoreResults を呼び出して、ストリーム出力パラメーターの処理を開始します。 SQL_PARAM_DATA_AVAILABLEを返す必要があります。

SQLParamDataSQLGetData を使用して、ストリーム出力パラメーターを取得します。
データには、警告メッセージ、結果セット、およびストリーム出力パラメーターが含まれます SQL_SUCCESS_WITH_INFO 警告メッセージを処理するには、 SQLGetDiagRecSQLGetDiagField を使用します。 次に 、SQLMoreResults を呼び出して、結果セットの処理を開始します。

SQLBindColSQLGetData を使用して結果セットを取得します。

SQLMoreResults を呼び出して、ストリーム出力パラメーターの処理を開始します。 SQLMoreResults は SQL_PARAM_DATA_AVAILABLEを返す必要があります。

SQLParamDataSQLGetData を使用して、ストリーム出力パラメーターを取得します。
DAE 入力パラメーターを使用したクエリ (ストリーム入力/出力 (DAE) パラメーターなど) SQL データが必要です SQLParamDataSQLPutData を呼び出して、DAE 入力パラメーター データを送信します。

すべての DAE 入力パラメーターが処理されると、SQLParamDataSQLExecute と SQLExecDirect が返すことができるすべてのリターン コードを返すことができます。 その後、この表のケースを適用できます。

戻りコードがSQL_PARAM_DATA_AVAILABLEされている場合は、ストリーム出力パラメーターを使用できます。 この表の最初の行で説明されているように、アプリケーションは SQLParamData をもう一度呼び出して、ストリーム出力パラメーターのトークンを取得する必要があります。

戻りコードがSQL_SUCCESS場合は、処理する結果セットがあるか、処理が完了しています。

戻りコードがSQL_SUCCESS_WITH_INFOされている場合は、処理する警告メッセージがあります。

SQLExecuteSQLExecDirect、または SQLMoreResults がSQL_PARAM_DATA_AVAILABLEを返した後、アプリケーションが次の一覧にない関数を呼び出すと、関数シーケンス エラーが発生します。

  • SQLAllocHandle / SQLAllocHandleStd

  • SQLDataSources / SQLDrivers

  • SQLGetInfo / SQLGetFunctions

  • SQLGetConnectAttr / SQLGetEnvAttr / SQLGetDescField / SQLGetDescRec

  • SQLNumParams

  • SQLDescribeParam

  • SQLNativeSql

  • SQLParamData

  • SQLMoreResults

  • SQLGetDiagField / SQLGetDiagRec

  • SQLCancel

  • SQLCancelHandle (ステートメント ハンドル付き)

  • SQLFreeStmt (Option = SQL_CLOSE、SQL_DROP、またはSQL_UNBIND)

  • SQLCloseCursor

  • SQLDisconnect

  • SQLFreeHandle (HandleType = SQL_HANDLE_STMT)

  • SQLGetStmtAttr

アプリケーションでは引き続き SQLSetDescField または SQLSetDescRec を使用してバインディング情報を設定できます。 フィールド マッピングは変更されません。 ただし、記述子内のフィールドは新しい値を返す場合があります。 たとえば、SQL_DESC_PARAMETER_TYPEはSQL_PARAM_INPUT_OUTPUT_STREAMまたはSQL_PARAM_OUTPUT_STREAMを返します。

使用シナリオ: 結果セットからパーツ内のイメージを取得する

SQLGetData を使用すると、ストアド プロシージャがイメージに関する 1 行のメタデータを含む結果セットを返し、イメージが大きな出力パラメーターで返される場合に、一部のデータを取得できます。

// CREATE PROCEDURE SP_TestOutputPara  
//      @ID_of_picture   as int,  
//      @Picture         as varbinary(max) out  
// AS  
//     output the image data through streamed output parameter  
// GO  
BOOL displayPicture(SQLUINTEGER idOfPicture, SQLHSTMT hstmt) {  
   SQLLEN      lengthOfPicture;    // The actual length of the picture.  
   BYTE        smallBuffer[100];   // A very small buffer.  
   SQLRETURN   retcode, retcode2;  
  
   // Bind the first parameter (input parameter)  
   SQLBindParameter(  
         hstmt,  
         1,                         // The first parameter.   
         SQL_PARAM_INPUT,           // Input parameter: The ID_of_picture.  
         SQL_C_ULONG,               // The C Data Type.  
         SQL_INTEGER,               // The SQL Data Type.  
         0,                         // ColumnSize is ignored for integer.  
         0,                         // DecimalDigits is ignored for integer.  
         &idOfPicture,              // The Address of the buffer for the input parameter.  
         0,                         // BufferLength is ignored for integer.  
         NULL);                     // This is ignored for integer.  
  
   // Bind the streamed output parameter.  
   SQLBindParameter(  
         hstmt,   
         2,                         // The second parameter.  
         SQL_PARAM_OUTPUT_STREAM,   // A streamed output parameter.   
         SQL_C_BINARY,              // The C Data Type.    
         SQL_VARBINARY,             // The SQL Data Type.  
         0,                         // ColumnSize: The maximum size of varbinary(max).  
         0,                         // DecimalDigits is ignored for binary type.  
         (SQLPOINTER)2,             // ParameterValuePtr: An application-defined  
                                    // token (this will be returned from SQLParamData).  
                                    // In this example, we used the ordinal   
                                    // of the parameter.  
         0,                         // BufferLength is ignored for streamed output parameters.  
         &lengthOfPicture);         // StrLen_or_IndPtr: The status variable returned.   
  
   retcode = SQLPrepare(hstmt, L"{call SP_TestOutputPara(?, ?)}", SQL_NTS);  
   if ( retcode == SQL_ERROR )  
      return FALSE;  
  
   retcode = SQLExecute(hstmt);  
   if ( retcode == SQL_ERROR )  
      return FALSE;  
  
   // Assume that the retrieved picture exists.  Use SQLBindCol or SQLGetData to retrieve the result-set.  
  
   // Process the result set and move to the streamed output parameters.  
   retcode = SQLMoreResults( hstmt );  
  
   // SQLGetData retrieves and displays the picture in parts.  
   // The streamed output parameter is available.  
   while (retcode == SQL_PARAM_DATA_AVAILABLE) {  
      SQLPOINTER token;   // Output by SQLParamData.  
      SQLLEN cbLeft;      // #bytes remained  
      retcode = SQLParamData(hstmt, &token);   // returned token is 2 (according to the binding)  
      if ( retcode == SQL_PARAM_DATA_AVAILABLE ) {  
         // A do-while loop retrieves the picture in parts.  
         do {  
            retcode2 = SQLGetData(   
               hstmt,   
               (UWORD) token,          // the value of the token is the ordinal.   
               SQL_C_BINARY,           // The C-type.  
               smallBuffer,            // A small buffer.   
               sizeof(smallBuffer),    // The size of the buffer.  
               &cbLeft);               // How much data we can get.  
         }  
         while ( retcode2 == SQL_SUCCESS_WITH_INFO );  
      }  
   }  
  
   return TRUE;  
}  

使用シナリオ: ストリーミング入力/出力パラメーターとしてラージ オブジェクトを送受信する

SQLGetData を使用すると、ストアド プロシージャが大きなオブジェクトを入力/出力パラメーターとして渡し、データベースとの間で値をストリーミングするときに、データを一部で取得および送信できます。 すべてのデータをメモリに格納する必要はありません。

// CREATE PROCEDURE SP_TestInOut  
//       @picture as varbinary(max) out  
// AS  
//    output the image data through output parameter   
// go  
  
BOOL displaySimilarPicture(BYTE* image, ULONG lengthOfImage, SQLHSTMT hstmt) {  
   BYTE smallBuffer[100];   // A very small buffer.  
   SQLRETURN retcode, retcode2;  
   SQLLEN statusOfPicture;  
  
   // First bind the parameters, before preparing the statement that binds the output streamed parameter.  
   SQLBindParameter(  
      hstmt,   
      1,                                 // The first parameter.  
      SQL_PARAM_INPUT_OUTPUT_STREAM,     // I/O-streamed parameter: The Picture.  
      SQL_C_BINARY,                      // The C Data Type.  
      SQL_VARBINARY,                     // The SQL Data Type.  
      0,                                 // ColumnSize: The maximum size of varbinary(max).  
      0,                                 // DecimalDigits is ignored.   
      (SQLPOINTER)1,                     // An application defined token.   
      0,                                 // BufferLength is ignored for streamed I/O parameters.  
      &statusOfPicture);                 // The status variable.  
  
   statusOfPicture = SQL_DATA_AT_EXEC;   // Input data in parts (DAE parameter at input).  
  
   retcode = SQLPrepare(hstmt, L"{call SP_TestInOut(?) }", SQL_NTS);  
   if ( retcode == SQL_ERROR )  
      return FALSE;  
  
   // Execute the statement.  
   retcode = SQLExecute(hstmt);  
   if ( retcode == SQL_ERROR )  
      return FALSE;  
  
   if ( retcode == SQL_NEED_DATA ) {  
      // Use SQLParamData to loop through DAE input parameters.  For  
      // each, use SQLPutData to send the data to database in parts.  
  
      // This example uses an I/O parameter with streamed output.  
      // Therefore, the last call to SQLParamData should return  
      // SQL_PARAM_DATA_AVAILABLE to indicate the end of the input phrase   
      // and report that a streamed output parameter is available.  
  
      // Assume retcode is set to the return value of the last call to  
      // SQLParamData, which is equal to SQL_PARAM_DATA_AVAILABLE.  
   }  
  
   // Start processing the streamed output parameters.  
   while ( retcode == SQL_PARAM_DATA_AVAILABLE ) {  
      SQLPOINTER token;   // Output by SQLParamData.  
      SQLLEN cbLeft;     // #bytes remained  
      retcode = SQLParamData(hstmt, &token);  
      if ( retcode == SQL_PARAM_DATA_AVAILABLE ) {  
         do {  
            retcode2 = SQLGetData(   
               hstmt,   
               (UWORD) token,          // the value of the token is the ordinal.   
               SQL_C_BINARY,           // The C-type.  
               smallBuffer,            // A small buffer.   
               sizeof(smallBuffer),    // The size of the buffer.  
               &cbLeft);               // How much data we can get.  
         }  
         while ( retcode2 == SQL_SUCCESS_WITH_INFO );  
      }  
   }   
  
   return TRUE;  
}  

こちらもご覧ください

ステートメント パラメーター