定位更新 (ODBC)

ODBC 支持通过两种方法在游标中执行定位更新:

  • SQLSetPos

  • WHERE CURRENT OF 子句

更常用的方法是使用 SQLSetPos。它具有以下选项。

  • SQL_POSITION
    将游标定位到当前行集中的特定行。

  • SQL_REFRESH
    使用游标当前所定位行的值刷新被绑定到结果集列上的程序变量。

  • SQL_UPDATE
    使用绑定到结果集列上的程序变量中所存储的值来更新游标中的当前行。

  • SQL_DELETE
    删除游标中的当前行。

当语句句柄游标属性设置为使用服务器游标时,可以将 SQLSetPos 用于任意语句结果集。结果集列必须绑定到程序变量。应用程序一旦提取了某一行,就会调用 SQLSetPos(SQL_POSTION) 将游标定位在该行上。随后应用程序可以调用 SQLSetPos(SQL_DELETE) 删除当前行,或者可以将新数据值移入绑定程序变量并调用 SQLSetPos(SQL_UPDATE) 更新当前行。

应用程序可以使用 SQLSetPos 更新或删除行集中的任意行。调用 SQLSetPos 是一种方便的可替代构造和执行 SQL 语句的方式。SQLSetPos 针对当前行集操作,且只能在调用 SQLFetchScroll 后使用。

通过调用带有属性参数 SQL_ATTR_ROW_ARRAY_SIZE 的 SQLSetStmtAttr,可以设置行集大小。SQLSetPos 仅在调用 SQLFetchSQLFetchScroll 后使用新的行集大小。例如,如果行集大小已更改,先调用了 SQLSetPos,然后调用了 SQLFetchSQLFetchScroll。对 SQLSetPos 的调用将使用旧的行集大小,但是对 SQLFetchSQLFetchScroll 的调用将使用新的行集大小。

行集中的第一行的行编号为 1。SQLSetPos 中的 RowNumber 参数必须标识行集中的某行;即,该参数的值必须介于 1 和最近提取的行数之间。这可能小于行集大小。如果 RowNumber 为 0,将对行集中的所有行应用操作。

SQLSetPos 的删除操作会从数据源中删除一个或多个选定表行。若要使用 SQLSetPos 删除行,应用程序应调用 SQLSetPos,同时将 Operation 设置为 SQL_DELETE,将 RowNumber 设置为要删除的行数。如果 RowNumber 为 0,将删除行集中的所有行。

SQLSetPos 返回结果后,删除的行将变为当前行,其状态为 SQL_ROW_DELETED。该行将无法用于任何其他定位操作,如调用 SQLGetDataSQLSetPos

删除行集中的所有行后 (RowNumber = 0),通过使用与 SQLSetPos 的更新操作所用的行操作数组类似的数组,应用程序可以防止驱动程序删除特定行。

每个删除的行都应该是结果集中存在的行。如果应用程序缓冲区已被提取操作填充,并且保持了行状态数组,则所有这些行位置处的行值都不应为 SQL_ROW_DELETED、SQL_ROW_ERROR 或 SQL_ROW_NOROW。

通过在 UPDATE、DELETE 和 INSERT 语句中使用 WHERE CURRENT OF 子句,也可以执行定位更新。WHERE CURRENT OF 要求提供一个游标名称,该名称将在调用 SQLGetCursorName 函数时由 ODBC 生成,或者通过调用 SQLSetCursorName 指定。以下是用于在 ODBC 应用程序中执行 WHERE CURRENT OF 更新的一般步骤:

  • 调用 SQLSetCursorName 为语句句柄设置游标名称。

  • 生成包含 FOR UPDATE OF 子句的 SELECT 语句,并执行该语句。

  • 调用 SQLFetchScroll 以检索行集;或调用 SQLFetch 以检索某一行。

  • 调用 SQLSetPos (SQL_POSITION) 将游标定位在该行上。

  • 生成并执行包含 WHERE CURRENT OF 子句(使用通过 SQLSetCursorName 设置的游标名称)的 UPDATE 语句。

或者,可以在执行 SELECT 语句后调用 SQLGetCursorName,代替在执行 SELECT 语句前调用 SQLSetCursorName 的方式。如果没有使用 SQLSetCursorName 设置游标名称,SQLGetCursorName 将返回 ODBC 分配的默认游标名称。

使用服务器游标时,最好使用 SQLSetPos 而不是 WHERE CURRENT OF。如果使用 ODBC 游标库中的静态、可更新游标,该游标库通过添加一个 WHERE 子句(带有基础表的键值)实现 WHERE CURRENT OF 更新。如果表中的键不唯一,这可能导致意外更新。