API 服务器游标
OLE DB、ODBC 和 ADO API 支持将游标映射到已执行 SQL 语句的结果集。Microsoft SQL Native Client OLE DB 访问接口和 SQL Native Client ODBC 驱动程序通过使用 API 服务器游标来实现这些操作。API 服务器游标在服务器上实现,并由 API 游标函数进行管理。当应用程序调用 API 游标函数时,游标操作由 OLE DB 访问接口或 ODBC 驱动程序传送给服务器。
当在 OLE DB、ODBC 和 ADO 中使用 API 服务器游标时,使用 API 函数和方法实现如下功能:
- 打开一个连接。
- 设置定义游标特征的特性或属性,API 自动将游标映射到每个结果集。
- 执行一个或多个 Transact-SQL 语句。
- 使用 API 函数或方法提取结果集中的行。
当 API 游标特性或属性设为默认值时,SQL Native Client OLE DB 访问接口和 SQL Native Client ODBC 驱动程序将使用默认结果集。虽然从技术上说 API 需要游标,但默认游标特征与默认结果集的行为是匹配的。因此,OLE DB 访问接口和 ODBC 驱动程序使用默认结果集实现默认游标选项,因为这是从服务器中检索行的最有效的方法。使用默认结果集时,应用程序可以执行任何 Transact-SQL 语句或批处理,但它只允许一个连接中有一个未完成的语句。这意味着应用程序必须处理或取消由一个语句返回的所有结果集,然后才能执行连接中的下一个语句。
当 API 游标特性或属性没有设为默认值,SQL Native Client OLE DB 访问接口和 SQL Native Client ODBC 驱动程序将使用 API 服务器游标代替默认结果集。每次对提取行的 API 函数的调用都会产生到服务器的一次往返,以从 API 服务器游标中提取行。
API 服务器游标限制
使用 API 服务器游标时,应用程序不能执行下列语句:
- 服务器游标中 SQL Server 不支持的 Transact-SQL 语句。
- 返回多个结果集的批处理或存储过程。
- 包含 COMPUTE、COMPUTE BY、FOR BROWSE 或 INTO 子句的 SELECT 语句。
- 引用远程存储过程的 EXECUTE 语句。
API 服务器游标实现
SQL Native Client OLE DB 访问接口和 SQL Native Client ODBC 驱动程序使用下面这些特殊的系统存储过程向服务器发出游标操作信号:
- sp_cursoropen 定义与游标和游标选项相关联的 SQL 语句,然后填充游标。
- sp_cursorfetch 从游标中提取一行或一个行块。
- sp_cursorclose 关闭并释放游标。
- sp_cursoroption 用于设置各种游标选项。
- sp_cursor 用于请求定位更新。
- sp_cursorprepare 将与游标有关的 Transact-SQL 语句或批处理编译成执行计划,但并不创建游标。
- sp_cursorexecute 从 sp_cursorprepare 创建的执行计划中创建并填充游标。
- sp_cursorunprepare 丢弃 sp_cursorprepare 生成的执行计划。
- sp_cursorprepexec 为提交的与游标相关联的 Transact-SQL 语句或批处理编译计划,创建并填充游标。sp_cursorprepexec 结合了 sp_cursorprepare 和 sp_cursorexecute 的行为。
这些系统存储过程将出现在使用 API 服务器游标的 ADO、OLE DB 和 ODBC 应用程序的 SQL Server Profiler 跟踪中。它们仅供 SQL Native Client OLE DB 访问接口和 SQL Native Client ODBC 启动程序内部使用。应用程序可通过数据库 API 的游标功能来使用这些过程的完整功能。不支持在应用程序中直接指定过程。
当 SQL Server 执行某个连接中的一个语句时,只有先处理完或取消第一个语句的所有结果才能执行连接中的其他语句。此规则在使用 API 服务器游标时仍然适用,但从应用程序的角度看,好像 SQL Server 已经开始支持一个连接中存在多个活动语句。这是因为完整的结果集存储在服务器游标中,并且只有传送给 SQL Server 的语句才执行 sp_cursor 系统存储过程。SQL Server 将执行存储过程,并且只要客户端检索到结果集,它就能执行任何其他语句。OLE DB 访问接口和 ODBC 驱动程序则在将控制返回给应用程序之前始终检索来自 sp_cursor 存储过程的所有结果集。这使应用程序可以插空在多个活动服务器游标中进行提取操作。
下表说明了应用程序如何利用两个语句句柄在一个连接上同时处理两个游标。
语句句柄 1 | 语句句柄 2 |
---|---|
设置游标特性,以便使用 API 服务器游标。 |
|
SQLExecDirect 一个 SQL 语句。ODBC 驱动程序调用 sp_cursoropen,然后检索该过程所返回的结果集。 |
|
|
设置游标特性,以便使用 API 服务器游标。 |
|
SQLExecDirect 一个 SQL 语句。ODBC 驱动程序调用 sp_cursoropen,然后检索该过程所返回的结果集。 |
SQLFetchScroll 检索第一个行块。驱动程序调用 sp_cursorfetch,然后检索该过程所返回的结果集。 |
|
|
SQLFetchScroll 检索第一个行块。驱动程序调用 sp_cursorfetch,然后检索该过程所返回的结果集。 |
SQLFetchScroll 检索另一个行块。驱动程序调用 sp_cursorfetch,然后检索该过程所返回的结果集。 |
|
|
SQLFetchScroll 检索另一个行块。驱动程序调用 sp_cursorfetch,然后检索该过程所返回的结果集。 |
调用 SQLFreeStmt 或 SQLCloseCursor。驱动程序调用 sp_cursorclose。 |
|
|
调用 SQLFreeStmt 或 SQLCloseCursor。驱动程序调用 sp_cursorclose。 |
由于调用 sp_cursor 存储过程之后连接中不再有未完成的结果,因此可以在一个连接中并发执行多个 Transact-SQL 语句,只要它们都是使用 API 服务器游标执行的。
指定 API 服务器游标
下面是有关如何在 API 中使用 API 服务器游标的摘要:
- OLE DB
- 打开会话对象,然后打开命令对象并指定命令文本。
- 设置行集属性(例如 DBPROP_OTHERINSERT、DBPROP_OTHERUPDATEDELETE、DBPROP_OWNINSERT、DBPROP_OWNUDPATEDELETE 等)以控制游标行为。
- 执行命令对象。
- 使用下列方法提取结果集中的行,如 IRowset::GetNextRows、IRowsetLocate::GetRowsAt、IRowsetLocate::GetRowsAtBookmark 和 IRowsetScroll::GetRowsAtRatio。
- ODBC
- 打开一个连接,然后调用 SQLAllocHandle 以分配语句句柄。
- 调用 SQLSetStmtAttr 以设置 SQL_ATTR_CURSOR_TYPE、SQL_ATTR_CONCURRENCY 和 SQL_ATTR_ROW_ARRAY_SIZE 特性。也可以通过设置 SQL_ATTR_CURSOR_SCROLLABLE 和 SQL_ATTR_CURSOR_SENSITIVITY 特性来指定游标行为。
- 使用 SQLExecDirect 或 SQLPrepare 和 SQLExecute 执行 Transact-SQL 语句。
- 使用 SQLFetch 或 SQLFetchScroll 提取行或行块。
- ADO
- 定义 Connection 对象和 Recordset 对象,然后对 Connection 对象执行 Open 方法。
- 指定 CursorType 和/或 LockType 参数,对 Recordset 对象执行 Open 方法。
- 使用 Move、MoveFirst、MoveLast、MoveNext 和 MovePrevious 记录集方法提取行。
API 服务器游标和 SET 选项
在 SQL Server 2005 中,如果发出提取语句,并且对下列影响计划的任何选项或索引视图或计算列需要的选项进行了更改,游标将使用打开时生效的选项值的快照。这些值将用于所有后续的提取操作,在当前上下文中所做的更改将被忽略。
影响计划的选项 |
ARITHABORT NUMERIC_ROUNDABORT FORCEPLAN QUOTED_IDENTIFIER ANSI_NULL_DFLT_ON ANSI_NULL_DFLT_OFF ANSI_WARNINGS ANSI_PADDING ANSI_NULLS CONCAT_NULL_YIELDS_NULL DATEFIRST DATEFORMAT LANGUAGE TEXTSIZE |
索引视图和计算列 |
ANSI_NULLS ANSI_PADDING ANSI_WARNINGS ARITHABORT(兼容级别为 80 或更低)CONCAT_NULL_YIELDS_NULL QUOTED_IDENTIFIER NUMERIC_ROUNDABORT |
请参阅
其他资源
Rowsets and SQL Server Cursors
Using Cursors