编写 ODBC 3.x 应用程序

将 ODBC 2.x 应用程序升级到 ODBC 3.x时,应该编写该应用程序,使其可以同时使用 ODBC 2.x 和 ODBC 3.x 驱动程序。 应用程序应包含条件代码,以充分利用 ODBC 3.x 的功能。

SQL_ATTR_ODBC_VERSION 环境属性应设置为 SQL_OV_ODBC2。 这将确保驱动程序的行为类似于 ODBC 2.x 驱动程序,与行为更改一节中所述的更改类似。

如果应用程序将使用新功能一节中介绍的功能,则应该使用条件代码来确定驱动程序是 ODBC 3.x 还是 ODBC 2.x 驱动程序。 应用程序在对这些条件代码片段执行错误处理时,使用 SQLGetDiagField 和 SQLGetDiagRec 来获取 ODBC 3.x SQLSTATEs。 应考虑以下关于新功能的要点:

  • 当数组大小大于 1 时,受行集大小更改影响的应用程序应注意不要调用 SQLFetch。 这些应用程序应将对 SQLExtendedFetch 的调用替换为对 SQLSetStmtAttr 的调用,以设置 SQL_ATTR_ARRAY_STATUS_PTR 语句属性,并调用 SQLFetchScroll,这样它们就具有可用于 ODBC 3.x 和 ODBC 2.x 驱动程序的常见代码。 因为对于 ODBC 2.x 驱动程序,带有 SQL_ATTR_ROW_ARRAY_SIZE 的 SQLSetStmtAttr 将映射到带有 SQL_ROWSET_SIZE 的 SQLSetStmtAttr,因此应用程序只需为其多行提取操作设置 SQL_ATTR_ROW_ARRAY_SIZE。

  • 大多数正在升级的应用程序实际上不受 SQLSTATE 代码更改的影响。 对于那些受影响的应用程序,大多数情况下可以进行机械搜索和替换,使用“SQLSTATE 映射”部分中的错误转换表将 ODBC 3.x 错误代码转换为 ODBC 2.x 代码。 由于 ODBC 3.x 驱动程序管理器将执行从 ODBC 2.x SQLSTATEs 到 ODBC 3.x SQLSTATEs 的映射,因此这些应用程序编写器只需检查 ODBC 3.x SQLSTATEs,而不必担心在条件代码中包含 ODBC 2.x SQLSTATEs。

  • 如果应用程序充分利用日期、时间和时间戳数据类型,则应用程序可以声明自己为 ODBC 2.x 应用程序,并使用其现有代码,而不是使用条件代码。

升级还应包括以下步骤:

  • 在分配连接前调用 SQLSetEnvAttr 以将 SQL_ATTR_ODBC_VERSION 环境属性设置为 SQL_OV_ODBC2。

  • 将所有对 SQLAllocEnv、SQLAllocConnect 或 SQLAllocStmt 的调用替换为对 SQLAllocHandle 的调用,并使用相应的 HandleType 参数 SQL_HANDLE_ENV、SQL_HANDLE_DBC 或 SQL_HANDLE_STMT。

  • 将所有对 SQLFreeEnv 或 SQLFreeConnect 的调用替换为对 SQLFreeHandle 的调用,并使用相应的 HandleType 参数 SQL_HANDLE_DBC 或 SQL_HANDLE_STMT。

  • 将对 SQLSetConnectOption 的所有调用替换为对 SQLSetConnectAttr 的调用。 如果所设置属性的值是字符串,请适当设置 StringLength 参数。 将 Attribute 参数从 SQL_XXXX 更改为 SQL_ATTR_XXXX。

  • 将对 SQLGetConnectOption 的所有调用替换为对 SQLGetConnectAttr 的调用。 如果获取字符串或二进制属性,请将 BufferLength 设置为适当的值并传入 StringLength 参数。 将 Attribute 参数从 SQL_XXXX 更改为 SQL_ATTR_XXXX。

  • 将对 SQLSetStmtOption 的所有调用替换为对 SQLSetStmtAttr 的调用。 如果所设置属性的值是字符串,请适当设置 StringLength 参数。 将 Attribute 参数从 SQL_XXXX 更改为 SQL_ATTR_XXXX。

  • 将对 SQLGetStmtOption 的所有调用替换为对 SQLGetStmtAttr 的调用。 如果获取字符串或二进制属性,请将 BufferLength 设置为适当的值并传入 StringLength 参数。 将 Attribute 参数从 SQL_XXXX 更改为 SQL_ATTR_XXXX。

  • 将对 SQLTransact 的所有调用替换为对 SQLEndTran 的调用。 如果 SQLTransact 调用中最右侧的有效句柄是环境句柄,则应在 SQLEndTran 调用中使用具有相应 Handle 参数的 HandleType 参数 SQL_HANDLE_ENV。 如果 SQLTransact 调用中最右侧的有效句柄是连接句柄,则应在 SQLEndTran 调用中使用具有相应 Handle 参数的 HandleType 参数 SQL_HANDLE_DBC。

  • 将所有对 SQLColAttributes 的调用替换为对 SQLColAttribute 的调用。 如果 FieldIdentifier 参数为 SQL_COLUMN_PRECISION、SQL_COLUMN_SCALE 或 SQL_COLUMN_LENGTH,则不更改函数名称以外的任何内容。 否则,请将 FieldIdentifier 从 SQL_COLUMN_XXXX 更改为 SQL_DESC_XXXX。 如果 FieldIdentifier 为 SQL_DESC_CONCISE_TYPE 且数据类型为日期/时间数据类型,请更改为相应的 ODBC 3.x 数据类型。

  • 如果使用块游标、可滚动游标或两者都使用,应用程序将执行以下操作:

    • 使用 SQLSetStmtAttr 设置行集大小、游标类型和游标并发。

    • 调用 SQLSetStmtAttr 将 SQL_ATTR_ROW_STATUS_PTR 设置为指向状态记录数组。

    • 调用 SQLSetStmtAttr 将 SQL_ATTR_ROWS_FETCHED_PTR 设置为指向 SQLINTEGER。

    • 执行所需的绑定并执行 SQL 语句。

    • 在循环中调用 SQLFetchScroll 以提取行并在结果集中移动。

    • 如果想要按书签提取,应用程序会调用 SQLSetStmtAttr 将 SQL_ATTR_FETCH_BOOKMARK_PTR 设置为包含要提取行的书签的变量,并使用 SQL_FETCH_BOOKMARK 的 FetchOrientation 参数调用 SQLFetchScroll

  • 如果使用参数数组,应用程序将执行以下操作:

    • 调用 SQLSetStmtAttr 将 SQL_ATTR_PARAMSET_SIZE 属性设置为参数数组的大小。

    • 调用 SQLSetStmtAttr 将 SQL_ATTR_ROWS_PROCESSED_PTR 设置为指向内部 UDWORD 变量。

    • 根据需要执行准备、绑定和执行操作。

    • 如果执行因某种原因(如 SQL_NEED_DATA)而停止,则可以通过检查 SQL_ATTR_ROWS_PROCESSED_PTR 指向的位置来查找参数的“当前”行。

本部分包含以下主题。