获取 Long 数据Getting Long Data

定义 Dbms长整型数据为任何字符或二进制数据而非特定大小,如 255 个字符。DBMSs define long data as any character or binary data over a certain size, such as 255 characters. 此数据可能很小,可存储在一个缓冲区,例如一部分描述的多个几千个字符。This data may be small enough to be stored in a single buffer, such as a part description of several thousand characters. 但是,它可能太长,无法存储在内存中,如长文本文档或位图。However, it might be too long to store in memory, such as long text documents or bitmaps. 由于此类数据不能存储在一个缓冲区,将从使用部件中的驱动程序中检索SQLGetData已提取的行中的其他数据之后。Because such data cannot be stored in a single buffer, it is retrieved from the driver in parts with SQLGetData after the other data in the row has been fetched.

备注

应用程序可以实际检索任何类型的数据与SQLGetData,而不仅仅是长数据,尽管可以在部件中检索仅字符和二进制数据。An application can actually retrieve any type of data with SQLGetData, not just long data, although only character and binary data can be retrieved in parts. 但是,如果数据是足够小,无法全部放入一个缓冲区,则通常无需使用SQLGetDataHowever, if the data is small enough to fit in a single buffer, there is generally no reason to use SQLGetData. 它是更轻松地将缓冲区绑定到的列和让驱动程序在缓冲区中返回数据。It is much easier to bind a buffer to the column and let the driver return the data in the buffer.

若要从一列中检索的长整型数据,应用程序首先调用SQLFetchScrollSQLFetch移动到某一行并提取对于绑定列的数据。To retrieve long data from a column, an application first calls SQLFetchScroll or SQLFetch to move to a row and fetch the data for bound columns. 然后,应用程序调用SQLGetDataThe application then calls SQLGetData. SQLGetData具有相同的参数SQLBindCol: 语句句柄; 列号; 应用程序变量; 的 C 数据类型、 地址和字节长度和长度/指示器缓冲区的地址。SQLGetData has the same arguments as SQLBindCol: a statement handle; a column number; the C data type, address, and byte length of an application variable; and the address of a length/indicator buffer. 这两个函数具有相同的参数,因为它们执行实质上是相同的任务:它们都描述向驱动程序应用程序变量,并指定应在该变量中返回的特定列的数据。Both functions have the same arguments because they perform essentially the same task: They both describe an application variable to the driver and specify that the data for a particular column should be returned in that variable. 主要区别是SQLGetData提取行后,将调用 (有时称为后期绑定出于此原因),并且该绑定指定由SQLGetData在调用期间持续。The major differences are that SQLGetData is called after a row is fetched (and is sometimes referred to as late binding for this reason) and that the binding specified by SQLGetData lasts only for the duration of the call.

有关单个列SQLGetData的行为类似于SQLFetch:它检索列的数据、 将其转换为应用程序变量的类型并将其返回该变量中。Regarding a single column, SQLGetData behaves like SQLFetch: It retrieves the data for the column, converts it to the type of the application variable, and returns it in that variable. 它还返回长度/指示器缓冲区中的数据的字节长度。It also returns the byte length of the data in the length/indicator buffer. 详细了解如何SQLFetch返回的数据,请参阅提取行数据For more information about how SQLFetch returns data, see Fetching a Row of Data.

SQLGetData不同于SQLFetch一个重要方面。SQLGetData differs from SQLFetch in one important respect. 如果调用一次连续的同一列,每个调用将返回连续数据的一部分。If it is called more than once in succession for the same column, each call returns a successive part of the data. 除最后一次调用每个调用将返回 SQL_SUCCESS_WITH_INFO 和 SQLSTATE 01004 (字符串数据,右端被截断);最后一次调用都返回 SQL_SUCCESS。Each call except the last call returns SQL_SUCCESS_WITH_INFO and SQLSTATE 01004 (String data, right truncated); the last call returns SQL_SUCCESS. 这是如何SQLGetData用于检索部分中的长整型数据。This is how SQLGetData is used to retrieve long data in parts. 若要返回,没有更多数据时SQLGetData返回 sql_no_data 为止。When there is no more data to return, SQLGetData returns SQL_NO_DATA. 应用程序负责将长数据组合在一起,这可能意味着串联的数据部分。The application is responsible for putting the long data together, which might mean concatenating the parts of the data. 每个部分是以 null 结尾;如果串联部件,该应用程序必须删除的 null 终止字符。Each part is null-terminated; the application must remove the null-termination character if concatenating the parts. 检索部分中的数据可能会出于长度可变的书签以及与其他长整型数据。Retrieving data in parts can be done for variable-length bookmarks as well as for other long data. 虽然很常见的驱动程序不能发现可用的数据量并返回 SQL_NO_TOTAL 字节长度长度/指示器缓冲区减少在每次调用中返回通过在上一个调用中,返回的字节数的值。The value returned in the length/indicator buffer decreases in each call by the number of bytes returned in the previous call, although it is common for the driver to be unable to discover the amount of available data and return a byte length of SQL_NO_TOTAL. 例如:For example:

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

使用的几项限制SQLGetDataThere are several restrictions on using SQLGetData. 通常情况下,与访问列SQLGetData:Generally, columns accessed with SQLGetData:

  • 必须按顺序列号递增 (由于从数据源中读取的结果集列的方式) 的访问。Must be accessed in order of increasing column number (because of the way the columns of a result set are read from the data source). 例如,它是错误调用SQLGetData为第 5 列,然后调用它的第 4 列。For example, it is an error to call SQLGetData for column 5 and then call it for column 4.

  • 无法绑定。Cannot be bound.

  • 必须具有更高版本的列号比最后一个绑定列。Must have a higher column number than the last bound column. 例如,如果最后一个绑定的列是第 3 列,它是调用错误SQLGetData有关第 2 列。For example, if the last bound column is column 3, it is an error to call SQLGetData for column 2. 出于此原因,应用程序应确保在选择列表的末尾放置的长整型数据列。For this reason, applications should make sure to place long data columns at the end of the select list.

  • 如果不能使用SQLFetchSQLFetchScroll已调用以检索多个行。Cannot be used if SQLFetch or SQLFetchScroll was called to retrieve more than one row. 有关详细信息,请参阅使用块状游标For more information, see Using Block Cursors.

某些驱动程序不会强制这些限制。Some drivers do not enforce these restrictions. 可互操作应用程序认为它们存在,或确定哪些限制不会通过调用强制执行SQLGetInfo SQL_GETDATA_EXTENSIONS 选项。Interoperable applications should either assume they exist or determine which restrictions are not enforced by calling SQLGetInfo with the SQL_GETDATA_EXTENSIONS option.

如果应用程序不需要的字符或二进制数据列中的所有数据,它可以通过执行语句前设置 SQL_ATTR_MAX_LENGTH 语句属性来减少基于 DBMS 的驱动程序中的网络流量。If the application does not need all the data in a character or binary data column, it can reduce network traffic in DBMS-based drivers by setting the SQL_ATTR_MAX_LENGTH statement attribute before executing the statement. 这会限制的任何字符或二进制列返回数据的字节数。This restricts the number of bytes of data that will be returned for any character or binary column. 例如,假设某个列包含长文本文档。For example, suppose a column contains long text documents. 浏览包含此列的表的应用程序可能需要显示仅每个文档的第一页。An application that browses the table containing this column might have to display only the first page of each document. 尽管可以在驱动程序中模拟此语句属性,但没有理由要这样做。Although this statement attribute can be simulated in the driver, there is no reason to do this. 具体而言,如果应用程序想要截断字符或二进制数据,它应将较小的缓冲区绑定到的列SQLBindCol ,并允许截断的数据的驱动程序。In particular, if an application wants to truncate character or binary data, it should bind a small buffer to the column with SQLBindCol and let the driver truncate the data.