Udostępnij przez


Uzyskiwanie długich danych

Zestawy DBMS definiują dane długie jako dowolne znaki lub dane binarne o określonym rozmiarze, takie jak 255 znaków. Te dane mogą być wystarczająco małe, aby być przechowywane w jednym buforze, takim jak opis części zawierający kilka tysięcy znaków. Jednak przechowywanie w pamięci może być zbyt długie, na przykład długich dokumentów tekstowych lub map bitowych. Ponieważ takie dane nie mogą być przechowywane w jednym buforze, są pobierane ze sterownika w częściach za pomocą funkcji SQLGetData po pobraniu innych danych w wierszu.

Uwaga / Notatka

Aplikacja może pobrać dowolny typ danych przy użyciu SQLGetData, nie tylko danych długich, chociaż tylko dane znakowe i binarne można pobrać częściowo. Jeśli jednak dane są wystarczająco małe, aby zmieściły się w jednym buforze, zazwyczaj nie ma powodu, aby używać danych SQLGetData. Znacznie łatwiej jest powiązać bufor z kolumną i pozwolić sterownikowi zwrócić dane w buforze.

Aby pobrać długie dane z kolumny, aplikacja najpierw wywołuje funkcję SQLFetchScroll lub SQLFetch , aby przejść do wiersza i pobrać dane dla powiązanych kolumn. Następnie aplikacja wywołuje metodę SQLGetData. SqlGetData ma te same argumenty co SQLBindCol: uchwyt instrukcji; numer kolumny; typ danych języka C, adres i długość bajtu zmiennej aplikacji; oraz adres bufora długości/wskaźnika. Obie funkcje mają te same argumenty, ponieważ wykonują zasadniczo to samo zadanie: obie opisują zmienną aplikacji dla sterownika i określają, że dane dla określonej kolumny powinny być zwracane w tej zmiennej. Główne różnice polegają na tym, że funkcja SQLGetData jest wywoływana po pobraniu wiersza (i czasami jest nazywana późnym powiązaniem z tego powodu) i że powiązanie określone przez funkcję SQLGetData trwa tylko przez czas trwania wywołania.

Jeśli chodzi o jedną kolumnę, funkcja SQLGetData zachowuje się jak SQLFetch: pobiera dane dla kolumny, konwertuje ją na typ zmiennej aplikacji i zwraca ją w tej zmiennej. Zwraca również długość bajtu danych w buforze długości/wskaźnika. Aby uzyskać więcej informacji na temat sposobu zwracania danych przez funkcję SQLFetch , zobacz Pobieranie wiersza danych.

Funkcja SQLGetData różni się od funkcji SQLFetch pod jednym ważnym względem. Jeśli jest wywoływana więcej niż raz z rzędu dla tej samej kolumny, każde wywołanie zwraca kolejną część danych. Każde wywołanie z wyjątkiem ostatniego wywołania zwraca SQL_SUCCESS_WITH_INFO i SQLSTATE 01004 (dane tekstowe, przycięte z prawej strony); ostatnie wywołanie zwraca SQL_SUCCESS. W ten sposób funkcja SQLGetData służy do pobierania długich danych w częściach. Gdy nie ma więcej danych do zwrócenia, funkcja SQLGetData zwraca SQL_NO_DATA. Aplikacja jest odpowiedzialna za łączenie długich danych, co może oznaczać łączenie części danych. Każda część jest zakończona znakiem null; aplikacja musi usunąć znak null podczas łączenia części. Pobieranie danych w częściach można wykonywać w przypadku zakładek o zmiennej długości, a także innych długich danych. Wartość zwrócona w buforze długości/wskaźnika zmniejsza się w każdym wywołaniu o liczbę bajtów zwróconych w poprzednim wywołaniu, chociaż sterownik często nie może odnaleźć ilości dostępnych danych i zwrócić długość bajtu SQL_NO_TOTAL. Przykład:

// Declare a binary buffer to retrieve 5000 bytes of data at a time.  
SQLCHAR       BinaryPtr[5000];  
SQLUINTEGER   PartID;  
SQLINTEGER    PartIDInd, BinaryLenOrInd, NumBytes;  
SQLRETURN     rc;   
SQLHSTMT      hstmt;  
  
// Create a result set containing the ID and picture of each part.  
SQLExecDirect(hstmt, "SELECT PartID, Picture FROM Pictures", SQL_NTS);  
  
// Bind PartID to the PartID column.  
SQLBindCol(hstmt, 1, SQL_C_ULONG, &PartID, 0, &PartIDInd);  
  
// Retrieve and display each row of data.  
while ((rc = SQLFetch(hstmt)) != SQL_NO_DATA) {  
   // Display the part ID and initialize the picture.  
   DisplayID(PartID, PartIDInd);  
   InitPicture();  
  
   // Retrieve the picture data in parts. Send each part and the number   
   // of bytes in each part to a function that displays it. The number   
   // of bytes is always 5000 if there were more than 5000 bytes   
   // available to return (cbBinaryBuffer > 5000). Code to check if   
   // rc equals SQL_ERROR or SQL_SUCCESS_WITH_INFO not shown.  
   while ((rc = SQLGetData(hstmt, 2, SQL_C_BINARY, BinaryPtr, sizeof(BinaryPtr),  
                           &BinaryLenOrInd)) != SQL_NO_DATA) {  
      NumBytes = (BinaryLenOrInd > 5000) || (BinaryLenOrInd == SQL_NO_TOTAL) ?  
                  5000 : BinaryLenOrInd;  
      DisplayNextPictPart(BinaryPtr, NumBytes);  
   }  
}  
  
// Close the cursor.  
SQLCloseCursor(hstmt);  

Istnieje kilka ograniczeń dotyczących używania funkcji SQLGetData. Ogólnie rzecz biorąc, kolumny, do których uzyskiwano dostęp za pomocą polecenia SQLGetData:

  • Musi być dostępny w celu zwiększenia liczby kolumn (ze względu na sposób odczytywania kolumn zestawu wyników ze źródła danych). Na przykład jest to błąd wywołania metody SQLGetData dla kolumny 5, a następnie wywołania jej dla kolumny 4.

  • Nie można powiązać.

  • Musi mieć większą liczbę kolumn niż ostatnia powiązana kolumna. Jeśli na przykład ostatnia powiązana kolumna to kolumna 3, jest to błąd podczas wywoływania danych SQLGetData dla kolumny 2. Z tego powodu aplikacje powinny umieścić długie kolumny danych na końcu listy wyboru.

  • Nie można użyć, jeśli wywołano funkcję SQLFetch lub SQLFetchScroll w celu pobrania więcej niż jednego wiersza. Aby uzyskać więcej informacji, zobacz Używanie kursorów blokowych.

Niektóre sterowniki nie wymuszają tych ograniczeń. Aplikacje współdziałające powinny zakładać, że istnieją lub określić, które ograniczenia nie są wymuszane przez wywołanie polecenia SQLGetInfo z opcją SQL_GETDATA_EXTENSIONS.

Jeśli aplikacja nie potrzebuje wszystkich danych w postaci lub kolumnie danych binarnych, może zmniejszyć ruch sieciowy w sterownikach opartych na systemie DBMS, ustawiając atrybut instrukcji SQL_ATTR_MAX_LENGTH przed wykonaniem instrukcji. Ogranicza to liczbę bajtów danych, które zostaną zwrócone dla dowolnego znaku lub kolumny binarnej. Załóżmy na przykład, że kolumna zawiera długie dokumenty tekstowe. Aplikacja, która przegląda tabelę zawierającą tę kolumnę, może potrzebować wyświetlać tylko pierwszą stronę każdego dokumentu. Mimo że ten atrybut instrukcji można symulować w sterowniku, nie ma powodu, aby to zrobić. W szczególności jeśli aplikacja chce obcinać znaki lub dane binarne, powinna powiązać mały bufor z kolumną za pomocą metody SQLBindCol i pozwolić sterownikowi na obcięcie danych.