连接数据源
本教程中,我们将学习使用ODBC APIs的细节.
由于我们的程序并不与ODBC驱动程序直接通信,而是通过ODBC管理器来定义一系列APIs供你的程序调用以完成任务,所以我们需求包含odbc32.inc和odbc32.lib文件,当然还有windows.inc。
连接数据源需求以下几步:
分配一个环境句柄(environment handle). 在进行每个ODBC任务(session)时仅需这样做一次.一旦获得了句柄,我们就可修正环境属性来适合我们的需求。你可以把这想象为在DB任务中创建一个workspace. 确认将使用的ODBC的版本. 你可在ODBC 2.x版和3.x版间选择.他们在很多方面存在不同,因此本步骤是必须的以使得ODBC管理器它将用何种语法与用户程序通讯,及如何解释用户程序的命令. 分配一个连接句柄.这个步骤可看作创建一个空连接.我们还没有指定使用那一个驱动程序,连接那一个数据库.这些信息将在稍后来写入. 建立一个连接.可通过调用ODBC函数来建立连接.
当连接完成时,必须通过以下步骤来关闭和销毁它:
断开与数据源的连接. 释放连接句柄. 释放环境句柄 (如果不再需求在这个环境中作更多连接) 分配一个句柄
在ODBC 3.x版本以前,我们需求调用很多独立的函数来分配环境、连接和语句句柄(SQLAllocEnv, SQLAllocConnect, SQLAllocStmt).而在ODBC 3.x中, 这些函数被SQLAllocHandle所代替,语法如下:
SQLRETURN SQLAllocHandle( SQLSMALLINT HandleType, SQLHANDLE InputHandle, SQLHANDLE * OutputHandlePtr );
看上去挺麻烦,简化一下看看:
SQLAllocHandle proto HandleType:DWORD,
InputHandle:DWORD,
OutputHandlePtr:DWORD
SQLRETURN 被定义为SQLSMALLINT类型.而 SQLSMALLINT被定义为短整型,例如一个字(16 bits). 所以该函数的前往值在ax中,而不是 eax. 这是很重要的.但是Win32下函数的参数是通过32位堆栈来传送的.即便这个参数只是一个字长(16位),它也应被扩展为32位.这就是为什么HandleType被说明为双字(dword)而不是字(word).看一下导入库 odbc32.lib,SQLAllocHandle的入口是_SQLAllocHandle@12. 就是说这个函数的参数的组合长度为12字节(3 dwords).然而,这不是说C函数的原型不对. SQLAllocHandle会只用HandleType的底位字并忽略高位字.因此C函数原型是功用上(functionally)正确而我们的汇编函数原型反映了实际.
结束了SQL类型的讨论,我们来看一看函数的参数和前往值。.
HandleType 是一个常数,定义了希望分配的句柄类型.可能值如下: SQL_HANDLE_ENV 环境句柄(Environment handle)SQL_HANDLE_DBC连接句柄(Connection handle)SQL_HANDLE_STMT语句句柄(Statement handle)SQL_HANDLE_DESC描述符句柄(Descriptor handle)
描述符是一个数据集合描述了一个SQL语句的参数或一个结果集的列数, 视使用程序或驱动程序而定。
InputHandle 是指向父"文本"的句柄.就是说,如果你想分配一个连接句柄, 需求通过一个环境句柄由于连接将在那个环境的文本中建立.如果你想分配一个环境句柄,这个参数必须为SQL_HANDLE_NULL (留意SQL_HANDLE_NULL在windows.inc版本1.18及其以前版本中被不正确的定义为0L.你需求删除掉"L"否则程序不会被编译通过.这是我的错,由于我担任修订windows.inc中的 SQL/ODBC部分.) 由于环境没有父文本.对于语句和描述符句柄,我们需求将连接句柄作为这个参数。 OutputHandlePtr 如果调用成功,将指向一个双字,其中包含了被分配的句柄.
SQLAllocHandle 可能的前往值如下:
SQL_SUCCESS函数成功完成.SQL_SUCCESS_WITH_INFO函数成功完成,但带回非致命错误或警告. SQL_ERROR函数调用失败.SQL_INVALID_HANDLE传送给函数的句柄非法.
无论函数的调用成功还是失败,我们都可通过调用SQLGetDiagRec或SQLGetDiagField函数来获得更多的信息.它们与Win32 API中的GetLastError很类似.
例子:
.data?
hEnv dd ?
.code
invoke SQLAllocHandle, SQL_HANDLE_ENV, SQL_HANDLE_NULL, addr hEnv
.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO
选择ODBC的版本
分配完环境句柄后,我们需求设置一个环境属性SQL_ATTR_ODBC_VERSION以适当的值.设置环境属性可通过调用函数SQLSetEnvAttr.你也许猜到了,还有类似的函数如 SQLSetConnectAttr和SQLSetStmtAttr. SQLSetEnvAttr原型如下:
SQLSetEnvAttr proto EnvironmentHandle:DWORD,
Attribute:DWORD,
ValuePtr:DWORD, StringLength:DWORD
EnvironmentHandle. 与字面意思一样, 它包含了要设置属性的环境句柄. Attribute. 这是一个常数,表示用户需求设置的属性.对我们而言,是SQL_ATTR_ODBC_VERSION.可以从MSDN中查看全部列表. ValuePtr. 这个参数的意义由希望设置的属性值决定.如果属性值是32位的, 这个参数将被认为是想要设置的属性值.如果属性值是一个字符串或二进制缓冲区,它就被解释为指向字符串或缓冲区的指针.如果我们指定了要设置的属性为SQL_ATTR_ODBC_VERSION, 这个参数我们可以填入SQL_OV_ODBC3和SQL_OV_ODBC2这两个可能值,分别对应ODBC 3.x和2.x. StringLength. 由ValuePtr指向的值的长度. 如果这个值是字符串或二进制缓冲区,这个参数一定是合法的. 如果想设置的属性是一个双字,这个参数被忽略.由于 SQL_ATTR_ODBC_VERSION属性包含一个双字的值,我们可以只给它赋为NULL.
这个函数的前往值与SQLAllocHandle相反.
例子:
.data?
hEnv dd ?
.code
invoke SQLAllocHandle, SQL_HANDLE_ENV, SQL_HANDLE_NULL, addr hEnv
.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO
invoke SQLSetEnvAttr, hEnv, SQL_ATTR_ODBC_VERSION, SQL_OV_ODBC3, NULL
.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO
分配连接句柄
这一步与分配环境句柄类似,我们可以通过调用SQLAllocHandle函数并赋以不同的参数值来完成.
例子:
.data?
hEnv dd ?
hConn dd ?
.code
invoke SQLAllocHandle, SQL_HANDLE_ENV, SQL_HANDLE_NULL, addr hEnv
.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO
invoke SQLSetEnvAttr, hEnv,