Getting Long Data
Note 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. However, 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.
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. The application then
calls SQLGetData. 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. The
major differences are that SQLGetData is called after a row is fetched (and is sometimes called late binding for this reason), and that the binding specified by SQLGetData only lasts for the duration of the call.
With respect to a single column, SQLGetData behaves in the same manner as 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. For more information on how SQLFetch returns data, see the immediately preceding section,
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);
If the application does not need all of 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 only need to
display the first page of each document. Although this statement attribute can be
simulated in the driver, there is no reason to do so. 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.
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). 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. 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 be careful to place long
data columns at the end of the select list.
Cannot be used if SQLFetch or SQLFetchScroll was called to retrieve more than one row. For more information, see