SQLFetchScroll Function
Conformance
Version Introduced: ODBC 3.0 Standards Compliance: ISO 92
Summary
SQLFetchScroll fetches the specified rowset of data from the result set and returns data for all bound columns. Rowsets can be specified at an absolute or relative position or by bookmark.
When working with an ODBC 2.x driver, the Driver Manager maps this function to SQLExtendedFetch. For more information, see Mapping Replacement Functions for Backward Compatibility of Applications.
Syntax
SQLRETURN SQLFetchScroll(
SQLHSTMT StatementHandle,
SQLSMALLINT FetchOrientation,
SQLLEN FetchOffset);
Arguments
StatementHandle
[Input] Statement handle.
FetchOrientation
[Input]
Type of fetch:
SQL_FETCH_NEXT
SQL_FETCH_PRIOR
SQL_FETCH_FIRST
SQL_FETCH_LAST
SQL_FETCH_ABSOLUTE
SQL_FETCH_RELATIVE
SQL_FETCH_BOOKMARK
For more information, see "Positioning the Cursor" in the "Comments" section.
FetchOffset
[Input]
Number of the row to fetch. The interpretation of this argument depends on the value of the FetchOrientation argument. For more information, see "Positioning the Cursor" in the "Comments" section.
Returns
SQL_SUCCESS, SQL_SUCCESS_WITH_INFO, SQL_NO_DATA, SQL_STILL_EXECUTING, SQL_ERROR, or SQL_INVALID_HANDLE.
Diagnostics
When SQLFetchScroll returns either SQL_ERROR or SQL_SUCCESS_WITH_INFO, an associated SQLSTATE value can be obtained by calling SQLGetDiagRec with a HandleType of SQL_HANDLE_STMT and a Handle of StatementHandle. The following table lists the SQLSTATE values commonly returned by SQLFetchScroll and explains each one in the context of this function; the notation "(DM)" precedes the descriptions of SQLSTATEs returned by the Driver Manager. The return code associated with each SQLSTATE value is SQL_ERROR, unless noted otherwise. If an error occurs on a single column, SQLGetDiagField can be called with a DiagIdentifier of SQL_DIAG_COLUMN_NUMBER to determine the column the error occurred on; and SQLGetDiagField can be called with a DiagIdentifier of SQL_DIAG_ROW_NUMBER to determine the row containing that column.
For all those SQLSTATEs that can return SQL_SUCCESS_WITH_INFO or SQL_ERROR (except 01xxx SQLSTATEs), SQL_SUCCESS_WITH_INFO is returned if an error occurs on one or more, but not all, rows of a multirow operation, and SQL_ERROR is returned if an error occurs on a single-row operation.
SQLSTATE | Error | Description |
---|---|---|
01000 | General warning | Driver-specific informational message. (Function returns SQL_SUCCESS_WITH_INFO.) |
01004 | String data, right truncated | String or binary data returned for a column resulted in the truncation of nonblank character or non-NULL binary data. If it was a string value, it was right-truncated. |
01S01 | Error in row | An error occurred while fetching one or more rows. (If this SQLSTATE is returned when an ODBC 3*.x* application is working with an ODBC 2*.x* driver, it can be ignored.) |
01S06 | Attempt to fetch before the result set returned the first rowset | The requested rowset overlapped the start of the result set when FetchOrientation was SQL_FETCH_PRIOR, the current position was beyond the first row, and the number of the current row is less than or equal to the rowset size. The requested rowset overlapped the start of the result set when FetchOrientation was SQL_FETCH_PRIOR, the current position was beyond the end of the result set, and the rowset size was greater than the result set size. The requested rowset overlapped the start of the result set when FetchOrientation was SQL_FETCH_RELATIVE, FetchOffset was negative, and the absolute value of FetchOffset was less than or equal to the rowset size. The requested rowset overlapped the start of the result set when FetchOrientation was SQL_FETCH_ABSOLUTE, FetchOffset was negative, and the absolute value of FetchOffset was greater than the result set size but less than or equal to the rowset size. (Function returns SQL_SUCCESS_WITH_INFO.) |
01S07 | Fractional truncation | The data returned for a column was truncated. For numeric data types, the fractional part of the number was truncated. For time, timestamp, and interval data types containing a time component, the fractional portion of the time was truncated. (Function returns SQL_SUCCESS_WITH_INFO.) |
07006 | Restricted data type attribute violation | The data value of a column in the result set could not be converted to the data type specified by TargetType in SQLBindCol. Column 0 was bound with a data type of SQL_C_BOOKMARK, and the SQL_ATTR_USE_BOOKMARKS statement attribute was set to SQL_UB_VARIABLE. Column 0 was bound with a data type of SQL_C_VARBOOKMARK, and the SQL_ATTR_USE_BOOKMARKS statement attribute was not set to SQL_UB_VARIABLE. |
07009 | Invalid descriptor index | The driver was an ODBC 2*.x* driver that does not support SQLExtendedFetch, and a column number specified in the binding for a column was 0. Column 0 was bound, and the SQL_ATTR_USE_BOOKMARKS statement attribute was set to SQL_UB_OFF. |
08S01 | Communication link failure | The communication link between the driver and the data source to which the driver was connected failed before the function completed processing. |
22001 | String data, right truncated | A variable-length bookmark returned for a column was truncated. |
22002 | Indicator variable required but not supplied | NULL data was fetched into a column whose StrLen_or_IndPtr set by SQLBindCol (or SQL_DESC_INDICATOR_PTR set by SQLSetDescField or SQLSetDescRec) was a null pointer. |
22003 | Numeric value out of range | Returning the numeric value (as numeric or string) for one or more bound columns would have caused the whole (as opposed to fractional) part of the number to be truncated. For more information, see Converting Data from SQL to C Data Types in Appendix D: Data Types. |
22007 | Invalid datetime format | A character column in the result set was bound to a date, time, or timestamp C structure, and a value in the column was, respectively, an invalid date, time, or timestamp. |
22012 | Division by zero | A value from an arithmetic expression was returned, which resulted in division by zero. |
22015 | Interval field overflow | Assigning from an exact numeric or interval SQL type to an interval C type caused a loss of significant digits in the leading field. When fetching data to an interval C type, there was no representation of the value of the SQL type in the interval C type. |
22018 | Invalid character value for cast specification | A character column in the result set was bound to a character C buffer, and the column contained a character for which there was no representation in the character set of the buffer. The C type was an exact or approximate numeric, a datetime, or an interval data type; the SQL type of the column was a character data type; and the value in the column was not a valid literal of the bound C type. |
24000 | Invalid cursor state | The StatementHandle was in an executed state but no result set was associated with the StatementHandle. |
40001 | Serialization failure | The transaction in which the fetch was executed was terminated to prevent deadlock. |
40003 | Statement completion unknown | The associated connection failed during the execution of this function, and the state of the transaction cannot be determined. |
HY000 | General error | An error occurred for which there was no specific SQLSTATE and for which no implementation-specific SQLSTATE was defined. The error message returned by SQLGetDiagRec in the *MessageText buffer describes the error and its cause. |
HY001 | Memory allocation error | The driver was unable to allocate memory required to support execution or completion of the function. |
HY008 | Operation canceled | Asynchronous processing was enabled for the StatementHandle. The function was called, and before it completed execution, SQLCancel or SQLCancelHandle was called on the StatementHandle. Then the function was called again on the StatementHandle. The function was called, and before it completed execution, SQLCancel or SQLCancelHandle was called on the StatementHandle from a different thread in a multithread application. |
HY010 | Function sequence error | (DM) An asynchronously executing function was called for the connection handle that is associated with the StatementHandle. This asynchronous function was still executing when the SQLFetchScroll function was called. (DM) SQLExecute, SQLExecDirect, or SQLMoreResults was called for the StatementHandle and returned SQL_PARAM_DATA_AVAILABLE. This function was called before data was retrieved for all streamed parameters. (DM) The specified StatementHandle was not in an executed state. The function was called without first calling SQLExecDirect, SQLExecute or a catalog function. (DM) An asynchronously executing function (not this one) was called for the StatementHandle and was still executing when this function was called. (DM) SQLExecute, SQLExecDirect, SQLBulkOperations, or SQLSetPos was called for the StatementHandle and returned SQL_NEED_DATA. This function was called before data was sent for all data-at-execution parameters or columns. (DM) SQLFetch was called for the StatementHandle after SQLExtendedFetch was called and before SQLFreeStmt with the SQL_CLOSE option was called. |
HY013 | Memory management error | The function call could not be processed because the underlying memory objects could not be accessed, possibly because of low memory conditions. |
HY090 | Invalid string or buffer length | The SQL_ATTR_USE_BOOKMARK statement attribute was set to SQL_UB_VARIABLE, and column 0 was bound to a buffer whose length was not equal to the maximum length for the bookmark for this result set. (This length is available in the SQL_DESC_OCTET_LENGTH field of the IRD and can be obtained by calling SQLDescribeCol, SQLColAttribute, or SQLGetDescField.) |
HY106 | Fetch type out of range | DM) The value specified for the argument FetchOrientation was invalid. (DM) The argument FetchOrientation was SQL_FETCH_BOOKMARK, and the SQL_ATTR_USE_BOOKMARKS statement attribute was set to SQL_UB_OFF. The value of the SQL_ATTR_CURSOR_TYPE statement attribute was SQL_CURSOR_FORWARD_ONLY, and the value of argument FetchOrientation was not SQL_FETCH_NEXT. The value of the SQL_ATTR_CURSOR_SCROLLABLE statement attribute was SQL_NONSCROLLABLE, and the value of argument FetchOrientation was not SQL_FETCH_NEXT. |
HY107 | Row value out of range | The value specified with the SQL_ATTR_CURSOR_TYPE statement attribute was SQL_CURSOR_KEYSET_DRIVEN, but the value specified with the SQL_ATTR_KEYSET_SIZE statement attribute was greater than 0 and less than the value specified with the SQL_ATTR_ROW_ARRAY_SIZE statement attribute. |
HY111 | Invalid bookmark value | The argument FetchOrientation was SQL_FETCH_BOOKMARK, and the bookmark pointed to by the value in the SQL_ATTR_FETCH_BOOKMARK_PTR statement attribute was not valid or was a null pointer. |
HY117 | Connection is suspended due to unknown transaction state. Only disconnect and read-only functions are allowed. | (DM) For more information about suspended state, see SQLEndTran Function. |
HYC00 | Optional feature not implemented | The driver or data source does not support the conversion specified by the combination of the TargetType in SQLBindCol and the SQL data type of the corresponding column. |
HYT00 | Timeout expired | The query timeout period expired before the data source returned the requested result set. The timeout period is set through SQLSetStmtAttr, SQL_ATTR_QUERY_TIMEOUT. |
HYT01 | Connection timeout expired | The connection timeout period expired before the data source responded to the request. The connection timeout period is set through SQLSetConnectAttr, SQL_ATTR_CONNECTION_TIMEOUT. |
IM001 | Driver does not support this function | (DM) The driver associated with the StatementHandle does not support the function. |
IM017 | Polling is disabled in asynchronous notification mode | Whenever the notification model is used, polling is disabled. |
IM018 | SQLCompleteAsync has not been called to complete the previous asynchronous operation on this handle. | If the previous function call on the handle returns SQL_STILL_EXECUTING and if notification mode is enabled, SQLCompleteAsync must be called on the handle to do post-processing and complete the operation. |
Comments
SQLFetchScroll returns a specified rowset from the result set. Rowsets can be specified by absolute or relative position or by bookmark. SQLFetchScroll can be called only while a result set exists - that is, after a call that creates a result set and before the cursor over that result set is closed. If any columns are bound, it returns the data in those columns. If the application has specified a pointer to a row status array or a buffer in which to return the number of rows fetched, SQLFetchScroll returns this information as well. Calls to SQLFetchScroll can be mixed with calls to SQLFetch but cannot be mixed with calls to SQLExtendedFetch.
For more information, see Using Block Cursors and Using Scrollable Cursors.
Positioning the Cursor
When the result set is created, the cursor is positioned before the start of the result set. SQLFetchScroll positions the block cursor based on the values of the FetchOrientation and FetchOffset arguments as shown in the following table. The exact rules for determining the start of the new rowset are shown in the next section.
FetchOrientation | Meaning |
---|---|
SQL_FETCH_NEXT | Return the next rowset. This is equivalent to calling SQLFetch. SQLFetchScroll ignores the value of FetchOffset. |
SQL_FETCH_PRIOR | Return the prior rowset. SQLFetchScroll ignores the value of FetchOffset. |
SQL_FETCH_RELATIVE | Return the rowset FetchOffset from the start of the current rowset. |
SQL_FETCH_ABSOLUTE | Return the rowset starting at row FetchOffset. |
SQL_FETCH_FIRST | Return the first rowset in the result set. SQLFetchScroll ignores the value of FetchOffset. |
SQL_FETCH_LAST | Return the last complete rowset in the result set. SQLFetchScroll ignores the value of FetchOffset. |
SQL_FETCH_BOOKMARK | Return the rowset FetchOffset rows from the bookmark specified by the SQL_ATTR_FETCH_BOOKMARK_PTR statement attribute. |
Drivers are not required to support all fetch orientations; an application calls SQLGetInfo with an information type of SQL_DYNAMIC_CURSOR_ATTRIBUTES1, SQL_KEYSET_CURSOR_ATTRIBUTES1, or SQL_STATIC_CURSOR_ATTRIBUTES1 (depending on the type of the cursor) to determine which fetch orientations are supported by the driver. The application should look at the SQL_CA1_NEXT, SQL_CA1_RELATIVE, SQL_CA1_ABSOLUTE, and WQL_CA1_BOOKMARK bitmasks in these information types. Furthermore, if the cursor is forward-only and FetchOrientation is not SQL_FETCH_NEXT, SQLFetchScroll returns SQLSTATE HY106 (Fetch type out of range).
The SQL_ATTR_ROW_ARRAY_SIZE statement attribute specifies the number of rows in the rowset. If the rowset being fetched by SQLFetchScroll overlaps the end of the result set, SQLFetchScroll returns a partial rowset. That is, if S + R - 1 is greater than L, where S is the starting row of the rowset being fetched, R is the rowset size, and L is the last row in the result set, then only the first L - S + 1 rows of the rowset are valid. The remaining rows are empty and have a status of SQL_ROW_NOROW.
After SQLFetchScroll returns, the current row is the first row of the rowset.
Cursor Positioning Rules
The following sections describe the exact rules for each value of FetchOrientation. These rules use the following notation.
Notation | Meaning |
---|---|
Before start | The block cursor is positioned before the start of the result set. If the first row of the new rowset is before the start of the result set, SQLFetchScroll returns SQL_NO_DATA. |
After end | The block cursor is positioned after the end of the result set. If the first row of the new rowset is after the end of the result set, SQLFetchScroll returns SQL_NO_DATA. |
CurrRowsetStart | The number of the first row in the current rowset. |
LastResultRow | The number of the last row in the result set. |
RowsetSize | The rowset size. |
FetchOffset | The value of the FetchOffset argument. |
BookmarkRow | The row corresponding to the bookmark specified by the SQL_ATTR_FETCH_BOOKMARK_PTR statement attribute. |
SQL_FETCH_NEXT
The following rules apply.
Condition | First row of new rowset |
---|---|
Before start | 1 |
CurrRowsetStart + RowsetSize[1] <= LastResultRow | CurrRowsetStart + RowsetSize[1] |
CurrRowsetStart + RowsetSize[1]> LastResultRow | After end |
After end | After end |
[1] If the rowset size has been changed since the previous call to fetch rows, this is the rowset size that was used with the previous call.
SQL_FETCH_PRIOR
The following rules apply.
Condition | First row of new rowset |
---|---|
Before start | Before start |
CurrRowsetStart = 1 | Before start |
1 < CurrRowsetStart <= RowsetSize [2] | 1 [1] |
CurrRowsetStart > RowsetSize [2] | CurrRowsetStart - RowsetSize [2] |
After end AND LastResultRow < RowsetSize [2] | 1 [1] |
After end AND LastResultRow >= RowsetSize [2] | LastResultRow - RowsetSize + 1 [2] |
[1] SQLFetchScroll returns SQLSTATE 01S06 (Attempt to fetch before the result set returned the first rowset) and SQL_SUCCESS_WITH_INFO.
[2] If the rowset size has been changed since the previous call to fetch rows, this is the new rowset size.
SQL_FETCH_RELATIVE
The following rules apply.
Condition | First row of new rowset |
---|---|
(Before start AND FetchOffset > 0) OR (After end AND FetchOffset < 0) | -- [1] |
BeforeStart AND FetchOffset <= 0 | Before start |
CurrRowsetStart = 1 AND FetchOffset < 0 | Before start |
CurrRowsetStart > 1 AND CurrRowsetStart + FetchOffset < 1 AND | FetchOffset | > RowsetSize [3] | Before start |
CurrRowsetStart > 1 AND CurrRowsetStart + FetchOffset < 1 AND | FetchOffset | <= RowsetSize [3] | 1 [2] |
1 <= CurrRowsetStart + FetchOffset <= LastResultRow | CurrRowsetStart + FetchOffset |
CurrRowsetStart + FetchOffset > LastResultRow | After end |
After end AND FetchOffset >= 0 | After end |
[1] SQLFetchScroll returns the same rowset as if it was called with FetchOrientation set to SQL_FETCH_ABSOLUTE. For more information, see the "SQL_FETCH_ABSOLUTE" section.
[2] SQLFetchScroll returns SQLSTATE 01S06 (Attempt to fetch before the result set returned the first rowset) and SQL_SUCCESS_WITH_INFO.
[3] If the rowset size has been changed since the previous call to fetch rows, this is the new rowset size.
SQL_FETCH_ABSOLUTE
The following rules apply.
Condition | First row of new rowset |
---|---|
FetchOffset < 0 AND | FetchOffset | <= LastResultRow | LastResultRow + FetchOffset + 1 |
FetchOffset < 0 AND | FetchOffset | > LastResultRow AND | FetchOffset | > RowsetSize [2] | Before start |
FetchOffset < 0 AND | FetchOffset | > LastResultRow AND | FetchOffset | <= RowsetSize [2] | 1 [1] |
FetchOffset = 0 | Before start |
1 <= FetchOffset <= LastResultRow | FetchOffset |
FetchOffset > LastResultRow | After end |
[1] SQLFetchScroll returns SQLSTATE 01S06 (Attempt to fetch before the result set returned the first rowset) and SQL_SUCCESS_WITH_INFO.
[2] If the rowset size has been changed since the previous call to fetch rows, this is the new rowset size.
An absolute fetch performed against a dynamic cursor cannot provide the required result because row positions in a dynamic cursor are undetermined. Such an operation is equivalent to a fetch first followed by a fetch relative; it is not an atomic operation, as is an absolute fetch on a static cursor.
SQL_FETCH_FIRST
The following rules apply.
Condition | First row of new rowset |
---|---|
Any | 1 |
SQL_FETCH_LAST
The following rules apply.
Condition | First row of new rowset |
---|---|
RowsetSize [1] <= LastResultRow | LastResultRow - RowsetSize + 1 [1] |
RowsetSize [1] > LastResultRow | 1 |
[1] If the rowset size has been changed since the previous call to fetch rows, this is the new rowset size.
SQL_FETCH_BOOKMARK
The following rules apply.
Condition | First row of new rowset |
---|---|
BookmarkRow + FetchOffset < 1 | Before start |
1 <= BookmarkRow + FetchOffset <= LastResultRow | BookmarkRow + FetchOffset |
BookmarkRow + FetchOffset > LastResultRow | After end |
For information about bookmarks, see Bookmarks (ODBC).
Effect of Deleted, Added, and Error Rows on Cursor Movement
Static and keyset-driven cursors sometimes detect rows added to the result set and remove rows deleted from the result set. By calling SQLGetInfo with the SQL_STATIC_CURSOR_ATTRIBUTES2 and SQL_KEYSET_CURSOR_ATTRIBUTES2 options and looking at the SQL_CA2_SENSITIVITY_ADDITIONS, SQL_CA2_SENSITIVITY_DELETIONS, and SQL_CA2_SENSITIVITY_UPDATES bitmasks, an application determines whether the cursors implemented by a particular driver do this. For drivers that can detect deleted rows and remove them, the following paragraphs describe the effects of this behavior. For drivers that can detect deleted rows but cannot remove them, deletions have no effect on cursor movements, and the following paragraphs do not apply.
If the cursor detects rows added to the result set or removes rows deleted from the result set, it appears as if it detects these changes only when it fetches data. This includes the case when SQLFetchScroll is called with FetchOrientation set to SQL_FETCH_RELATIVE and FetchOffset set to 0 to refetch the same rowset, but does not include the case when SQLSetPos is called with fOption set to SQL_REFRESH. In the latter case, the data in the rowset buffers is refreshed, but not refetched, and deleted rows are not removed from the result set. Thus, when a row is deleted from or inserted into the current rowset, the cursor does not modify the rowset buffers. Instead, it detects the change when it fetches any rowset that previously included the deleted row or now includes the inserted row.
For example:
// Fetch the next rowset.
SQLFetchScroll(hstmt, SQL_FETCH_NEXT, 0);
// Delete third row of the rowset. Does not modify the rowset buffers.
SQLSetPos(hstmt, 3, SQL_DELETE, SQL_LOCK_NO_CHANGE);
// The third row has a status of SQL_ROW_DELETED after this call.
SQLSetPos(hstmt, 3, SQL_REFRESH, SQL_LOCK_NO_CHANGE);
// Refetch the same rowset. The third row is removed, replaced by what
// was previously the fourth row.
SQLFetchScroll(hstmt, SQL_FETCH_RELATIVE, 0);
When SQLFetchScroll returns a new rowset that has a position relative to the current rowset - that is, FetchOrientation is SQL_FETCH_NEXT, SQL_FETCH_PRIOR, or SQL_FETCH_RELATIVE - it does not include changes to the current rowset when calculating the starting position of the new rowset. However, it does include changes outside the current rowset if it is capable of detecting them. Furthermore, when SQLFetchScroll returns a new rowset that has a position independent of the current rowset - that is, FetchOrientation is SQL_FETCH_FIRST, SQL_FETCH_LAST, SQL_FETCH_ABSOLUTE, or SQL_FETCH_BOOKMARK - it includes all changes it is capable of detecting, even if they are in the current rowset.
When determining whether newly added rows are inside or outside the current rowset, a partial rowset is considered to end at the last valid row; that is, the last row for which the row status is not SQL_ROW_NOROW. For example, suppose the cursor is capable of detecting newly added rows, the current rowset is a partial rowset, the application adds new rows, and the cursor adds these rows to the end of the result set. If the application calls SQLFetchScroll with FetchOrientation set to SQL_FETCH_NEXT, SQLFetchScroll returns the rowset starting with the first newly added row.
For example, suppose the current rowset comprises rows 21 to 30, the rowset size is 10, the cursor removes rows deleted from the result set, and the cursor detects rows added to the result set. The following table shows the rows SQLFetchScroll returns in various situations.
Change | Fetch type | FetchOffset | New rowset[1] |
---|---|---|---|
Delete row 21 | NEXT | 0 | 31 to 40 |
Delete row 31 | NEXT | 0 | 32 to 41 |
Insert row between rows 21 and 22 | NEXT | 0 | 31 to 40 |
Insert row between rows 30 and 31 | NEXT | 0 | Inserted row, 31 to 39 |
Delete row 21 | PRIOR | 0 | 11 to 20 |
Delete row 20 | PRIOR | 0 | 10 to 19 |
Insert row between rows 21 and 22 | PRIOR | 0 | 11 to 20 |
Insert row between rows 20 and 21 | PRIOR | 0 | 12 to 20, inserted row |
Delete row 21 | RELATIVE | 0 | 22 to 31[2] |
Delete row 21 | RELATIVE | 1 | 22 to 31 |
Insert row between rows 21 and 22 | RELATIVE | 0 | 21, inserted row, 22 to 29 |
Insert row between rows 21 and 22 | RELATIVE | 1 | 22 to 31 |
Delete row 21 | ABSOLUTE | 21 | 22 to 31[2] |
Delete row 22 | ABSOLUTE | 21 | 21, 23 to 31 |
Insert row between rows 21 and 22 | ABSOLUTE | 22 | Inserted row, 22 to 29 |
[1] This column uses the row numbers before any rows were inserted or deleted.
[2] In this case, the cursor attempts to return rows starting with row 21. Because row 21 has been deleted, the first row it returns is row 22.
Error rows (that is, rows with a status of SQL_ROW_ERROR) do not affect cursor movement. For example, if the current rowset starts with row 11 and the status of row 11 is SQL_ROW_ERROR, calling SQLFetchScroll with FetchOrientation set to SQL_FETCH_RELATIVE and FetchOffset set to 5 returns the rowset starting with row 16, just as it would if the status for row 11 was SQL_SUCCESS.
Returning Data in Bound Columns
SQLFetchScroll returns data in bound columns in the same way as SQLFetch. For more information, see "Returning Data in Bound Columns" in SQLFetch Function.
If no columns are bound, SQLFetchScroll does not return data but does move the block cursor to the specified position. Whether data can be retrieved from unbound columns of a block cursor with SQLGetData depends on the driver. This capability is supported if a call to SQLGetInfo returns the SQL_GD_BLOCK bit for the SQL_GETDATA_EXTENSIONS information type.
Buffer Addresses
SQLFetchScroll uses the same formula to determine the address of data and length/indicator buffers as SQLFetch. For more information, see "Buffer Addresses" in SQLBindCol Function.
Row Status Array
SQLFetchScroll sets values in the row status array in the same manner as SQLFetch. For more information, see "Row Status Array" in SQLFetch Function.
Rows Fetched Buffer
SQLFetchScroll returns the number of rows fetched in the rows fetched buffer in the same manner as SQLFetch. For more information, see "Rows Fetched Buffer" in SQLFetch Function.
Error Handling
When an application calls SQLFetchScroll in an ODBC 3.x driver, the Driver Manager calls SQLFetchScroll in the driver. When an application calls SQLFetchScroll in an ODBC 2.x driver, the Driver Manager calls SQLExtendedFetch in the driver. Because SQLFetchScroll and SQLExtendedFetch handle errors in a slightly different manner, the application sees slightly different error behavior when it calls SQLFetchScroll in ODBC 2.x and ODBC 3.x drivers.
SQLFetchScroll returns errors and warnings in the same manner as SQLFetch; for more information, see "Error Handling" in SQLFetch. SQLExtendedFetch returns errors in the same manner as SQLFetch, with the following exceptions:
When a warning occurs that applies to a particular row in the rowset, SQLExtendedFetch sets the corresponding entry in the row status array to SQL_ROW_SUCCESS, not SQL_ROW_SUCCESS_WITH_INFO.
If errors occur in every row in the rowset, SQLExtendedFetch returns SQL_SUCCESS_WITH_INFO, not SQL_ERROR.
In each group of status records that applies to an individual row, the first status record returned by SQLExtendedFetch must contain SQLSTATE 01S01 (Error in row); SQLFetchScroll does not return this SQLSTATE. If SQLExtendedFetch is unable to return additional SQLSTATEs, it still must return this SQLSTATE.
SQLFetchScroll and Optimistic Concurrency
If a cursor uses optimistic concurrency - that is, the SQL_ATTR_CONCURRENCY statement attribute has a value of SQL_CONCUR_VALUES or SQL_CONCUR_ROWVER - SQLFetchScroll updates the optimistic concurrency values used by the data source to detect whether a row has changed. This happens whenever SQLFetchScroll fetches a new rowset, including when it refetches the current rowset. (It is called with FetchOrientation set to SQL_FETCH_RELATIVE and FetchOffset set to 0.)
SQLFetchScroll and ODBC 2.x Drivers
When an application calls SQLFetchScroll in an ODBC 2.x driver, the Driver Manager maps this call to SQLExtendedFetch. It passes the following values for the arguments of SQLExtendedFetch.
SQLExtendedFetch argument | Value |
---|---|
StatementHandle | StatementHandle in SQLFetchScroll. |
FetchOrientation | FetchOrientation in SQLFetchScroll. |
FetchOffset | If FetchOrientation is not SQL_FETCH_BOOKMARK, the value of the FetchOffset argument in SQLFetchScroll is used. If FetchOrientation is SQL_FETCH_BOOKMARK, the value stored at the address specified by the SQL_ATTR_FETCH_BOOKMARK_PTR statement attribute is used. |
RowCountPtr | The address specified by the SQL_ATTR_ROWS_FETCHED_PTR statement attribute. |
RowStatusArray | The address specified by the SQL_ATTR_ROW_STATUS_PTR statement attribute. |
For more information, see Block Cursors, Scrollable Cursors, and Backward Compatibility in Appendix G: Driver Guidelines for Backward Compatibility.
Descriptors and SQLFetchScroll
SQLFetchScroll interacts with descriptors in the same manner as SQLFetch. For more information, see the "Descriptors and SQLFetchScroll" section in SQLFetch Function.
Code Example
See Column-Wise Binding, Row-Wise Binding, Positioned Update and Delete Statements, and Updating Rows in the Rowset with SQLSetPos.
Related Functions
For information about | See |
---|---|
Binding a buffer to a column in a result set | SQLBindCol Function |
Performing bulk insert, update, or delete operations | SQLBulkOperations Function |
Canceling statement processing | SQLCancel Function |
Returning information about a column in a result set | SQLDescribeCol Function |
Executing a SQL statement | SQLExecDirect Function |
Executing a prepared SQL statement | SQLExecute Function |
Fetching a single row or a block of data in a forward-only direction | SQLFetch Function |
Closing the cursor on the statement | SQLFreeStmt Function |
Returning the number of result set columns | SQLNumResultCols Function |
Positioning the cursor, refreshing data in the rowset, or updating or deleting data in the result set | SQLSetPos Function |
Setting a statement attribute | SQLSetStmtAttr Function |