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 기능을 사용하도록 설정하는 방법에 대한 자세한 내용은 호환성 매트릭스를 참조 하세요.
사용 예
예를 들어 두 매개 변수가 모두 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이 가리키는 버퍼에 반환됩니다.
인수 Col_or_Param_Num 매개 변수 서수로 설정된 SQLGetData를 호출하여 사용 가능한 첫 번째 매개 변수의 데이터를 검색합니다. SQLGetData가 SQL_SUCCESS_WITH_INFO 및 SQLState 01004(잘린 데이터)를 반환하고 형식이 클라이언트와 서버 모두에서 가변 길이인 경우 사용 가능한 첫 번째 매개 변수에서 검색할 데이터가 더 많습니다. 다른 SQLState를 사용하여 SQL_SUCCESS 반환하거나 SQL_SUCCESS_WITH_INFO 때까지 SQLGetData를 계속 호출할 수 있습니다.
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를 호출하는 경우 값의 다시 기본der가 해제되고카드 애플리케이션이 다음 매개 변수를 처리할 수 있습니다.
모든 스트리밍 출력 매개 변수가 처리되기 전에 애플리케이션이 SQLMoreResults를 호출하는 경우(SQLParamData는 여전히 SQL_PARAM_DATA_AVAILABLE 반환함) 모든 다시 기본 매개 변수가 해제됩니다카드. 마찬가지로 SQLGetData에서 모든 매개 변수 값을 읽기 전에 애플리케이션이 SQLMoreResults를 호출하는 경우 값의 re기본der 및 모든 다시 기본 매개 변수는 해제되고 카드 애플리케이션은 다음 매개 변수 집합을 계속 처리할 수 있습니다.
애플리케이션은 SQLBindParameter 및 SQLGetData 모두에서 C 데이터 형식을 지정할 수 있습니다. SQLGetData로 지정된 C 데이터 형식은 SQLGetData에 지정된 C 데이터 형식이 SQL_APD_TYPE 않는 한 SQLBindParameter에 지정된 C 데이터 형식을 재정의합니다.
출력 매개 변수의 데이터 형식이 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를 호출 하여 스트리밍된 출력 매개 변수와 별도로 처리됩니다. 스트리밍된 출력 매개 변수를 처리하기 전에 경고 및 결과 집합을 처리합니다.
다음 표에서는 서버에 전송된 단일 명령의 다양한 시나리오와 애플리케이션의 작동 방식에 대해 설명합니다.
시나리오 | 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 NEED_DATA | 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
SQLGet커넥트Attr / 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;
}