Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Před rozhraním ODBC 3.8 mohla aplikace načíst pouze výstupní parametry dotazu s vázanou výstupní vyrovnávací pamětí. Je však obtížné přidělit velmi velkou vyrovnávací paměť, pokud je velikost hodnoty parametru velmi velká (například velký obrázek). ODBC 3.8 zavádí nový způsob vyzvedávání výstupních parametrů po částech. Aplikace nyní může volat SQLGetData vícekrát s malým množstvím vyrovnávací paměti, aby načetla velkou hodnotu parametru. Toto se podobá načítání velkých sloupcových dat.
Chcete-li vytvořit vazbu výstupního parametru nebo vstupního/výstupního parametru, který se má načíst v částech, zavolejte sqlBindParameter s argumentem InputOutputType nastaveným na SQL_PARAM_OUTPUT_STREAM nebo SQL_PARAM_INPUT_OUTPUT_STREAM. S SQL_PARAM_INPUT_OUTPUT_STREAM může aplikace použít SQLPutData ke zadávání dat do parametru a pak pomocí SQLGetData načíst výstupní parametr. Vstupní data musí být ve formátu data-at-execution (DAE) pomocí SQLPutData místo jejich vazby na předem přiřazenou vyrovnávací paměť.
Tuto funkci mohou používat aplikace ODBC 3.8 nebo rekompilované aplikace ODBC 3.x a ODBC 2.x, a tyto aplikace musí mít ovladač ODBC 3.8, který podporuje načítání výstupních parametrů pomocí SQLGetData a Správce ovladačů ODBC 3.8. Informace o tom, jak povolit starší aplikaci používat nové funkce ODBC, naleznete v tématu Matice kompatibility.
Příklad použití
Zvažte například provedení uložené procedury {CALL sp_f(?,?)}, kde jsou oba parametry svázané jako SQL_PARAM_OUTPUT_STREAM a uložená procedura nevrátí žádnou sadu výsledků (dále v tomto tématu najdete složitější scénář):
Pro každý parametr volejte SQLBindParameter s InputOutputType nastaveným na SQL_PARAM_OUTPUT_STREAM a ParameterValuePtr nastaven na token, například číslo parametru, ukazatel na data nebo ukazatel na strukturu, kterou aplikace používá k vytvoření vazby vstupních parametrů. V tomto příkladu se jako token použije řadový parametr.
Spusťte dotaz pomocí SQLExecDirect nebo SQLExecute. SQL_PARAM_DATA_AVAILABLE se vrátí, což znamená, že jsou k dispozici streamované výstupní parametry pro načtení.
Zavolejte SQLParamData, abyste získali parametr, který je k dispozici pro načtení. SQLParamData vrátí SQL_PARAM_DATA_AVAILABLE s tokenem prvního dostupného parametru, který je nastavený v SQLBindParameter (krok 1). Token se vrátí do vyrovnávací paměti, na kterou ValuePtrPtr odkazuje.
Volání SQLGetData s argumentem Col_or_Param_Num nastaveným na parametr ordinal pro načtení dat prvního dostupného parametru. Pokud SQLGetData vrátí SQL_SUCCESS_WITH_INFO a SQLState 01004 (data zkrácena) a typ je proměnná délka na klientovi i serveru, je třeba načíst více dat z prvního dostupného parametru. Můžete pokračovat v volání SQLGetData , dokud nevrátí SQL_SUCCESS nebo SQL_SUCCESS_WITH_INFO s jiným SQLState.
Opakováním kroku 3 a kroku 4 načtěte aktuální parametr.
Znovu zavolejte SQLParamData . Pokud vrátí cokoli kromě SQL_PARAM_DATA_AVAILABLE, už nejsou streamovaná data parametrů k načtení a návratový kód bude návratový kód dalšího příkazu, který se spustí.
Zavolejte SQLMoreResults pro zpracování další sady parametrů, dokud nevrátí SQL_NO_DATA. SQLMoreResults vrátí SQL_NO_DATA v tomto příkladu, pokud byl atribut příkazu SQL_ATTR_PARAMSET_SIZE nastaven na hodnotu 1. V opačném případě vrátí funkce SQLMoreResults SQL_PARAM_DATA_AVAILABLE, která indikuje, že pro další sadu parametrů, které se mají načíst, jsou k dispozici streamované výstupní parametry.
Podobně jako vstupní parametr DAE může být token použitý v argumentu ParameterValuePtr v SQLBindParameter (krok 1) ukazatel, který odkazuje na datovou strukturu aplikace, která v případě potřeby obsahuje pořadové číslo parametru a další informace specifické pro aplikaci.
Pořadí vrácených streamovaných výstupních nebo vstupních/výstupních parametrů je specifické pro konkrétní ovladač a nemusí být vždy stejné jako pořadí zadané v dotazu.
Pokud aplikace nevolá SQLGetData v kroku 4, hodnota parametru se zahodí. Podobně pokud aplikace volá SQLParamData před načtením všech hodnot parametru sqlGetData, zbytek hodnoty je zahozen a aplikace může zpracovat další parametr.
Pokud aplikace volá SQLMoreResults před zpracováním všech streamovaných výstupních parametrů (SQLParamData stále vrací SQL_PARAM_DATA_AVAILABLE), všechny zbývající parametry se zahodí. Podobně platí, že pokud aplikace volá SQLMoreResults před načtením všech hodnot parametru SQLGetData, zbytek hodnoty a všechny zbývající parametry jsou zahozeny a aplikace může pokračovat ve zpracování další sady parametrů.
Aplikace může zadat datový typ C v SQLBindParameter i SQLGetData. Datový typ C zadaný pomocí SQLGetData přepíše datový typ C zadaný v SQLBindParameter, pokud datový typ jazyka C zadaný v SQLGetData není SQL_APD_TYPE.
I když streamovaný výstupní parametr je užitečnější v případě, že datový typ výstupního parametru je typu BLOB, lze tuto funkci použít i s libovolným datovým typem. Datové typy podporované streamovanými výstupními parametry jsou uvedeny v ovladači.
Pokud se mají zpracovat parametry SQL_PARAM_INPUT_OUTPUT_STREAM, SQLExecute nebo SQLExecDirect nejprve vrátí SQL_NEED_DATA. Aplikace může volat SQLParamData a SQLPutData k odesílání dat parametrů DAE. Po zpracování všech vstupních parametrů DAE zobrazí SQLParamData SQL_PARAM_DATA_AVAILABLE, aby naznačil, že streamované výstupní parametry jsou k dispozici.
Pokud jsou streamované výstupní parametry a vázané výstupní parametry, které se mají zpracovat, ovladač určuje pořadí zpracování výstupních parametrů. Pokud je výstupní parametr vázán na vyrovnávací paměť (parametr SQLBindParameterInputOutputType je nastaven na SQL_PARAM_INPUT_OUTPUT nebo SQL_PARAM_OUTPUT), vyrovnávací paměť nemusí být naplněna, dokud SQLParamData nevrátí SQL_SUCCESS nebo SQL_SUCCESS_WITH_INFO. Aplikace by měla vázanou vyrovnávací paměť číst až poté, co SQLParamData vrátí SQL_SUCCESS nebo SQL_SUCCESS_WITH_INFO, a to až po zpracování všech streamovaných výstupních parametrů.
Zdroj dat může kromě streamovaného výstupního parametru vrátit i upozornění a sadu výsledků. Obecně platí, že upozornění a sady výsledků se zpracovávají odděleně od streamovaného výstupního parametru voláním SQLMoreResults. Zpracujte upozornění a výsledkovou sadu před zpracováním streamovaného výstupního parametru.
Následující tabulka popisuje různé scénáře jednoho příkazu odeslaného na server a způsob fungování aplikace.
| Scenario | Návratová hodnota z SQLExecute nebo SQLExecDirect | Co dělat dál |
|---|---|---|
| Data zahrnují pouze streamované výstupní parametry. | SQL_PARAM_DATA_AVAILABLE | K načtení streamovaných výstupních parametrů použijte SQLParamData a SQLGetData . |
| Data zahrnují sadu výsledků a streamované výstupní parametry. | SQL_SUCCESS | Načtěte sadu výsledků pomocí sqlBindCol a SQLGetData. Volání SQLMoreResults ke spuštění zpracování streamovaných výstupních parametrů. Měla by se vrátit SQL_PARAM_DATA_AVAILABLE. K načtení streamovaných výstupních parametrů použijte SQLParamData a SQLGetData . |
| Data zahrnují upozornění a streamované výstupní parametry. | SQL_SUCCESS_WITH_INFO | Ke zpracování zpráv upozornění použijte SQLGetDiagRec a SQLGetDiagField . Volání SQLMoreResults ke spuštění zpracování streamovaných výstupních parametrů. Měla by se vrátit SQL_PARAM_DATA_AVAILABLE. K načtení streamovaných výstupních parametrů použijte SQLParamData a SQLGetData . |
| Data zahrnují upozornění, sadu výsledků a streamované výstupní parametry. | SQL_SUCCESS_WITH_INFO | Ke zpracování zpráv upozornění použijte SQLGetDiagRec a SQLGetDiagField . Potom zavolejte SQLMoreResults a začněte zpracovávat sadu výsledků. Načtení sady výsledků pomocí sqlBindCol a SQLGetData Volání SQLMoreResults ke spuštění zpracování streamovaných výstupních parametrů. SQLMoreResults by měla vrátit SQL_PARAM_DATA_AVAILABLE. K načtení streamovaných výstupních parametrů použijte SQLParamData a SQLGetData . |
| Dotazování pomocí vstupních parametrů DAE, například streamovaného vstupního/výstupního parametru (DAE) | SQL POTŘEBUJE_DATA | Volejte SQLParamData a SQLPutData k odeslání dat vstupních parametrů DAE. Po zpracování všech vstupních parametrů DAE může SQLParamData vrátit libovolný návratový kód, který může sqlExecute a SQLExecDirect vrátit. Případy v této tabulce je pak možné použít. Pokud je návratový kód SQL_PARAM_DATA_AVAILABLE, jsou k dispozici streamované výstupní parametry. Aplikace musí znovu volat SQLParamData , aby načetla token streamovaného výstupního parametru, jak je popsáno v prvním řádku této tabulky. Pokud je návratový kód SQL_SUCCESS, buď existuje sada výsledků pro zpracování, nebo je zpracování dokončeno. Pokud je návratový kód SQL_SUCCESS_WITH_INFO, existují zprávy s upozorněním, které je potřeba zpracovat. |
Jakmile sqlExecute, SQLExecDirect nebo SQLMoreResults vrátí SQL_PARAM_DATA_AVAILABLE, dojde k chybě sekvence funkce, pokud aplikace volá funkci, která není v následujícím seznamu:
SQLAllocHandle / SQLAllocHandleStd
SQLDataSources / SQLDrivers
SQLGetInfo / SQLGetFunctions
SQLGetConnectAttr / SQLGetEnvAttr / SQLGetDescField / SQLGetDescRec
SQLNumParams
Sqldescribeparam
SQLNativeSql
Sqlparamdata
Sqlmoreresults
SQLGetDiagField / SQLGetDiagRec
SQLCancel
SQLCancelHandle (s popisovačem příkazu)
SQLFreeStmt (s možností = SQL_CLOSE, SQL_DROP nebo SQL_UNBIND)
SQLCloseCursor
SQLDisconnect
SQLFreeHandle (s HandleType = SQL_HANDLE_STMT)
SQLGetStmtAttr
Aplikace mohou stále používat SQLSetDescField nebo SQLSetDescRec k nastavení informací vazby. Mapování polí se nezmění. Pole uvnitř popisovače ale můžou vracet nové hodnoty. Například SQL_DESC_PARAMETER_TYPE může vrátit SQL_PARAM_INPUT_OUTPUT_STREAM nebo SQL_PARAM_OUTPUT_STREAM.
Scénář použití: Načtení obrázku v částech ze sady výsledků
SQLGetData lze použít k získání dat v částech, když uložená procedura vrátí sadu výsledků obsahující jeden řádek metadat o obrázku a image se vrátí ve velkém výstupním parametru.
// 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;
}
Scénář použití: Odeslání a přijetí velkého objektu jako streamovaného vstupního nebo výstupního parametru
SQLGetData lze použít k získání a odesílání dat v částech, když uložená procedura předává velký objekt jako vstupní/výstupní parametr, streamuje hodnotu do a z databáze. Nemusíte ukládat všechna data do paměti.
// 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;
}