TN042:ODBC 驱动程序开发人员建议
注意
以下技术说明在首次包括在联机文档中后未更新。 因此,某些过程和主题可能已过时或不正确。 要获得最新信息,建议你在联机文档索引中搜索热点话题。
此说明介绍 ODBC 驱动程序编写器的指南。 它概述了 MFC 数据库类对 ODBC 功能提出的一般要求和假设,以及各种预期的语义详细信息。 介绍支持三种 CRecordset
打开模式(只进、快照和动态集)所需的驱动程序功能。
ODBC 的游标库
MFC 数据库类向用户提供的功能在许多情况下超过大多数级别 1 ODBC 驱动程序提供的功能。 幸运的是,ODBC 的游标库会将自己置于数据库类和驱动程序之间,并且会自动提供大部分附加功能。
例如,大多数 1.0 驱动程序不支持向后滚动。 游标库可以检测到这一点,并且将缓存驱动程序中的行,然后按 SQLExtendedFetch
中的 FETCH_PREV 调用的请求显示这些行。
游标库依赖的另一个重要示例是定位更新。 大多数 1.0 驱动程序也没有定位更新,但游标库将生成更新语句,这些语句根据数据源的当前缓存数据值或缓存时间戳值来标识数据源上的目标行。
类库从不使用多个行集。 因此,少数 SQLSetPos
语句始终应用于行集的第 1 行。
CDatabases
每个 CDatabase
分配单个 HDBC。 (如果使用 CDatabase
的 ExecuteSQL
函数,则暂时分配 HSTMT。)因此,如果需要多个 CDatabase
,则必须支持每个 HENV 的多个 HDBC。
数据库类需要游标库。 这反映在 SQLSetConnections
调用 SQL_ODBC_CURSORS、SQL_CUR_USE_ODBC 中。
SQLDriverConnect
,SQL_DRIVER_COMPLETE 由 CDatabase::Open
用来建立与数据源的连接。
驱动程序必须支持 SQLGetInfo SQL_ODBC_API_CONFORMANCE
>= SQL_OAC_LEVEL1、SQLGetInfo SQL_ODBC_SQL_CONFORMANCE
>= SQL_OSC_MINIMUM。
为了使事务受 CDatabase
及其依赖记录集的支持,SQLGetInfo SQL_CURSOR_COMMIT_BEHAVIOR
和 SQL_CURSOR_ROLLBACK_BEHAVIOR 必须具有 SQL_CR_PRESERVE。 否则,将忽略尝试执行事务控制。
必须支持 SQLGetInfo SQL_DATA_SOURCE_READ_ONLY
。 如果返回“Y”,则不会对数据源执行任何更新操作。
如果 CDatabase
是打开的 ReadOnly,则使用 SQLSetConnectOption SQL_ACCESS_MODE
和 SQL_MODE_READ_ONLY 尝试设置数据源只读。
如果标识符需要引用,则应使用 SQLGetInfo SQL_IDENTIFIER_QUOTE_CHAR
调用从驱动程序返回此信息。
出于调试目的,从驱动程序检索 SQLGetInfo SQL_DBMS_VER
和 SQL_DBMS_NAME。
可以在 CDatabase
的 HDBC 上调用 SQLSetStmtOption SQL_QUERY_TIMEOUT
和 SQL_ASYNC_ENABLE。
可以使用任何或所有参数 NULL 调用 SQLError
。
当然,必须支持 SQLAllocEnv
、SQLAllocConnect
、SQLDisconnect
和 SQLFreeConnect
。
ExecuteSQL
除了分配和释放临时 HSTMT,ExecuteSQL
还调用 SQLExecDirect
、SQLFetch
、SQLNumResultCol
和 SQLMoreResults
。 可以在 HSTMT 上调用 SQLCancel
。
GetDatabaseName
将调用 SQLGetInfo SQL_DATABASE_NAME
。
BeginTrans、CommitTrans、Rollback
如果发出事务请求,将调用 SQLSetConnectOption SQL_AUTOCOMMIT
和 SQLTransact SQL_COMMIT
、SQL_ROLLBACK 和 SQL_AUTOCOMMIT。
CRecordsets
必须支持 SQLAllocStmt
、SQLPrepare
、SQLExecute
(对于 Open
和 Requery
)、SQLExecDirect
(对于更新操作)、SQLFreeStmt
。 将在各种时间对结果集调用 SQLNumResultCols
和 SQLDescribeCol
。
SQLSetParam
广泛用于绑定参数数据和 DATA_AT_EXEC 功能。
SQLBindCol
广泛用于向 ODBC 注册输出列数据存储位置。
两个 SQLGetData
调用用于检索 SQL_LONG_VARCHAR 和 SQL_LONG_VARBINARY 数据。 第一次调用尝试通过调用 cbMaxValue 为 0 但具有有效的 pcbValue 的 SQLGetData
来查找列值的总长度。 如果 pcbValue 保留 SQL_NO_TOTAL,则会引发异常。 否则,会分配 HGLOBAL,并进行另一个 SQLGetData
调用来检索整个结果。
更新
如果请求悲观锁定,则会查询 SQLGetInfo SQL_LOCK_TYPES
。 如果不支持 SQL_LCK_EXCLUSIVE,则会引发异常。
尝试更新 CRecordset
(快照或动态集)将导致分配第二个 HSTMT。 对于不支持第二个 HSTMT 的驱动程序,游标库将模拟此功能。 遗憾的是,这有时可能意味着在处理第二个 HSTMT 的请求之前,迫使第一个 HSTMT 上的当前查询完成。
将在更新操作期间调用 SQLFreeStmt SQL_CLOSE
、SQL_RESET_PARAMS 和 SQLGetCursorName
。
如果 outputColumns 中有 CLongBinary,则必须支持 ODBC 的 DATA_AT_EXEC 功能。 这包括从 SQLExecDirect
、SQLParamData
和 SQLPutData
返回 SQL_NEED_DATA。
执行后调用 SQLRowCount
以验证只有 1 条记录已由 SQLExecDirect
更新。
只进游标
只有 SQLFetch
对 Move
操作是必需的。 请注意,只进游标不支持更新。
快照游标
快照功能需要 SQLExtendedFetch
支持。 如上所述,ODBC 游标库将检测驱动程序何时不支持 SQLExtendedFetch
,并本身提供必要的支持。
SQLGetInfo
、SQL_SCROLL_OPTIONS 必须支持 SQL_SO_STATIC。
动态集游标
下面是打开动态集所需的最低支持:
SQLGetInfo
、SQL_ODBC_VER 必须返回 >“01”。
SQLGetInfo
、SQL_SCROLL_OPTIONS 必须支持 SQL_SO_KEYSET_DRIVEN。
SQLGetInfo
、SQL_ROW_UPDATES 必须返回“Y”。
SQLGetInfo
、SQL_POSITIONED_UPDATES 必须支持 SQL_PS_POSITIONED_DELETE 和 SQL_PS_POSITIONED_UPDATE。
此外,如果请求悲观锁定,则会调用具有 irow 1、fRefresh FALSE 和 fLock SQL_LCK_EXCLUSIVE 的 SQLSetPos
。