Поделиться через


Получение данных типа Long

DBMS определяет длинные данные как любые символы или двоичные данные с определенным размером, например 255 символов. Эти данные могут быть достаточно маленькими, чтобы храниться в одном буфере, например описание нескольких тысяч символов. Однако может быть слишком долго храниться в памяти, например длинные текстовые документы или растровые изображения. Так как эти данные не могут храниться в одном буфере, он извлекается из драйвера в частях с SQLGetData после получения других данных в строке.

Примечание.

Приложение может фактически извлекать любые типы данных с помощью SQLGetData, а не только длинных данных, хотя только символьные и двоичные данные можно получить в частях. Однако если данные достаточно малы для размещения в одном буфере, обычно нет причин использовать SQLGetData. Гораздо проще привязать буфер к столбцу и позволить драйверу возвращать данные в буфере.

Чтобы получить длинные данные из столбца, приложение сначала вызывает SQLFetchScroll или SQLFetch , чтобы перейти к строке и получить данные для привязанных столбцов. Затем приложение вызывает SQLGetData. SQLGetData имеет те же аргументы, что и SQLBindCol: дескриптор инструкции; номер столбца; тип данных C, адрес и длина байтов переменной приложения; и адрес буфера длины или индикатора. Обе функции имеют одинаковые аргументы, так как они выполняют по сути одну и ту же задачу: они описывают переменную приложения драйверу и указывают, что данные для определенного столбца должны быть возвращены в этой переменной. Основные различия заключается в том, что SQLGetData вызывается после получения строки (и иногда называется поздней привязкой по этой причине) и что привязка, указанная SQLGetData , длится только в течение длительности вызова.

В отношении одного столбца SQLGetData ведет себя как SQLFetch: получает данные для столбца, преобразует его в тип переменной приложения и возвращает его в этой переменной. Он также возвращает длину байтов данных в буфере длины или индикатора. Дополнительные сведения о том, как SQLFetch возвращает данные, см. в разделе "Получение строки данных".

SQLGetData отличается от SQLFetch в одном важном отношении. Если он вызывается несколько раз в последовательности для одного столбца, каждый вызов возвращает последовательную часть данных. Каждый вызов, кроме последнего вызова, возвращает SQL_SUCCESS_WITH_INFO и SQLSTATE 01004 (строковые данные, усеченные справа); Последний вызов возвращает SQL_SUCCESS. Вот как SQLGetData используется для получения длинных данных в частях. Если нет дополнительных данных для возврата, SQLGetData возвращает SQL_NO_DATA. Приложение отвечает за объединение длинных данных, что может означать объединение частей данных. Каждая часть завершается с пустым завершением; Приложение должно удалить символ завершения null, если сцеплять части. Получение данных в частях можно сделать для закладок переменной длины, а также для других длинных данных. Значение, возвращаемое в буфере длины или индикатора, уменьшается по количеству байтов, возвращенных в предыдущем вызове, хотя обычно драйверу не удается обнаружить объем доступных данных и вернуть длину байтов SQL_NO_TOTAL. Например:

// 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);  

Существует несколько ограничений на использование SQLGetData. Как правило, столбцы, к которым обращается SQLGetData:

  • Доступ к ним должен осуществляться в порядке увеличения числа столбцов (из-за того, как столбцы результирующего набора считываются из источника данных). Например, это ошибка для вызова SQLGetData для столбца 5, а затем вызвать его для столбца 4.

  • Не удается привязать.

  • Должен иметь более высокий номер столбца, чем последний привязанный столбец. Например, если последний привязанный столбец равен столбцу 3, это ошибка при вызове SQLGetData для столбца 2. По этой причине приложения должны размещать длинные столбцы данных в конце списка выбора.

  • Невозможно использовать, если для получения нескольких строк вызывается SQLFetch или SQLFetchScroll. Дополнительные сведения см. в разделе "Использование блоковых курсоров".

Некоторые драйверы не применяют эти ограничения. Приложения, взаимодействующие между собой, должны предполагать, что они существуют или определяют, какие ограничения не применяются путем вызова SQLGetInfo с параметром SQL_GETDATA_EXTENSIONS.

Если приложению не нужны все данные в символьном или двоичном столбце данных, он может уменьшить сетевой трафик в драйверах на основе СУБД, задав атрибут инструкции SQL_ATTR_MAX_LENGTH перед выполнением инструкции. Это ограничивает количество байтов данных, возвращаемых для любого символа или двоичного столбца. Например, предположим, что столбец содержит длинные текстовые документы. Приложение, которое просматривает таблицу, содержащую этот столбец, может потребоваться отобразить только первую страницу каждого документа. Хотя этот атрибут инструкции можно имитировать в драйвере, нет причин для этого. В частности, если приложение хочет усечь символ или двоичные данные, оно должно привязать небольшой буфер к столбцу с помощью SQLBindCol и позволить драйверу усечь данные.