Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Przed ODBC 3.8 aplikacja mogła pobrać tylko parametry wyjściowe zapytania z powiązanym buforem wyjściowym. Trudno jednak przydzielić bardzo duży bufor, gdy rozmiar wartości parametru jest bardzo duży (na przykład duży obraz). ODBC 3.8 wprowadza nowy sposób pobierania parametrów wyjściowych w segmentach. Aplikacja może teraz wywołać funkcję SQLGetData z małym buforem wielokrotnie, aby pobrać dużą wartość parametru. Jest to podobne do pobierania danych z dużych kolumn.
Aby powiązać parametr wyjściowy lub parametr wejściowy/wyjściowy do pobierania w częściach, wywołaj SQLBindParameter z argumentem InputOutputType ustawionym na SQL_PARAM_OUTPUT_STREAM lub SQL_PARAM_INPUT_OUTPUT_STREAM. W przypadku SQL_PARAM_INPUT_OUTPUT_STREAM aplikacja może używać sqlPutData do wprowadzania danych do parametru, a następnie pobierać parametr wyjściowy za pomocą funkcji SQLGetData . Dane wejściowe muszą znajdować się w formacie data-at-execution (DAE) przy użyciu SQLPutData zamiast wiązania ich ze wstępnie alokowanym buforem.
Ta funkcja może być używana przez aplikacje ODBC 3.8 lub ponownie skompilowane aplikacje ODBC 3.x i ODBC 2.x, a te aplikacje muszą mieć sterownik ODBC 3.8, który obsługuje pobieranie parametrów wyjściowych przy użyciu sqlGetData i ODBC 3.8 Driver Manager. Aby uzyskać informacje na temat włączania starszej aplikacji do korzystania z nowych funkcji ODBC, zobacz Macierz zgodności.
Przykład użycia
Rozważ na przykład wykonanie procedury składowanej {CALL sp_f(?,?)}, gdzie oba parametry są powiązane jako SQL_PARAM_OUTPUT_STREAM, a procedura składowana nie zwraca żadnego zestawu wyników (w dalszej części tego tematu znajdziesz bardziej złożony scenariusz):
Dla każdego parametru wywołaj parametr SQLBindParameter z parametrem InputOutputType ustawionym na SQL_PARAM_OUTPUT_STREAM i ParametrValuePtr ustawionym na token, taki jak numer parametru, wskaźnik do danych lub wskaźnik do struktury używanej przez aplikację do powiązania parametrów wejściowych. W tym przykładzie użyto parametru ordinalnego jako tokenu.
Wykonaj zapytanie za pomocą polecenia SQLExecDirect lub SQLExecute. SQL_PARAM_DATA_AVAILABLE zostaną zwrócone, co wskazuje, że do pobierania są dostępne parametry wyjściowe przesyłane strumieniowo.
Wywołaj metodę SQLParamData , aby uzyskać parametr dostępny do pobrania. Funkcja SQLParamData zwróci SQL_PARAM_DATA_AVAILABLE z tokenem pierwszego dostępnego parametru, który jest ustawiony w parametrze SQLBindParameter (krok 1). Token jest zwracany w buforze, na który wskazuje ValuePtrPtr.
Wywołaj metodę SQLGetData za pomocą argumentu Col_or_Param_Num ustawionego na porządkowy parametr, aby pobrać dane pierwszego dostępnego parametru. Jeśli SQLGetData zwraca SQL_SUCCESS_WITH_INFO i SQLState 01004 (dane obcięte), i jeśli typ ma zmienną długość zarówno po stronie klienta, jak i serwera, do pobrania jest więcej danych z pierwszego dostępnego parametru. Możesz nadal wywoływać funkcję SQLGetData , dopóki nie zwróci SQL_SUCCESS lub SQL_SUCCESS_WITH_INFO z innym stanem SQLState.
Powtórz krok 3 i krok 4, aby pobrać bieżący parametr.
Ponownie wywołaj metodę SQLParamData . Jeśli zwraca wszystkie elementy z wyjątkiem SQL_PARAM_DATA_AVAILABLE, nie ma więcej przesyłanych strumieniowo danych parametrów do pobrania, a kod zwracany będzie kodem zwracanym kolejnej instrukcji, która jest wykonywana.
Wywołaj metodę SQLMoreResults , aby przetworzyć następny zestaw parametrów, dopóki nie zwróci SQL_NO_DATA. Funkcja SQLMoreResults zwróci SQL_NO_DATA w tym przykładzie, jeśli atrybut instrukcji SQL_ATTR_PARAMSET_SIZE został ustawiony na 1. W przeciwnym razie funkcja SQLMoreResults zwróci SQL_PARAM_DATA_AVAILABLE, aby wskazać, że są dostępne parametry wyjściowe przesyłane strumieniowo dla następnego zestawu parametrów do pobrania.
Podobnie jak w przypadku parametru wejściowego DAE, token używany w argumencie ParameterValuePtr w funkcji SQLBindParameter (krok 1) może być wskaźnikiem na strukturę danych aplikacji, która zawiera numerację parametru i, w razie potrzeby, bardziej specyficzne dla aplikacji informacje.
Kolejność zwracanych strumieniowych parametrów wyjściowych lub wejściowych/wyjściowych jest specyficzna dla sterownika i może nie zawsze być taka sama jak kolejność określona w zapytaniu.
Jeśli aplikacja nie wywołuje metody SQLGetData w kroku 4, wartość parametru zostanie odrzucona. Podobnie, jeśli aplikacja wywołuje metodę SQLParamData , zanim wszystkie wartości parametru zostały odczytane przez funkcję SQLGetData, pozostała część wartości zostanie odrzucona, a aplikacja może przetworzyć następny parametr.
Jeśli aplikacja wywołuje metodę SQLMoreResults przed przetworzeniem wszystkich przesyłanych strumieniowo parametrów wyjściowych (funkcja SQLParamData nadal zwraca SQL_PARAM_DATA_AVAILABLE), wszystkie pozostałe parametry zostaną odrzucone. Podobnie, jeśli aplikacja wywołuje element SQLMoreResults przed odczytaniem przez sqlGetData wszystkich wartości parametrów, pozostała część wartości i wszystkie pozostałe parametry zostaną odrzucone, a aplikacja będzie nadal przetwarzać następny zestaw parametrów.
Należy pamiętać, że aplikacja może określić typ danych języka C zarówno w parametrach SQLBindParameter , jak i SQLGetData. Typ danych języka C określony za pomocą parametru SQLGetData zastępuje typ danych C określony w parametrze SQLBindParameter, chyba że typ danych języka C określony w danych SQLGetData jest SQL_APD_TYPE.
Chociaż przesyłany strumieniowo parametr wyjściowy jest bardziej przydatny, gdy typ danych parametru wyjściowego jest typu BLOB, ta funkcja może być również używana z dowolnym typem danych. Typy danych obsługiwane przez parametry przesyłane strumieniowo danych wyjściowych są określone w sterowniku.
Jeśli istnieją parametry SQL_PARAM_INPUT_OUTPUT_STREAM do przetworzenia, procedury SQLExecute lub SQLExecDirect zwrócą najpierw SQL_NEED_DATA. Aplikacja może wywoływać metody SQLParamData i SQLPutData w celu wysyłania danych parametrów języka DAE. Po przetworzeniu wszystkich parametrów wejściowych DAE funkcja SQLParamData zwraca SQL_PARAM_DATA_AVAILABLE, aby wskazać, że dostępne są strumieniowane parametry wyjściowe.
Gdy są przesyłane strumieniowo parametry wyjściowe i powiązane parametry wyjściowe do przetworzenia, sterownik określa kolejność przetwarzania parametrów wyjściowych. Dlatego jeśli parametr wyjściowy jest powiązany z buforem (parametr SQLBindParameterInputOutputType jest ustawiony na wartość SQL_PARAM_INPUT_OUTPUT lub SQL_PARAM_OUTPUT), bufor może nie zostać wypełniony, dopóki funkcja SQLParamData nie zwróci SQL_SUCCESS lub SQL_SUCCESS_WITH_INFO. Aplikacja powinna odczytywać powiązany bufor tylko wtedy, gdy funkcja SQLParamData zwróci SQL_SUCCESS lub SQL_SUCCESS_WITH_INFO, co ma miejsce po przetworzeniu wszystkich przesyłanych strumieniowo parametrów wyjściowych.
Źródło danych może zwrócić ostrzeżenie i zestaw wyników oprócz strumieniowego parametru wyjściowego. Ogólnie rzecz biorąc, ostrzeżenia i zestawy wyników są przetwarzane oddzielnie od przesyłanego strumieniowo parametru wyjściowego przez wywołanie metody SQLMoreResults. Ostrzeżenia dotyczące przetwarzania i zestaw wyników przed przetworzeniem przesyłanego strumieniowo parametru wyjściowego.
W poniższej tabeli opisano różne scenariusze pojedynczego polecenia wysyłanego na serwer oraz sposób działania aplikacji.
| Scenario | Zwracana wartość z sqlExecute lub SQLExecDirect | Co zrobić dalej |
|---|---|---|
| Dane wyjściowe obejmują tylko parametry przesyłane strumieniowo | SQL_PARAM_DATA_AVAILABLE | Użyj SQLParamData i SQLGetData, aby pobrać strumieniowane parametry wyjściowe. |
| Dane zawierają zestaw wyników i przesyłane strumieniowo parametry wyjściowe | SQL_SUCCESS | Pobierz zestaw wyników przy użyciu elementów SQLBindCol i SQLGetData. Wywołaj metodę SQLMoreResults , aby rozpocząć przetwarzanie strumieniowych parametrów wyjściowych. Powinien zwrócić SQL_PARAM_DATA_AVAILABLE. Użyj SQLParamData i SQLGetData, aby pobrać przesyłane strumieniowo parametry wyjściowe. |
| Dane zawierają komunikat ostrzegawczy i przesyłane strumieniowo parametry wyjściowe | SQL_SUCCESS_WITH_INFO | Użyj funkcji SQLGetDiagRec i SQLGetDiagField do przetwarzania komunikatów ostrzegawczych. Wywołaj metodę SQLMoreResults , aby rozpocząć przetwarzanie strumieniowych parametrów wyjściowych. Powinien zwrócić SQL_PARAM_DATA_AVAILABLE. Użyj funkcji SQLParamData i SQLGetData, aby pobrać przesyłane strumieniowo parametry wyjściowe. |
| Dane zawierają komunikat ostrzegawczy, zestaw wyników i parametry wyjściowe przesyłane strumieniowo | SQL_SUCCESS_WITH_INFO | Użyj SQLGetDiagRec i SQLGetDiagField do przetwarzania komunikatów ostrzegawczych. Następnie wywołaj metodę SQLMoreResults , aby rozpocząć przetwarzanie zestawu wyników. Pobieranie zestawu wyników przy użyciu elementów SQLBindCol i SQLGetData. Wywołaj metodę SQLMoreResults , aby rozpocząć przetwarzanie strumieniowych parametrów wyjściowych. SqlMoreResults powinien zwrócić SQL_PARAM_DATA_AVAILABLE. Użyj SQLParamData i SQLGetData, aby pobrać przesyłane strumieniowo parametry wyjściowe. |
| Zapytanie z parametrami wejściowymi DAE, na przykład parametrem strumieniowym wejściowym/wyjściowym (DAE) | SQL NEED_DATA | Wywołaj metody SQLParamData i SQLPutData , aby wysłać dane parametrów wejściowych języka DAE. Po przetworzeniu wszystkich parametrów wejściowych DAE funkcja SQLParamData może zwrócić dowolny kod zwracany przez SQLExecute i SQLExecDirect. Przypadki w tej tabeli można następnie zastosować. Jeśli kod zwracany jest SQL_PARAM_DATA_AVAILABLE, dostępne są przesyłane strumieniowo parametry wyjściowe. Aplikacja musi ponownie wywołać metodę SQLParamData , aby pobrać token dla przesyłanego strumieniowo parametru wyjściowego, zgodnie z opisem w pierwszym wierszu tej tabeli. Jeśli kod zwracany jest SQL_SUCCESS, istnieje zestaw wyników do przetworzenia lub przetwarzanie zostało zakończone. Jeśli kod powrotny jest SQL_SUCCESS_WITH_INFO, istnieją komunikaty ostrzegawcze do przetworzenia. |
Gdy funkcja SQLExecute, SQLExecDirect lub SQLMoreResults zwróci SQL_PARAM_DATA_AVAILABLE, błąd sekwencji funkcji spowoduje, że aplikacja wywołuje funkcję, która nie znajduje się na poniższej liście:
SQLAllocHandle / SQLAllocHandleStd
SQLDataSources / SQLDrivers
Sqlgetinfo / Sqlgetfunctions
SQLGetConnectAttr / SQLGetEnvAttr / SQLGetDescField / SQLGetDescRec
SQLNumParams
Sqldescribeparam
SQLNativeSql
Sqlparamdata
Sqlmoreresults
Sqlgetdiagfield / Sqlgetdiagrec
Sqlcancel
SQLCancelHandle (z obsługą instrukcji)
SQLFreeStmt (z opcją = SQL_CLOSE, SQL_DROP lub SQL_UNBIND)
SQLCloseCursor
SQLDisconnect
SQLFreeHandle (with HandleType = SQL_HANDLE_STMT)
SQLGetStmtAttr
Aplikacje nadal mogą używać sqlSetDescField lub SQLSetDescRec , aby ustawić informacje o powiązaniu. Mapowanie pól nie zostanie zmienione. Jednak pola wewnątrz deskryptora mogą zwracać nowe wartości. Na przykład SQL_DESC_PARAMETER_TYPE może zwrócić SQL_PARAM_INPUT_OUTPUT_STREAM lub SQL_PARAM_OUTPUT_STREAM.
Scenariusz użycia: pobieranie obrazu w częściach z zestawu wyników
Funkcja SQLGetData może służyć do pobierania danych w częściach, gdy procedura składowana zwraca zestaw wyników zawierający jeden wiersz metadanych obrazu, a obraz jest zwracany w dużym parametrze wyjściowym.
// 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;
}
Scenariusz użycia: wysyłanie i odbieranie dużego obiektu jako strumieniowego parametru wejściowego/wyjściowego
Funkcja SQLGetData może służyć do pobierania i wysyłania danych w częściach, gdy procedura składowana przekazuje duży obiekt jako parametr wejściowy/wyjściowy, przesyłając strumieniowo wartość do i z bazy danych. Nie trzeba przechowywać wszystkich danych w pamięci.
// 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;
}