Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Zgodność
Wprowadzona wersja: Zgodność ze standardami ODBC 3.0: ODBC
Podsumowanie
SQLBulkOperations wykonuje masowe wstawianie i masowe operacje zakładek, w tym aktualizację, usuwanie i pobieranie przez zakładki.
Syntax
SQLRETURN SQLBulkOperations(
SQLHSTMT StatementHandle,
SQLUSMALLINT Operation);
Arguments
StatementHandle
[Dane wejściowe] Uchwyt instrukcji.
Operation
[Input] Operacja do wykonania:
SQL_ADD SQL_UPDATE_BY_BOOKMARK SQL_DELETE_BY_BOOKMARK SQL_FETCH_BY_BOOKMARK
Więcej informacji znajdziesz w sekcji "Komentarze."
Zwroty
SQL_SUCCESS, SQL_SUCCESS_WITH_INFO, SQL_NEED_DATA, SQL_STILL_EXECUTING, SQL_ERROR lub SQL_INVALID_HANDLE.
Diagnostyka
Gdy SQLBulkOperations zwraca SQL_ERROR lub SQL_SUCCESS_WITH_INFO, powiązaną wartość SQLSTATE można uzyskać, wywołując SQLGetDiagRec z HandleType SQL_HANDLE_STMT oraz HandleStatementHandle. Poniższa tabela przedstawia wartości SQLSTATE typowo zwracane przez SQLBulkOperations i wyjaśnia każdą z nich w kontekście tej funkcji; notacja "(DM)" poprzedza opisy stanów SQL zwracanych przez Menedżera Sterowników. Kod zwracany skojarzony z każdą wartością SQLSTATE jest SQL_ERROR, chyba że określono inaczej.
Dla wszystkich stanów SQL, które mogą zwracać SQL_SUCCESS_WITH_INFO lub SQL_ERROR (z wyjątkiem 01xxx SQLSTATE), SQL_SUCCESS_WITH_INFO zwracany, jeśli błąd wystąpi na jednym lub więcej, ale nie we wszystkich wierszach operacji wielowierszowej, a SQL_ERROR zwracany, jeśli błąd wystąpi w operacji pojedynczej wierszowej.
| SQLSTATE | Error | Description |
|---|---|---|
| 01000 | Ostrzeżenie ogólne | Komunikat informacyjny specyficzny dla sterownika. (Funkcja zwraca SQL_SUCCESS_WITH_INFO). |
| 01004 | Obcięcie prawej skracki danych ciągu | Argument Operation był SQL_FETCH_BY_BOOKMARK, a dane ciągowe lub binarne zwracane dla kolumny lub kolumn o typie danych SQL_C_CHAR lub SQL_C_BINARY skutkowały obcięciem niepustych znaków lub danych binarnych nie-NULL. |
| 01S01 | Błąd w wierszu | Argument Operacja był SQL_ADD, a podczas wykonywania operacji wystąpił błąd w jednym lub więcej wierszach, ale przynajmniej jeden wiersz został pomyślnie dodany. (Funkcja zwraca SQL_SUCCESS_WITH_INFO). (Ten błąd pojawia się tylko wtedy, gdy aplikacja pracuje z ODBC 2. x driver.) |
| 01S07 | Obcięcie ułamkowe | Argument Operation był SQL_FETCH_BY_BOOKMARK, typ danych bufora aplikacji nie był SQL_C_CHAR ani SQL_C_BINARY, a dane wracane do buforów aplikacji dla jednej lub więcej kolumn były obcinane. (Dla numerycznych typów danych C część ułamkowa liczby była obcięta. Dla typów danych czasowych, znaczników czasowych i przedziału C zawierających składową czasową, część czasu ułamkowa została obcięta.) (Funkcja zwraca SQL_SUCCESS_WITH_INFO). |
| 07006 | Naruszenie atrybutu typu danych z ograniczeniami | Argument Operation był SQL_FETCH_BY_BOOKMARK, a wartość danych kolumny w zbiorze wyników nie mogła zostać przekonwertowana na typ danych określony przez argument TargetType w wywołaniu SQLBindCol. Argument Operacja to SQL_UPDATE_BY_BOOKMARK lub SQL_ADD, a wartość danych w buforach aplikacji nie mogła zostać przekonwertowana na typ danych kolumny w zbiorze wyników. |
| 07009 | Nieprawidłowy indeks deskryptorów | Argument Operacja była SQL_ADD, a kolumna była owiązywana z numerem kolumny większym niż liczba kolumn w zbiorze wyników. |
| 21S02 | Stopień tabeli pochodnej nie jest zgodny z listą kolumn | Argumentem Operacja była SQL_UPDATE_BY_BOOKMARK; i żadne kolumny nie były aktualizowane, ponieważ wszystkie kolumny były albo niepowiązane, albo tylko do odczytu, albo wartość w buforze długości bound/wskaźnika była SQL_COLUMN_IGNORE. |
| 22001 | Obcięcie prawej skracki danych ciągu | Przypisanie znaku lub wartości binarnej do kolumny w zbiorze wyników skutkowało obcięciem znaków lub bajtów niepustych (dla znaków) lub nie-nulowych (dla binarnych). |
| 22003 | Wartość liczbowa poza zakresem | Argument Operacja był SQL_ADD lub SQL_UPDATE_BY_BOOKMARK, a przypisanie wartości liczbowej kolumnie w zbiorze wyników powodowało obcięcie całej (w przeciwieństwie do ułamkowej) części liczby. Argument Operation był SQL_FETCH_BY_BOOKMARK, a zwracanie wartości liczbowej dla jednej lub więcej kolumn wiązanych powodowałoby utratę istotnych cyfr. |
| 22007 | Nieprawidłowy format daty/godziny | Argument Operacja brzmiał SQL_ADD lub SQL_UPDATE_BY_BOOKMARK, a przypisanie wartości daty lub znacznika czasu do kolumny w zestawie wyników powodowało, że pole roku, miesiąca lub dnia było poza zakresem. Argument Operacja był SQL_FETCH_BY_BOOKMARK, a zwrot daty lub znacznika czasu dla jednej lub więcej powiązanych kolumn powodowałby, że pole roku, miesiąca lub dnia byłoby poza zakresem. |
| 22008 | Przepełnienie pola daty/czasu | Argument operacji był SQL_ADD lub SQL_UPDATE_BY_BOOKMARK, a wykonanie arytmetyki datowej na danych przesyłanych do kolumny w zbiorze wyników skutkowało tym, że pole daty (rok, miesiąc, dzień, godzina, minuta lub drugie pole) wyniku, wykraczało poza dopuszczalny zakres wartości dla pola lub było nieważne według naturalnych reguł kalendarza gregoriańskiego dla dat. Argument operacji był SQL_FETCH_BY_BOOKMARK, a wykonanie arytmetyki daty-czasu na danych pobieranych z zestawu wyników skutkowało tym, że pole daty (rok, miesiąc, dzień, godzina, minuta lub drugie pole) wyniku, wykraczało poza dopuszczalny zakres wartości dla pola lub było nieważne według naturalnych reguł kalendarza gregoriańskiego dla dat. |
| 22015 | Przepełnienie pola interwału | Argument Operacja był SQL_ADD lub SQL_UPDATE_BY_BOOKMARK, a przypisanie dokładnego numerycznego lub interwałowego typu C do typu SQL interwałowego powodowało utratę istotnych cyfr. Argument dotyczący Operacji brzmiał SQL_ADD lub SQL_UPDATE_BY_BOOKMARK; przy przypisywaniu typu SQL interwałowego nie było reprezentacji wartości typu C w typie SQL interwału. Argument Operation był SQL_FETCH_BY_BOOKMARK, a przypisanie z dokładnego numerycznego lub interwałowego typu SQL do typu przedziału C powodowało utratę istotnych cyfr w polu wiodącym. Argument dotyczący Operacji był SQL_FETCH_BY_BOOKMARK; przy przypisywaniu do typu przedziału C nie było reprezentacji wartości typu SQL w typie przedziału C. |
| 22018 | Nieprawidłowa wartość znaku dla specyfikacji rzutu | Argument dotyczący Operacji był SQL_FETCH_BY_BOOKMARK; typ C był dokładnym lub przybliżonym numerycznym typem danych, datą lub przedziałem; typ SQL kolumny był typem danych znaków; a wartość w kolumnie nie była prawidłowym literalem typu C z wiązaniem. Argument Operacja to SQL_ADD lub SQL_UPDATE_BY_BOOKMARK; typ SQL był dokładnym lub przybliżonym numerem, datą lub typem danych interwałowych; typ C był SQL_C_CHAR; a wartość w kolumnie nie była prawidłowym literalem powiązanego typu SQL. |
| 23000 | Naruszenie ograniczeń integralności | Argument dotyczący Operacji był SQL_ADD, SQL_DELETE_BY_BOOKMARK lub SQL_UPDATE_BY_BOOKMARK, a naruszono ograniczenie integralności. Argument Operacja był SQL_ADD, a kolumna, która nie była związana, jest definiowana jako NIE NULL i nie ma domyślnego. Argument Operation był SQL_ADD, długość określona w buforze bound StrLen_or_IndPtr była SQL_COLUMN_IGNORE, a kolumna nie miała wartości domyślnej. |
| 24000 | Nieprawidłowy stan kursora | CommandHandle był w stanie wykonania, ale żaden zestaw wyników nie był powiązany z StatementHandle. |
| 40001 | Niepowodzenie serializacji | Transakcja została wycofana z powodu zakleszczenia zasobów z inną transakcją. |
| 40003 | Ukończenie instrukcji nieznane | Skojarzone połączenie nie powiodło się podczas wykonywania tej funkcji, a nie można określić stanu transakcji. |
| 42000 | Błąd składniowy lub naruszenie dostępu | Kierowca nie był w stanie zablokować wiersza zgodnie z koniecznością wykonania operacji wymaganej w argumentze Operation . |
| 44000 | Z NARUSZENIEM OPCJI SPRAWDZANIA | Argument Operation to SQL_ADD lub SQL_UPDATE_BY_BOOKMARK, a wstawienie lub aktualizacja była wykonywana na wyświetlonej tabeli (lub tabeli pochodzącej z tej tabeli), która została utworzona przez wpisanie Z OPCJĄ CHECK, w taki sposób, że jeden lub więcej wierszy dotkniętych wstawką lub aktualizacją nie będzie już obecne w wyświetlanej tabeli. |
| HY000 | Błąd ogólny | Wystąpił błąd, dla którego nie było określonego stanu SQLSTATE i dla którego nie zdefiniowano parametru SQLSTATE specyficznego dla implementacji. Komunikat o błędzie zwrócony przez element SQLGetDiagRec w buforze *MessageText opisuje błąd i jego przyczynę. |
| HY001 | Błąd alokacji pamięci | Sterownik nie może przydzielić pamięci wymaganej do obsługi wykonywania lub ukończenia funkcji. |
| HY008 | Operacja anulowana | Przetwarzanie asynchroniczne zostało włączone dla instrukcji StatementHandle. Wywołano funkcję , a przed zakończeniem wykonywania wywołano metodę SQLCancel lub SQLCancelHandle w obiekcie StatementHandle. Następnie funkcja została ponownie wywołana w instrukcji StatementHandle. Wywołano funkcję , a przed zakończeniem wykonywania wywołano funkcję SQLCancel lub SQLCancelHandle na instrukcjiHandle z innego wątku w aplikacji wielowątku. |
| HY010 | Błąd sekwencji funkcji | (DM) Asynchronicznie wykonywana funkcja została wywołana dla dojścia połączenia skojarzonego z instrukcją StatementHandle. Ta asynchroniczna funkcja działała nadal, gdy wywoływano funkcję SQLBulkOperations . (DM) SqlExecute, SQLExecDirect lub SQLMoreResults została wywołana dla instrukcji StatementHandle i zwrócona SQL_PARAM_DATA_AVAILABLE. Ta funkcja została wywołana przed pobraniem danych dla wszystkich parametrów przesyłanych strumieniowo. (DM) Określony CommandHandle nie był w stanie wykonania. Funkcja była wywoływana bez wcześniejszego wywołania SQLExecDirect, SQLExecute lub funkcji katalogowej. (DM) Asynchronicznie wykonująca funkcję (a nie tę) została wywołana dla instrukcji StatementHandle i nadal była wykonywana, gdy ta funkcja została wywołana. (DM) SQLExecute, SQLExecDirect lub SQLSetPos zostały wywołane dla CommandHandle i zwracały SQL_NEED_DATA. Ta funkcja została wywołana przed wysłaniem danych dla wszystkich parametrów wykonywania danych lub kolumn. (DM) Kierowca był ODBC 2. x driver, a SQLBulkOperations został wywołany dla CommandHandle przed wywołaniem SQLFetchScroll lub SQLFetch . (DM) SQLBulkOperations został wywołany po wywołaniu SQLExtendedFetch na CommandHandle. |
| HY011 | Atrybut nie może być teraz ustawiony | (DM) Kierowca był ODBC 2. x driver, a atrybut SQL_ATTR_ROW_STATUS_PTR Command był ustawiany pomiędzy wywołaniami SQLFetch , SQLFetchScroll i SQLBulkOperations. |
| HY013 | Błąd zarządzania pamięcią | Nie można przetworzyć wywołania funkcji, ponieważ nie można uzyskać dostępu do bazowych obiektów pamięci, prawdopodobnie z powodu niskich warunków pamięci. |
| HY090 | Nieprawidłowa długość ciągu lub buforu | Argument dotyczący Operacji brzmiał SQL_ADD lub SQL_UPDATE_BY_BOOKMARK; wartość danych nie była wskaźnikiem zerowym; typ danych C to SQL_C_BINARY lub SQL_C_CHAR; a wartość długości kolumny była mniejsza niż 0, ale nie równa SQL_DATA_AT_EXEC, SQL_COLUMN_IGNORE, SQL_NTS ani SQL_NULL_DATA, ani mniejsza lub równa SQL_LEN_DATA_AT_EXEC_OFFSET. Wartość w buforze długości/wskaźnika wynosiła SQL_DATA_AT_EXEC; typ SQL to albo SQL_LONGVARCHAR, SQL_LONGVARBINARY, albo długi typ danych specyficzny dla źródła danych; a SQL_NEED_LONG_DATA_LEN typ informacji w SQLGetInfo to "Y". Argument Operacja był SQL_ADD, atrybut SQL_ATTR_USE_BOOKMARK polecenia ustawiono na SQL_UB_VARIABLE, a kolumna 0 była przypisana do bufora, którego długość nie była równa maksymalnej długości zakładki dla tego zbioru wyników. (Ta długość jest dostępna w polu SQL_DESC_OCTET_LENGTH IRD i można ją uzyskać, wywołując SQLDescribeCol, SQLColAttribute lub SQLGetDescField.) |
| HY092 | Nieprawidłowy identyfikator atrybutu | (DM) Wartość podana dla argumentu Operation była nieprawidłowa. Argument Operacja to SQL_ADD, SQL_UPDATE_BY_BOOKMARK lub SQL_DELETE_BY_BOOKMARK, a atrybut SQL_ATTR_CONCURRENCY instrukcji był ustawiony na SQL_CONCUR_READ_ONLY. Argument Operacja to SQL_DELETE_BY_BOOKMARK, SQL_FETCH_BY_BOOKMARK lub SQL_UPDATE_BY_BOOKMARK, a kolumna zakładek nie była powiązana ani atrybut SQL_ATTR_USE_BOOKMARKS był ustawiony na SQL_UB_OFF. |
| HY117 | Połączenie jest zawieszone z powodu nieznanego stanu transakcji. Dozwolone są tylko funkcje rozłączania i tylko do odczytu. | (DM) Aby uzyskać więcej informacji na temat stanu wstrzymania, zobacz SQLEndTran, funkcja. |
| HYC00 | Opcjonalna funkcja nie zaimplementowana | Sterownik lub źródło danych nie wspiera operacji żądanej w argumentze Operation . |
| HYT00 | Upłynął limit czasu | Okres przekroczenia limitu czasu zapytania wygasł przed zwróceniem zestawu wyników przez źródło danych. Okres przekroczenia czasu jest ustalany za pomocą SQLSetStmtAttr z argumentem atrybutu SQL_ATTR_QUERY_TIMEOUT. |
| HYT01 | Upłynął limit czasu połączenia | Okres przekroczenia limitu czasu połączenia wygasł, zanim źródło danych odpowiedziało na żądanie. Limit czasu połączenia jest ustawiany za pomocą parametru SQLSetConnectAttr, SQL_ATTR_CONNECTION_TIMEOUT. |
| IM001 | Sterownik nie obsługuje tej funkcji | (DM) Sterownik skojarzony z instrukcją StatementHandle nie obsługuje funkcji. |
| IM017 | Sondowanie jest wyłączone w trybie powiadomień asynchronicznych | Za każdym razem, gdy jest używany model powiadomień, sondowanie jest wyłączone. |
| IM018 | Funkcja SQLCompleteAsync nie została wywołana w celu ukończenia poprzedniej operacji asynchronicznej na tym dojściu. | Jeśli poprzednie wywołanie funkcji na dojściu zwraca SQL_STILL_EXECUTING i jeśli tryb powiadomień jest włączony, narzędzie SQLCompleteAsync musi być wywoływane na dojściu, aby wykonać przetwarzanie końcowe i zakończyć operację. |
Comments
Caution
Informacje o tym, jakie zdanie mówi, że SQLBulkOperations można wywołać i co musi zrobić, aby uzyskać kompatybilność z ODBC 2. x aplikacje, zobacz sekcję Kursory Blokowe, Przewijane kursory i Kompatybilność wsteczna w Załączniku G: Wytyczne sterowników dotyczące kompatybilności wstecznej.
Aplikacja wykorzystuje SQLBulkOperations do wykonania następujących operacji na tabeli bazowej lub widoku odpowiadającym aktualnemu zapytaniu:
Dodaj nowe rzędy.
Zaktualizuj zestaw wierszy, gdzie każdy wiersz jest oznaczony zakładką.
Usuń zestaw wierszy, z których każdy wiersz jest oznaczony zakładką.
Pobierz zestaw wierszy, z których każdy wiersz jest oznaczony zakładką.
Po wywołaniu do SQLBulkOperations, pozycja kursora bloku pozostaje nieokreślona. Aplikacja musi wywołać SQLFetchScroll , aby ustawić pozycję kursora. Aplikacja powinna wywoływać SQLFetchScroll wyłącznie z argumentem FetchOrientation o SQL_FETCH_FIRST, SQL_FETCH_LAST, SQL_FETCH_ABSOLUTE lub SQL_FETCH_BOOKMARK. Pozycja kursora nie jest zdefiniowana, jeśli aplikacja wywołuje SQLFetch lub SQLFetchScroll z argumentem FetchOrientation SQL_FETCH_PRIOR, SQL_FETCH_NEXT lub SQL_FETCH_RELATIVE.
Kolumnę można zignorować w operacjach masowych wykonywanych przez wywołanie do SQLBulkOperations , ustawiając długość kolumny/bufor wskaźnikowy określony w wywołaniu SQLBindCol na SQL_COLUMN_IGNORE.
Nie jest konieczne, aby aplikacja ustawiała atrybut SQL_ATTR_ROW_OPERATION_PTR podczas wywoływania SQLBulkOperations , ponieważ wierszy nie mogą być ignorowane podczas wykonywania operacji masowych z tą funkcją.
Bufor, na który wskazuje atrybut SQL_ATTR_ROWS_FETCHED_PTR instrukcji, zawiera liczbę wierszy dotkniętych wywołaniem do SQLBulkOperations.
Gdy argument Operacja jest SQL_ADD lub SQL_UPDATE_BY_BOOKMARK, a lista wyboru specyfikacji zapytania powiązanej z kursorem zawiera więcej niż jedno odwołanie do tej samej kolumny, jest definiowany przez sterownik, niezależnie od tego, czy wygenerowany jest błąd, czy sterownik ignoruje zduplikowane odwołania i wykonuje żądane operacje.
Więcej informacji o tym, jak korzystać z SQLBulkOperations, znajdziesz w artykule Aktualizacja danych za pomocą SQLBulkOperations.
Wykonywanie wkładek masowych
Aby wstawić dane za pomocą SQLBulkOperations, aplikacja wykonuje następującą sekwencję kroków:
Wykonuje zapytanie, które zwraca zbiór wyników.
Ustawia atrybut SQL_ATTR_ROW_ARRAY_SIZE polecenia na liczbę wierszy, które chce wstawić.
Wywołuje SQLBindCol , aby powiązać dane, które chce włożyć. Dane są powiązane z tablicą o rozmiarze równym wartości SQL_ATTR_ROW_ARRAY_SIZE.
Note
Rozmiar tablicy wskazanej przez atrybut SQL_ATTR_ROW_STATUS_PTR powinien być albo równy SQL_ATTR_ROW_ARRAY_SIZE, albo SQL_ATTR_ROW_STATUS_PTR powinien być wskaźnikiem zerowym.
Wywołuje SQLBulkOperations (StatementHandle, SQL_ADD), aby wykonać wstawienie.
Jeśli aplikacja ustawiła atrybut SQL_ATTR_ROW_STATUS_PTR instrukcji, może przejrzeć tę tablicę, aby zobaczyć wynik operacji.
Jeśli aplikacja zwiąże kolumnę 0 przed wywołaniem SQLBulkOperations argumentem Operation o wartości SQL_ADD, sterownik zaktualizuje bufory kolumny 0 o wartości zakładek dla nowo wstawionego wiersza. Aby to nastąpiło, aplikacja musi ustawić atrybut SQL_ATTR_USE_BOOKMARKS instrukcji na SQL_UB_VARIABLE przed wykonaniem instrukcji. (To nie działa z ODBC 2. x driver.)
Długie dane mogą być dodawane częściowo przez SQLBulkOperations, wykorzystując wywołania SQLParamData i SQLPutData. Więcej informacji można znaleźć w artykule "Dostarczanie długich danych dla wstawiania i aktualizacji masowych" później w tej funkcji.
Nie jest konieczne, aby aplikacja wywoływała SQLFetch lub SQLFetchScroll przed wywołaniem SQLBulkOperations (z wyjątkiem sytuacji, gdy jest przeciw ODBC 2.x driver; zobacz Kompatybilność wsteczna i zgodność ze standardami).
Zachowanie jest definiowane przez sterownik, jeśli SQLBulkOperations, z argumentem Operation SQL_ADD, jest wywołany na kursorze zawierającym zduplikowane kolumny. Sterownik może zwracać zdefiniowany przez sterownik stan SQL, dodawać dane do pierwszej kolumny pojawiającej się w zbiorze wyników lub wykonywać inne zachowania zdefiniowane przez sterownik.
Wykonywanie masowych aktualizacji za pomocą zakładek
Aby wykonać aktualizacje masowe za pomocą zakładek z SQLBulkOperations, aplikacja wykonuje następujące kroki w kolejności:
Ustawia atrybut SQL_ATTR_USE_BOOKMARKS na SQL_UB_VARIABLE.
Wykonuje zapytanie, które zwraca zbiór wyników.
Ustawia atrybut SQL_ATTR_ROW_ARRAY_SIZE instrukcji na liczbę wierszy, które chce zaktualizować.
Wywołuje SQLBindCol , aby powiązać dane, które chce zaktualizować. Dane są powiązane z tablicą o rozmiarze równym wartości SQL_ATTR_ROW_ARRAY_SIZE. Wywołuje także SQLBindCol , aby przypisać kolumnę 0 (kolumnę zakładek).
Kopiuje zakładki wierszy, które chce zaktualizować, do tablicy powiązanej z kolumną 0.
Aktualizuje dane w powiązanych buforach.
Note
Rozmiar tablicy wskazanej przez atrybut SQL_ATTR_ROW_STATUS_PTR powinien być SQL_ATTR_ROW_ARRAY_SIZE lub SQL_ATTR_ROW_STATUS_PTR powinien być wskaźnikiem zerowym.
Wywołuje SQLBulkOperations(StatementHandle, SQL_UPDATE_BY_BOOKMARK).
Note
Jeśli aplikacja ustawiła atrybut SQL_ATTR_ROW_STATUS_PTR instrukcji, może przejrzeć tę tablicę, aby zobaczyć wynik operacji.
Opcjonalnie wywołuje SQLBulkOperations(StatementHandle, SQL_FETCH_BY_BOOKMARK), aby pobrać dane do buforów aplikacji powiązanych i potwierdzić, że aktualizacja została dokonana.
Jeśli dane zostały zaktualizowane, sterownik zmienia wartość w tablicy statusu wiersza dla odpowiednich wierszy na SQL_ROW_UPDATED.
Aktualizacje masowe wykonywane przez SQLBulkOperations mogą zawierać długie dane poprzez wywołania SQLParamData i SQLPutData. Więcej informacji można znaleźć w artykule "Dostarczanie długich danych dla wstawiania i aktualizacji masowych" później w tej funkcji.
Jeśli zakładki pozostają na kursorach, aplikacja nie musi wywoływać SQLFetch ani SQLFetchScroll przed aktualizacją zakładek. Może korzystać z zakładek zapisanych z poprzedniego kursora. Jeśli zakładki nie pozostają na kursorach, aplikacja musi wywołać SQLFetch lub SQLFetchScroll , aby pobrać zakładki.
Zachowanie jest definiowane sterownikiem, jeśli SQLBulkOperations, z argumentem Operation SQL_UPDATE_BY_BOOKMARK, jest wywoływane na kursorze zawierającym zduplikowane kolumny. Sterownik może zwracać zdefiniowany przez sterownik stan SQL, aktualizować pierwszą kolumnę pojawiającą się w zbiorze wyników lub wykonywać inne zachowania zdefiniowane przez sterownik.
Wykonywanie zbiorczego pobierania za pomocą zakładek
Aby wykonać zbiorcze pobieranie z użyciem zakładek z SQLBulkOperations, aplikacja wykonuje następujące kroki w kolejności:
Ustawia atrybut SQL_ATTR_USE_BOOKMARKS na SQL_UB_VARIABLE.
Wykonuje zapytanie, które zwraca zbiór wyników.
Ustawia atrybut SQL_ATTR_ROW_ARRAY_SIZE instrukcji na liczbę wierszy, które chce pobrać.
Wywołuje SQLBindCol , aby powiązać dane, które chce pobrać. Dane są powiązane z tablicą o rozmiarze równym wartości SQL_ATTR_ROW_ARRAY_SIZE. Wywołuje także SQLBindCol , aby przypisać kolumnę 0 (kolumnę zakładek).
Kopiuje zakładki wierszy, które chce pobrać, do tablicy powiązanej z kolumną 0. (Zakłada to, że aplikacja już osobno otrzymała zakładki.)
Note
Rozmiar tablicy wskazanej przez atrybut SQL_ATTR_ROW_STATUS_PTR powinien być SQL_ATTR_ROW_ARRAY_SIZE lub SQL_ATTR_ROW_STATUS_PTR powinien być wskaźnikiem zerowym.
Wywołuje SQLBulkOperations(StatementHandle, SQL_FETCH_BY_BOOKMARK).
Jeśli aplikacja ustawiła atrybut SQL_ATTR_ROW_STATUS_PTR instrukcji, może przejrzeć tę tablicę, aby zobaczyć wynik operacji.
Jeśli zakładki pozostają na kursorach, aplikacja nie musi wywoływać SQLFetch ani SQLFetchScroll przed pobraniem przez zakładki. Może korzystać z zakładek zapisanych z poprzedniego kursora. Jeśli zakładki nie pozostają na kursorach, aplikacja musi raz wywołać SQLFetch lub SQLFetchScroll , aby pobrać zakładki.
Wykonywanie masowych usuwań za pomocą zakładek
Aby wykonać masowe usuwanie za pomocą zakładek w SQLBulkOperations, aplikacja wykonuje następujące kroki kolejno:
Ustawia atrybut SQL_ATTR_USE_BOOKMARKS na SQL_UB_VARIABLE.
Wykonuje zapytanie, które zwraca zbiór wyników.
Ustawia atrybut SQL_ATTR_ROW_ARRAY_SIZE instrukcji na liczbę wierszy, które chce usunąć.
Wywołuje SQLBindCol , aby przypisać kolumnę 0 (kolumnę zakładek).
Kopiuje zakładki wierszy, które chce usunąć, do tablicy powiązanej z kolumną 0.
Note
Rozmiar tablicy wskazanej przez atrybut SQL_ATTR_ROW_STATUS_PTR powinien być SQL_ATTR_ROW_ARRAY_SIZE lub SQL_ATTR_ROW_STATUS_PTR powinien być wskaźnikiem zerowym.
Wywołuje SQLBulkOperations(StatementHandle, SQL_DELETE_BY_BOOKMARK).
Jeśli aplikacja ustawiła atrybut SQL_ATTR_ROW_STATUS_PTR instrukcji, może przejrzeć tę tablicę, aby zobaczyć wynik operacji.
Jeśli zakładki pozostają na kursorach, aplikacja nie musi wywoływać SQLFetch ani SQLFetchScroll przed usuwaniem zakładek. Może korzystać z zakładek zapisanych z poprzedniego kursora. Jeśli zakładki nie pozostają na kursorach, aplikacja musi raz wywołać SQLFetch lub SQLFetchScroll , aby pobrać zakładki.
Dostarczanie długich danych dla wkładów i aktualizacji masowych
Długie dane mogą być dostarczane do masowych wstawiań i aktualizacji wykonywanych przez wywołania do SQLBulkOperations. Aby wstawić lub zaktualizować długie dane, aplikacja wykonuje następujące kroki oprócz tych opisanych w sekcjach "Wykonywanie zbiorowych wstawiań" oraz "Wykonywanie masowych aktualizacji za pomocą zakładek" wcześniej w tym temacie.
Gdy aplikacja wiąże dane za pomocą SQLBindCol, umieszcza wartość zdefiniowaną przez aplikację, taką jak numer kolumny, w buforze *TargetValuePtr dla kolumn danych przy wykonaniu. Wartość ta może być później użyta do identyfikacji kolumny.
Aplikacja umieszcza wynik makra SQL_LEN_DATA_AT_EXEC(length) w buforze *StrLen_or_IndPtr . Jeśli typ danych SQL w kolumnie to SQL_LONGVARBINARY, SQL_LONGVARCHAR lub długi typ danych specyficzny dla źródła danych, a sterownik zwraca "Y" dla SQL_NEED_LONG_DATA_LEN typu informacji w SQLGetInfo, długość to liczba bajtów danych do wysłania dla parametru; w przeciwnym razie musi być wartością nieujemną i jest ignorowana.
Gdy wywołane jest SQLBulkOperations , jeśli są kolumny danych podczas wykonywania, funkcja zwraca SQL_NEED_DATA i przechodzi do kroku 3, który następuje następująco. (Jeśli nie ma kolumn danych przy wykonaniu, proces jest zakończony.)
Aplikacja wywołuje SQLParamData , aby pobrać adres bufora *TargetValuePtr dla pierwszej przetworzonej kolumny danych przy wykonaniu. SQLParamData zwraca SQL_NEED_DATA. Aplikacja pobiera wartość zdefiniowaną przez aplikację z bufora *TargetValuePtr .
Note
Chociaż parametry danych przy wykonaniu przypominają kolumny danych w trakcie wykonywania, wartość zwracana przez SQLParamData jest inna dla każdej z nich.
Kolumny danych przy wykonaniu to kolumny w zestawie wierszy, dla których dane będą wysyłane wraz z SQLPutData po aktualizacji lub wstawieniu wiersza za pomocą SQLBulkOperations. Są powiązane z SQLBindCol. Wartość zwracana przez SQLParamData to adres wiersza w buforze *TargetValuePtr , który jest przetwarzany.
Aplikacja wywołuje SQLPutData jeden lub więcej razy, aby przesłać dane do kolumny. Potrzeba więcej niż jednego wywołania, jeśli wszystkie wartości danych nie mogą zostać zwrócone w buforze *TargetValuePtr określonym w SQLPutData; wielokrotne wywołania do SQLPutData dla tej samej kolumny są dozwolone tylko przy wysyłaniu danych znaku C do kolumny zawierającej typ danych znakowy, binarny lub specyficzny dla źródła danych, albo przy wysyłaniu danych binarnych C do kolumny zawierającej typ danych ze znakiem, binarnym lub specyficznym dla źródła danych.
Aplikacja ponownie wywołuje SQLParamData , aby zasygnalizować, że wszystkie dane zostały przesłane do kolumny.
Jeśli jest więcej kolumn danych podczas wykonywania, SQLParamData zwraca SQL_NEED_DATA oraz adres bufora TargetValuePtr dla kolejnej kolumny danych przy wykonywaniu danych, którą ma się przetworzyć. Aplikacja powtarza kroki 4 i 5.
Jeśli nie ma już kolumn danych przy wykonaniu, proces jest zakończony. Jeśli instrukcja została pomyślnie wykonana, SQLParamData zwraca SQL_SUCCESS lub SQL_SUCCESS_WITH_INFO; jeśli wykonanie się nie powiodło, zwraca SQL_ERROR. W tym momencie SQLParamData może zwracać dowolny stan SQL, który SQLBulkOperations może zwrócić.
Jeśli operacja zostanie anulowana lub wystąpi błąd w SQLParamData lub SQLPutData po tym, jak SQLBulkOperations zwróci SQL_NEED_DATA i przed wysłaniem danych dla wszystkich kolumn danych przy wykonaniu, aplikacja może wywołać tylko SQLCancel, SQLGetDiagField, SQLGetDiagRec, SQLGetFunctions, SQLParamData lub SQLPutData dla polecenia lub połączenia powiązanego z tym zadaniem. Jeśli wywoła inną funkcję dla polecenia lub powiązania z tym zdaniem, funkcja zwraca SQL_ERROR oraz SQLSTATE HY010 (błąd sekwencji funkcji).
Jeśli aplikacja wywołuje SQLCancel , gdy sterownik nadal potrzebuje danych dla kolumn danych podczas wykonywania, sterownik anuluje operację. Aplikacja może następnie ponownie wywołać SQLBulkOperations ; Anulowanie nie wpływa na stan kursora ani na aktualną pozycję kursora.
Tablica stanu wiersza
Tablica statusów wiersza zawiera wartości statusu dla każdego wiersza danych w zestawie wierszy po wywołaniu do SQLBulkOperations. Sterownik ustawia wartości statusu w tej tablicy po wywołaniu do SQLFetch, SQLFetchScroll, SQLSetPos lub SQLBulkOperations. Ta tablica jest początkowo wypełniana wywołaniem do SQLBulkOperations , jeśli SQLFetch lub SQLFetchScroll nie zostały wywołane przed SQLBulkOperations. Na tę tablicę wskazuje atrybut SQL_ATTR_ROW_STATUS_PTR statement. Liczba elementów w tablicach statusu wiersza musi być równa liczbie wierszy w zestawie wierszy (zgodnie z atrybutem SQL_ATTR_ROW_ARRAY_SIZE instrukcji). Aby uzyskać informacje o tej tablicy statusu wiersza, zobacz SQLFetch.
Przykład kodu
Poniższy przykład pobiera 10 wierszy danych naraz z tabeli Klienci. Następnie użytkownik prosi o podjęcie działania. Aby zmniejszyć ruch sieciowy, przykład bufora aktualizuje, usuwa i wstawia lokalnie w powiązanych tablicach, ale z przesunięciami poza dane wiersza. Gdy użytkownik zdecyduje się wysłać aktualizacje, usunąć i wstawić do źródła danych, kod odpowiednio ustawia przesunięcie wiązania i wywołuje SQLBulkOperations. Dla uproszczenia użytkownik nie może buforować więcej niż 10 aktualizacji, usuwań lub wstawiań.
// SQLBulkOperations_Function.cpp
// compile with: ODBC32.lib
#include <windows.h>
#include <sqlext.h>
#include "stdio.h"
#define UPDATE_ROW 100
#define DELETE_ROW 101
#define ADD_ROW 102
#define SEND_TO_DATA_SOURCE 103
#define UPDATE_OFFSET 10
#define INSERT_OFFSET 20
#define DELETE_OFFSET 30
// Define structure for customer data (assume 10 byte maximum bookmark size).
typedef struct tagCustStruct {
SQLCHAR Bookmark[10];
SQLINTEGER BookmarkLen;
SQLUINTEGER CustomerID;
SQLINTEGER CustIDInd;
SQLCHAR CompanyName[51];
SQLINTEGER NameLenOrInd;
SQLCHAR Address[51];
SQLINTEGER AddressLenOrInd;
SQLCHAR Phone[11];
SQLINTEGER PhoneLenOrInd;
} CustStruct;
// Allocate 40 of these structures. Elements 0-9 are for the current rowset,
// elements 10-19 are for the buffered updates, elements 20-29 are for
// the buffered inserts, and elements 30-39 are for the buffered deletes.
CustStruct CustArray[40];
SQLUSMALLINT RowStatusArray[10], Action, RowNum, NumUpdates = 0, NumInserts = 0,
NumDeletes = 0;
SQLLEN BindOffset = 0;
SQLRETURN retcode;
SQLHENV henv = NULL;
SQLHDBC hdbc = NULL;
SQLHSTMT hstmt = NULL;
int main() {
retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER*)SQL_OV_ODBC3, 0);
retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
retcode = SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);
retcode = SQLConnect(hdbc, (SQLCHAR*) "Northwind", SQL_NTS, (SQLCHAR*) NULL, 0, NULL, 0);
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
// Set the following statement attributes:
// SQL_ATTR_CURSOR_TYPE: Keyset-driven
// SQL_ATTR_ROW_BIND_TYPE: Row-wise
// SQL_ATTR_ROW_ARRAY_SIZE: 10
// SQL_ATTR_USE_BOOKMARKS: Use variable-length bookmarks
// SQL_ATTR_ROW_STATUS_PTR: Points to RowStatusArray
// SQL_ATTR_ROW_BIND_OFFSET_PTR: Points to BindOffset
retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER)SQL_CURSOR_KEYSET_DRIVEN, 0);
retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_BIND_TYPE, (SQLPOINTER)sizeof(CustStruct), 0);
retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)10, 0);
retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_USE_BOOKMARKS, (SQLPOINTER)SQL_UB_VARIABLE, 0);
retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_STATUS_PTR, RowStatusArray, 0);
retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_BIND_OFFSET_PTR, &BindOffset, 0);
// Bind arrays to the bookmark, CustomerID, CompanyName, Address, and Phone columns.
retcode = SQLBindCol(hstmt, 0, SQL_C_VARBOOKMARK, CustArray[0].Bookmark, sizeof(CustArray[0].Bookmark), &CustArray[0].BookmarkLen);
retcode = SQLBindCol(hstmt, 1, SQL_C_ULONG, &CustArray[0].CustomerID, 0, &CustArray[0].CustIDInd);
retcode = SQLBindCol(hstmt, 2, SQL_C_CHAR, CustArray[0].CompanyName, sizeof(CustArray[0].CompanyName), &CustArray[0].NameLenOrInd);
retcode = SQLBindCol(hstmt, 3, SQL_C_CHAR, CustArray[0].Address, sizeof(CustArray[0].Address), &CustArray[0].AddressLenOrInd);
retcode = SQLBindCol(hstmt, 4, SQL_C_CHAR, CustArray[0].Phone, sizeof(CustArray[0].Phone), &CustArray[0].PhoneLenOrInd);
// Execute a statement to retrieve rows from the Customers table.
retcode = SQLExecDirect(hstmt, (SQLCHAR*)"SELECT CustomerID, CompanyName, Address, Phone FROM Customers", SQL_NTS);
// Fetch and display the first 10 rows.
retcode = SQLFetchScroll(hstmt, SQL_FETCH_NEXT, 0);
// DisplayCustData(CustArray, 10);
// Call GetAction to get an action and a row number from the user.
// while (GetAction(&Action, &RowNum)) {
Action = SQL_FETCH_NEXT;
RowNum = 2;
switch (Action) {
case SQL_FETCH_NEXT:
case SQL_FETCH_PRIOR:
case SQL_FETCH_FIRST:
case SQL_FETCH_LAST:
case SQL_FETCH_ABSOLUTE:
case SQL_FETCH_RELATIVE:
// Fetch and display the requested data.
SQLFetchScroll(hstmt, Action, RowNum);
// DisplayCustData(CustArray, 10);
break;
case UPDATE_ROW:
// Check if we have reached the maximum number of buffered updates.
if (NumUpdates < 10) {
// Get the new customer data and place it in the next available element of
// the buffered updates section of CustArray, copy the bookmark of the row
// being updated to the same element, and increment the update counter.
// Checking to see we have not already buffered an update for this
// row not shown.
// GetNewCustData(CustArray, UPDATE_OFFSET + NumUpdates);
memcpy(CustArray[UPDATE_OFFSET + NumUpdates].Bookmark,
CustArray[RowNum - 1].Bookmark,
CustArray[RowNum - 1].BookmarkLen);
CustArray[UPDATE_OFFSET + NumUpdates].BookmarkLen =
CustArray[RowNum - 1].BookmarkLen;
NumUpdates++;
} else {
printf("Buffers full. Send buffered changes to the data source.");
}
break;
case DELETE_ROW:
// Check if we have reached the maximum number of buffered deletes.
if (NumDeletes < 10) {
// Copy the bookmark of the row being deleted to the next available element
// of the buffered deletes section of CustArray and increment the delete
// counter. Checking to see we have not already buffered an update for
// this row not shown.
memcpy(CustArray[DELETE_OFFSET + NumDeletes].Bookmark,
CustArray[RowNum - 1].Bookmark,
CustArray[RowNum - 1].BookmarkLen);
CustArray[DELETE_OFFSET + NumDeletes].BookmarkLen =
CustArray[RowNum - 1].BookmarkLen;
NumDeletes++;
} else
printf("Buffers full. Send buffered changes to the data source.");
break;
case ADD_ROW:
// reached maximum number of buffered inserts?
if (NumInserts < 10) {
// Get the new customer data and place it in the next available element of
// the buffered inserts section of CustArray and increment insert counter.
// GetNewCustData(CustArray, INSERT_OFFSET + NumInserts);
NumInserts++;
} else
printf("Buffers full. Send buffered changes to the data source.");
break;
case SEND_TO_DATA_SOURCE:
// If there are any buffered updates, inserts, or deletes, set the array size
// to that number, set the binding offset to use the data in the buffered
// update, insert, or delete part of CustArray, and call SQLBulkOperations to
// do the updates, inserts, or deletes. Because we will never have more than
// 10 updates, inserts, or deletes, we can use the same row status array.
if (NumUpdates) {
SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)NumUpdates, 0);
BindOffset = UPDATE_OFFSET * sizeof(CustStruct);
SQLBulkOperations(hstmt, SQL_UPDATE_BY_BOOKMARK);
NumUpdates = 0;
}
if (NumInserts) {
SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)NumInserts, 0);
BindOffset = INSERT_OFFSET * sizeof(CustStruct);
SQLBulkOperations(hstmt, SQL_ADD);
NumInserts = 0;
}
if (NumDeletes) {
SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)NumDeletes, 0);
BindOffset = DELETE_OFFSET * sizeof(CustStruct);
SQLBulkOperations(hstmt, SQL_DELETE_BY_BOOKMARK);
NumDeletes = 0;
}
// If there were any updates, inserts, or deletes, reset the binding offset
// and array size to their original values.
if (NumUpdates || NumInserts || NumDeletes) {
SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)10, 0);
BindOffset = 0;
}
break;
}
// }
// Close the cursor.
SQLFreeStmt(hstmt, SQL_CLOSE);
}
Powiązane funkcje
| Aby uzyskać informacje o | Zobacz |
|---|---|
| Wiązanie buforu z kolumną w zestawie wyników | SQLBindCol, funkcja |
| Anulowanie przetwarzania instrukcji | SQLCancel, funkcja |
| Pobieranie bloku danych lub przewijanie zestawu wyników | SQLFetchScroll, funkcja |
| Uzyskanie pojedynczego pola deskryptora | Funkcja SQLGetDescField |
| Uzyskanie wielu pól deskryptora | Funkcja SQLGetDescRec |
| Ustawianie pojedynczego pola deskryptora | Funkcja SQLSetDescField |
| Ustawianie wielu pól deskryptora | Funkcja SQLSetDescRec |
| Ustawianie kursora, odświeżanie danych w zestawie wierszy lub aktualizowanie lub usuwanie danych w zestawie wierszy | Funkcja SQLSetPos |
| Ustawianie atrybutu instrukcji | SQLSetStmtAttr, funkcja |