ODBC 3.8 이전에는 애플리케이션이 바인딩된 출력 버퍼를 사용하여 쿼리의 출력 매개 변수만 검색할 수 있습니다. 그러나 매개 변수 값의 크기가 매우 큰 경우(예: 큰 이미지) 매우 큰 버퍼를 할당하기는 어렵습니다. ODBC 3.8에서는 출력 매개 변수를 파트에서 검색하는 새로운 방법이 도입되었습니다. 이제 애플리케이션은 작은 버퍼가 있는 SQLGetData 를 여러 번 호출하여 큰 매개 변수 값을 검색할 수 있습니다. 이는 큰 열 데이터를 검색하는 것과 유사합니다.
출력 매개 변수 또는 입력/출력 매개 변수를 부분적으로 검색하도록 바인딩하려면, SQLBindParameter을(를) 호출하고 InputOutputType 인수를 SQL_PARAM_OUTPUT_STREAM 또는 SQL_PARAM_INPUT_OUTPUT_STREAM으로 설정합니다. 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 기능을 사용하도록 설정하는 방법에 대한 자세한 내용은 호환성 매트릭스를 참조하세요.
사용 예제
예를 들어 두 매개 변수가 모두 SQL_PARAM_OUTPUT_STREAM 바인딩되고 저장 프로시저가 결과 집합을 반환하지 않는 저장 프로시저 {CALL sp_f(?,?)}을 실행하는 것이 좋습니다(이 항목의 뒷부분에서는 더 복잡한 시나리오를 찾을 수 있음).
각 매개 변수에 대해 InputOutputType이 SQL_PARAM_OUTPUT_STREAM 설정되고 ParameterValuePtr가 토큰으로 설정된 SQLBindParameter를 호출합니다(예: 매개 변수 번호, 데이터에 대한 포인터 또는 애플리케이션이 입력 매개 변수를 바인딩하는 데 사용하는 구조에 대한 포인터). 이 예제에서는 매개 변수 서수를 토큰으로 사용합니다.
SQLExecDirect 또는 SQLExecute를 사용하여 쿼리를 실행합니다. 검색에 사용할 수 있는 스트리밍 출력 매개 변수가 있음을 나타내는 SQL_PARAM_DATA_AVAILABLE 반환됩니다.
SQLParamData를 호출하여 검색에 사용할 수 있는 매개 변수를 가져옵니다. SQLParamData 는 SQLBindParameter (1단계)에 설정된 사용 가능한 첫 번째 매개 변수의 토큰을 사용하여 SQL_PARAM_DATA_AVAILABLE 반환합니다. 토큰은 ValuePtrPtr 이 가리키는 버퍼에 반환됩니다.
SQLGetData를 호출하여 Col_or_Param_Num을 매개 변수 인덱스로 설정하고 첫 번째 사용 가능한 매개 변수의 데이터를 검색합니다. SQLGetData가 SQL_SUCCESS_WITH_INFO 및 SQLState 01004(잘린 데이터)를 반환하고 형식이 클라이언트와 서버 모두에서 가변 길이인 경우 사용 가능한 첫 번째 매개 변수에서 검색할 데이터가 더 많습니다. SQLGetData를 계속 호출하면 다른 SQLState와 함께 SQL_SUCCESS 또는 SQL_SUCCESS_WITH_INFO가 반환될 때까지 가능합니다.
3단계와 4단계를 반복하여 현재 매개 변수를 검색합니다.
SQLParamData를 다시 호출합니다. SQL_PARAM_DATA_AVAILABLE 제외한 모든 항목을 반환하는 경우 더 이상 검색할 스트리밍된 매개 변수 데이터가 없으며 반환 코드는 실행되는 다음 문의 반환 코드가 됩니다.
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를 호출하는 경우 나머지 값과 나머지 매개 변수는 모두 삭제되고 애플리케이션은 다음 매개 변수 집합을 계속 처리할 수 있습니다.
애플리케이션은 SQLBindParameter 및 SQLGetData 모두에서 C 데이터 형식을 지정할 수 있습니다. SQLGetData로 지정된 C 데이터 형식은 SQLBindParameter에 지정된 C 데이터 형식을 재정의합니다. 단, SQLGetData에 지정된 C 데이터 형식이 SQL_APD_TYPE이 아닌 한.
출력 매개 변수의 데이터 형식이 BLOB 형식인 경우 스트리밍된 출력 매개 변수가 더 유용하지만 이 기능은 모든 데이터 형식과 함께 사용할 수도 있습니다. 스트리밍된 출력 매개 변수에서 지원하는 데이터 형식은 드라이버에 지정됩니다.
처리할 SQL_PARAM_INPUT_OUTPUT_STREAM 매개 변수가 있는 경우 SQLExecute 또는 SQLExecDirect 는 먼저 SQL_NEED_DATA 반환합니다. 애플리케이션은 SQLParamData 및 SQLPutData 를 호출하여 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를 호출하여 스트리밍된 출력 매개 변수와 별도로 처리됩니다. 스트리밍된 출력 매개 변수를 처리하기 전에 경고 및 결과 집합을 처리합니다.
다음 표에서는 서버에 전송된 단일 명령의 다양한 시나리오와 애플리케이션의 작동 방식에 대해 설명합니다.
| Scenario | SQLExecute 또는 SQLExecDirect에서 값 반환 | 다음에 수행할 일 |
|---|---|---|
| 데이터에는 스트리밍된 출력 매개 변수만 포함됩니다. | SQL_PARAM_DATA_AVAILABLE | SQLParamData 및 SQLGetData를 사용하여 스트리밍된 출력 매개 변수를 검색합니다. |
| 데이터에는 결과 집합 및 스트리밍된 출력 매개 변수가 포함됩니다. | SQL_SUCCESS |
SQLBindCol 및 SQLGetData를 사용하여 결과 집합을 검색합니다. SQLMoreResults를 호출하여 스트리밍된 출력 매개 변수 처리를 시작합니다. SQL_PARAM_DATA_AVAILABLE 반환해야 합니다. SQLParamData 및 SQLGetData를 사용하여 스트리밍된 출력 매개 변수를 검색합니다. |
| 데이터에는 경고 메시지 및 스트리밍된 출력 매개 변수가 포함됩니다. | SQL_SUCCESS_WITH_INFO (성공하지만 정보가 있습니다) |
SQLGetDiagRec 및 SQLGetDiagField를 사용하여 경고 메시지를 처리합니다. SQLMoreResults를 호출하여 스트리밍된 출력 매개 변수 처리를 시작합니다. SQL_PARAM_DATA_AVAILABLE 반환해야 합니다. SQLParamData 및 SQLGetData를 사용하여 스트리밍된 출력 매개 변수를 검색합니다. |
| 데이터에는 경고 메시지, 결과 집합 및 스트리밍된 출력 매개 변수가 포함됩니다. | SQL_SUCCESS_WITH_INFO |
SQLGetDiagRec 및 SQLGetDiagField를 사용하여 경고 메시지를 처리합니다. 그런 다음 , SQLMoreResults를 호출하여 결과 집합 처리를 시작합니다. SQLBindCol 및 SQLGetData를 사용하여 결과 집합을 검색합니다. SQLMoreResults를 호출하여 스트리밍된 출력 매개 변수 처리를 시작합니다. SQLMoreResults는 SQL_PARAM_DATA_AVAILABLE 반환해야 합니다. SQLParamData 및 SQLGetData를 사용하여 스트리밍된 출력 매개 변수를 검색합니다. |
| DAE 입력 매개 변수를 사용하여 쿼리(예: DAE(스트리밍된 입력/출력) 매개 변수) | SQL 필요_데이터 |
SQLParamData 및 SQLPutData를 호출하여 DAE 입력 매개 변수 데이터를 보냅니다. 모든 DAE 입력 매개 변수가 처리되면 SQLParamData 는 SQLExecute 및 SQLExecDirect 에서 반환할 수 있는 모든 반환 코드를 반환할 수 있습니다. 그런 다음 이 테이블의 사례를 적용할 수 있습니다. 반환 코드가 SQL_PARAM_DATA_AVAILABLE 경우 스트리밍된 출력 매개 변수를 사용할 수 있습니다. 애플리케이션은 이 테이블의 첫 번째 행에 설명된 대로 스트리밍된 출력 매개 변수에 대한 토큰을 검색하기 위해 SQLParamData 를 다시 호출해야 합니다. 반환 코드가 SQL_SUCCESS 경우 처리할 결과 집합이 있거나 처리가 완료됩니다. 반환 코드가 SQL_SUCCESS_WITH_INFO 경우 처리할 경고 메시지가 있습니다. |
SQLExecute, SQLExecDirect 또는 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 (옵션 = 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를 사용하여 데이터를 파트 단위로 가져올 수 있습니다.
// 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;
}