Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Vóór ODBC 3.8 kon een toepassing alleen de uitvoerparameters van een query ophalen met een afhankelijke uitvoerbuffer. Het is echter moeilijk om een zeer grote buffer toe te wijzen wanneer de grootte van de parameterwaarde erg groot is (bijvoorbeeld een grote afbeelding). ODBC 3.8 introduceert een nieuwe manier om uitvoerparameters op te halen in onderdelen. Een toepassing kan nu SQLGetData meerdere keren aanroepen met een kleine buffer om een grote parameterwaarde op te halen. Dit is vergelijkbaar met het ophalen van grote kolomgegevens.
Als u een uitvoerparameter of invoer-/uitvoerparameter wilt binden die in onderdelen moet worden opgehaald, roept u SQLBindParameter aan met het argument InputOutputType ingesteld op SQL_PARAM_OUTPUT_STREAM of SQL_PARAM_INPUT_OUTPUT_STREAM. Met SQL_PARAM_INPUT_OUTPUT_STREAM kan een toepassing SQLPutData gebruiken om gegevens in de parameter in te voeren en vervolgens SQLGetData gebruiken om de uitvoerparameter op te halen. De invoergegevens moeten zich in het DAE-formulier (data-at-execution) bevinden, waarbij SQLPutData wordt gebruikt in plaats van deze te binden aan een vooraf toegewezen buffer.
Deze functie kan worden gebruikt door ODBC 3.8-toepassingen of opnieuw gecompileerde ODBC 3.x- en ODBC 2.x-toepassingen. Deze toepassingen moeten een ODBC 3.8-stuurprogramma hebben dat ondersteuning biedt voor het ophalen van uitvoerparameters met behulp van SQLGetData en ODBC 3.8 Driver Manager. Zie Compatibiliteitsmatrix voor informatie over het inschakelen van een oudere toepassing voor het gebruik van nieuwe ODBC-functies.
Gebruiksvoorbeeld
U kunt bijvoorbeeld een opgeslagen procedure {CALL sp_f(?,?)} uitvoeren, waarbij beide parameters als SQL_PARAM_OUTPUT_STREAM zijn gebonden en de opgeslagen procedure geen resultatenset retourneert (verderop in dit onderwerp vindt u een complexer scenario):
Roep voor elke parameter SQLBindParameter aan met InputOutputType ingesteld op SQL_PARAM_OUTPUT_STREAM en ParameterValuePtr ingesteld op een token, zoals een parameternummer, een aanwijzer naar gegevens of een aanwijzer naar een structuur die de toepassing gebruikt om invoerparameters te binden. In dit voorbeeld wordt de parameter ordinaal gebruikt als token.
Voer de query uit met SQLExecDirect of SQLExecute. SQL_PARAM_DATA_AVAILABLE wordt geretourneerd, waarmee wordt aangegeven dat er gestreamde uitvoerparameters beschikbaar zijn voor het ophalen.
Roep SQLParamData aan om de parameter op te halen die beschikbaar is voor het ophalen. SQLParamData retourneert SQL_PARAM_DATA_AVAILABLE met het token van de eerste beschikbare parameter, die is ingesteld in SQLBindParameter (stap 1). Het token wordt geretourneerd in de buffer waarnaar de ValuePtrPtr verwijst.
Roep SQLGetData aan met het argument Col_or_Param_Num ingesteld op de parameterordinaal om de gegevens van de eerste beschikbare parameter op te halen. Als SQLGetData SQL_SUCCESS_WITH_INFO en SQLState 01004 (gegevens afgekapt) retourneert en het type variabele lengte heeft op zowel de client als de server, zijn er meer gegevens om op te halen uit de eerste beschikbare parameter. U kunt SQLGetData blijven aanroepen totdat deze SQL_SUCCESS of SQL_SUCCESS_WITH_INFO retourneert met een andere SQLState.
Herhaal stap 3 en stap 4 om de huidige parameter op te halen.
Roep SQLParamData opnieuw aan. Als er iets wordt geretourneerd behalve SQL_PARAM_DATA_AVAILABLE, zijn er geen gestreamde parametergegevens meer die moeten worden opgehaald en is de retourcode de retourcode van de volgende instructie die wordt uitgevoerd.
Roep SQLMoreResults aan om de volgende set parameters te verwerken totdat deze SQL_NO_DATA retourneert. SQLMoreResults retourneert SQL_NO_DATA in dit voorbeeld als het instructiekenmerk SQL_ATTR_PARAMSET_SIZE is ingesteld op 1. Anders retourneert SQLMoreResults SQL_PARAM_DATA_AVAILABLE om aan te geven dat er gestreamde uitvoerparameters beschikbaar zijn voor de volgende set parameters die moeten worden opgehaald.
Net als bij een DAE-invoerparameter kan het token dat wordt gebruikt in het argument ParameterValuePtr in SQLBindParameter (stap 1) een aanwijzer zijn die verwijst naar een gegevensstructuur van een toepassing, die indien nodig de rangschikker van de parameter en meer toepassingsspecifieke informatie bevat.
De volgorde van de geretourneerde gestreamde uitvoer- of invoer-/uitvoerparameters is stuurprogrammaspecifiek en is mogelijk niet altijd hetzelfde als de volgorde die is opgegeven in de query.
Als de toepassing SQLGetData niet aanroept in stap 4, wordt de parameterwaarde verwijderd. Als de toepassing SQLParamData aanroept voordat alle parameterwaarden zijn gelezen door SQLGetData, wordt de rest van de waarde verwijderd en kan de toepassing de volgende parameter verwerken.
Als de toepassing SQLMoreResults aanroept voordat alle gestreamde uitvoerparameters worden verwerkt (SQLParamData retourneert nog steeds SQL_PARAM_DATA_AVAILABLE), worden alle resterende parameters verwijderd. Als de toepassing SQLMoreResults aanroept voordat alle parameterwaarden door SQLGetData zijn gelezen, worden de rest van de waarde en alle resterende parameters verwijderd en kan de toepassing de volgende parameterset blijven verwerken.
Houd er rekening mee dat een toepassing het C-gegevenstype kan opgeven in zowel SQLBindParameter als SQLGetData. Het C-gegevenstype dat is opgegeven met SQLGetData overschrijft het C-gegevenstype dat is opgegeven in SQLBindParameter, tenzij het C-gegevenstype dat is opgegeven in SQLGetData wordt SQL_APD_TYPE.
Hoewel een gestreamde uitvoerparameter nuttiger is wanneer het gegevenstype van de uitvoerparameter van het type BLOB is, kan deze functionaliteit ook worden gebruikt met elk gegevenstype. De gegevenstypen die worden ondersteund door gestreamde uitvoerparameters, worden opgegeven in het stuurprogramma.
Als er SQL_PARAM_INPUT_OUTPUT_STREAM parameters moeten worden verwerkt, retourneert SQLExecute of SQLExecDirect eerst SQL_NEED_DATA. Een toepassing kan SQLParamData en SQLPutData aanroepen om DAE-parametergegevens te verzenden. Wanneer alle DAE-invoerparameters worden verwerkt, retourneert SQLParamData SQL_PARAM_DATA_AVAILABLE om aan te geven dat gestreamde uitvoerparameters beschikbaar zijn.
Wanneer er gestreamde uitvoerparameters en afhankelijke uitvoerparameters moeten worden verwerkt, bepaalt het stuurprogramma de volgorde voor het verwerken van uitvoerparameters. Dus als een uitvoerparameter is gebonden aan een buffer (de parameter InputOutputTypevan DE SQLBindParameter is ingesteld op SQL_PARAM_INPUT_OUTPUT of SQL_PARAM_OUTPUT), wordt de buffer mogelijk pas ingevuld als SQLParamData SQL_SUCCESS of SQL_SUCCESS_WITH_INFO retourneert. Een toepassing moet een gebonden buffer alleen lezen nadat SQLParamData SQL_SUCCESS of SQL_SUCCESS_WITH_INFO retourneert, en dat moet gebeuren nadat alle gestreamde uitvoerparameters zijn verwerkt.
De gegevensbron kan een waarschuwing en resultatenset retourneren, naast de gestreamde uitvoerparameter. Over het algemeen worden waarschuwingen en resultatensets afzonderlijk verwerkt van een gestreamde uitvoerparameter door SQLMoreResults aan te roepen. Proceswaarschuwingen en de resultatenset voordat de gestreamde uitvoerparameter wordt verwerkt.
In de volgende tabel worden verschillende scenario's beschreven van één opdracht die naar de server wordt verzonden en hoe de toepassing moet werken.
| Scenario | Retourwaarde van SQLExecute of SQLExecDirect | Wat u vervolgens moet doen |
|---|---|---|
| Gegevens bevatten alleen gestreamde uitvoerparameters | SQL_PARAM_DATA_AVAILABLE | Gebruik SQLParamData en SQLGetData om gestreamde uitvoerparameters op te halen. |
| Gegevens bevatten een resultatenset en gestreamde uitvoerparameters | SQL_SUCCESS | Haal de resultatenset op met SQLBindCol en SQLGetData. Roep SQLMoreResults aan om de verwerking van gestreamde uitvoerparameters te starten. Het moet SQL_PARAM_DATA_AVAILABLE retourneren. Gebruik SQLParamData en SQLGetData om gestreamde uitvoerparameters op te halen. |
| Gegevens bevatten een waarschuwingsbericht en gestreamde uitvoerparameters | SQL_SUCCESS_WITH_INFO | Gebruik SQLGetDiagRec en SQLGetDiagField om waarschuwingsberichten te verwerken. Roep SQLMoreResults aan om de verwerking van gestreamde uitvoerparameters te starten. Het moet SQL_PARAM_DATA_AVAILABLE retourneren. Gebruik SQLParamData en SQLGetData om gestreamde uitvoerparameters op te halen. |
| Gegevens bevatten een waarschuwingsbericht, resultatenset en gestreamde uitvoerparameters | SQL_SUCCESS_WITH_INFO | Gebruik SQLGetDiagRec en SQLGetDiagField om waarschuwingsberichten te verwerken. Roep vervolgens SQLMoreResults aan om te beginnen met het verwerken van de resultatenset. Haal een resultatenset op met SQLBindCol en SQLGetData. Roep SQLMoreResults aan om de verwerking van gestreamde uitvoerparameters te starten. SQLMoreResults moet SQL_PARAM_DATA_AVAILABLE retourneren. Gebruik SQLParamData en SQLGetData om gestreamde uitvoerparameters op te halen. |
| Voer query's uit met DAE-invoerparameters, bijvoorbeeld een gestreamde DAE-parameter (invoer/uitvoer) | SQL-NEED_DATA | Roep SQLParamData en SQLPutData aan om DAE-invoerparametergegevens te verzenden. Nadat alle DAE-invoerparameters zijn verwerkt, kan SQLParamData elke retourcode retourneren die SQLExecute en SQLExecDirect kunnen retourneren. De gevallen in deze tabel kunnen vervolgens worden toegepast. Als de retourcode is SQL_PARAM_DATA_AVAILABLE, zijn gestreamde uitvoerparameters beschikbaar. Een toepassing moet SQLParamData opnieuw aanroepen om het token voor de gestreamde uitvoerparameter op te halen, zoals beschreven in de eerste rij van deze tabel. Als de retourcode is SQL_SUCCESS, is er een resultatenset die moet worden verwerkt of is de verwerking voltooid. Als de retourcode SQL_SUCCESS_WITH_INFO is, zijn er waarschuwingsberichten om te verwerken. |
Nadat SQLExecute, SQLExecDirect of SQLMoreResults SQL_PARAM_DATA_AVAILABLE retourneert, resulteert een functiereeksfout als een toepassing een functie aanroept die niet in de volgende lijst staat:
SQLAllocHandle / SQLAllocHandleStd
SQLDataSources / SQLDrivers
SQLGetInfo / SQLGetFunctions
SQLGetConnectAttr / SQLGetEnvAttr / SQLGetDescField / SQLGetDescRec
SQLNumParams
SQLDescribeParam
SQLNativeSql
SQLParamData
SQLMoreResults
SQLGetDiagField / SQLGetDiagRec
SQLCancel
SQLCancelHandle (met instructiegreep)
SQLFreeStmt (met Optie = SQL_CLOSE, SQL_DROP of SQL_UNBIND)
SQLCloseCursor
SQLDisconnect
SQLFreeHandle (met HandleType = SQL_HANDLE_STMT)
SQLGetStmtAttr
Toepassingen kunnen nog steeds SQLSetDescField of SQLSetDescRec gebruiken om de bindingsgegevens in te stellen. Veldtoewijzing wordt niet gewijzigd. Velden in de descriptor kunnen echter nieuwe waarden retourneren. SQL_DESC_PARAMETER_TYPE kan bijvoorbeeld SQL_PARAM_INPUT_OUTPUT_STREAM of SQL_PARAM_OUTPUT_STREAM retourneren.
Gebruiksscenario: een afbeelding in onderdelen ophalen uit een resultatenset
SQLGetData kan worden gebruikt om gegevens in onderdelen op te halen wanneer een opgeslagen procedure een resultatenset retourneert die één rij metagegevens over een afbeelding bevat en de afbeelding wordt geretourneerd in een grote uitvoerparameter.
// 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;
}
Gebruiksscenario: Een groot object verzenden en ontvangen als een gestreamde invoer-/uitvoerparameter
SQLGetData kan worden gebruikt om gegevens in delen op te halen en te verzenden wanneer een opgeslagen procedure een groot object doorgeeft als invoer-/uitvoerparameter, waarbij de waarde naar en van de database wordt gestreamd. U hoeft niet alle gegevens in het geheugen op te slaan.
// 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;
}