连接数据源

本教程中,我们将学习使用ODBC APIs的细节.

因为我们的程序并不与ODBC驱动程序直接通信,而是通过ODBC管理器来定义一系列APIs供你的程序调用以完成工作,所以我们需要包含odbc32.inc和odbc32.lib文件,当然还有windows.inc。

连接数据源需要以下几步:

  1. 分配一个环境句柄(environment handle). 在进行每个ODBC任务(session)时仅需这样做一次.一旦获得了句柄,我们就可修改环境属性来适合我们的需要。你可以把这想象为在DB工作中创建一个workspace.
  2. 确认将使用的ODBC的版本. 你可在ODBC 2.x版和3.x版间选择.他们在很多方面存在不同,因此本步骤是必须的以使得ODBC管理器它将用何种语法与用户程序通讯,及如何解释用户程序的命令.
  3. 分配一个连接句柄.这个步骤可看作创建一个空连接.我们还没有指定使用那一个驱动程序,连接那一个数据库.这些信息将在稍后来写入.
  4. 建立一个连接.可通过调用ODBC函数来建立连接.

当连接完成时,必须通过以下步骤来关闭和销毁它:

  1. 断开与数据源的连接.
  2. 释放连接句柄.
  3. 释放环境句柄 (如果不再需要在这个环境中作更多连接)

分配一个句柄

在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.libSQLAllocHandle的入口是_SQLAllocHandle@12. 就是说这个函数的参数的组合长度为12字节(3 dwords).然而,这不是说C函数的原型不对. SQLAllocHandle会只用HandleType的底位字并忽略高位字.因此C函数原型是功能上(functionally)正确而我们的汇编函数原型反映了实际.

结束了SQL类型的讨论,我们来看一看函数的参数和返回值。.

SQL_HANDLE_ENV 环境句柄(Environment handle)
SQL_HANDLE_DBC 连接句柄(Connection handle)
SQL_HANDLE_STMT 语句句柄(Statement handle)
SQL_HANDLE_DESC 描述符句柄(Descriptor handle)

描述符是一个数据集合描述了一个SQL语句的参数或一个结果集的列数, 视应用程序或驱动程序而定。

SQLAllocHandle 可能的返回值如下:

SQL_SUCCESS 函数成功完成.
SQL_SUCCESS_WITH_INFO 函数成功完成,但带回非致命错误或警告.
SQL_ERROR 函数调用失败.
SQL_INVALID_HANDLE 传送给函数的句柄非法.

无论函数的调用成功还是失败,我们都可通过调用SQLGetDiagRecSQLGetDiagField函数来获得更多的信息.它们与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.你也许猜到了,还有类似的函数如 SQLSetConnectAttrSQLSetStmtAttr. SQLSetEnvAttr原型如下:

SQLSetEnvAttr proto EnvironmentHandle:DWORD,
Attribute:DWORD,
ValuePtr:DWORD, StringLength:DWORD

这个函数的返回值与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, SQL_ATTR_ODBC_VERSION, SQL_OV_ODBC3, NULL
.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO
invoke SQLAllocHandle, SQL_HANDLE_DBC, hEnv, addr hConn
.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO

建立一个连接

我们现在要通过特定的ODBC驱动程序来连接数据源.通过这三个ODBC函数来达成这个目标.它们为我们提供了好几层"选择".

SQLConnect Core 这是最简单的函数。它只需要数据源名(DSN,Data source name)和可选的用户名和密码.它不提供任何GUI选项例如向用户显示一个对话框来提供更多信息。如果你已经有了需要使用的数据库的DSN就可以使用这个函数.
SQLDriverConnect Core 这个函数提供了较SQLConnect更多的选择.我们可以连接一个没有在系统信息内定义的数据源。如没有DSN.另外,我们可以指定这个函数是否需要显示一个对话框来为用户提供更多信息.例如,如果用户遗漏了数据库的名字,它会指导ODBC驱动程序显示一个对话框,让用户来选择想连接的数据库.
SQLBrowseConnect Level 1 这个函数允许在运行时(RunTime)枚举数据源.比SQLDriverConnect更加灵活。因为可以多次顺序调用SQLBrowseConnect,而每次提供给使用者更多的专用信息直到最后获得需要的连接句柄.

我将先检查SQLConnect函数.要使用 SQLConnect,你应先知道什么是DSN. DSN是数据源名(Data Source Name)的缩写,是一个唯一标识某数据源的字符串。一个DSN标识了一个包含了如何连接某一特定的数据源的信息的数据结构.这个信息包括要使用何种ODBC驱动程序及要连接哪个数据库.我们可以通过控制面板中的32位ODBC数据源来创建、修改及删除DSN.

SQLConnect的语法如下:

SQLConnect proto ConnectionHandle:DWORD
pDSN:DWORD,
DSNLength:DWORD,
pUserName:DWORD,
NameLength:DWORD,
pPassword:DWORD,
PasswordLength:DWORD

在最小情况下, SQLConnect 需要连接句柄,DSN和DSN的长度。如果数据源不需要的话,用户名和密码就不是必须的.函数的返回值与SQLAllocHandle的返回值相同.

假设我们的系统中有一个叫做"Sales" 的DSN并且我们想连接这个数据源.我们可以这样做:

.data
DSN db "Sales",0

.code
......
invoke SQLConnect, hConn, addr DSN, sizeof DSN,0,0,0,0

SQLConnect 的缺点是:在连接一个数据源之前,我们必须创建它的DSN. SQLDriverConnect 提供了更大的灵活性.它的语法如下:

SQLDriverConnect proto ConnectionHandle:DWORD,
hWnd:DWORD,
pInConnectString:DWORD,
InStringLength:DWORD,
pOutConnectString:DWORD,
OutBufferSize:DWORD,
pOutConnectStringLength:DWORD, DriverCompletion:DWORD

例子:

.data
strConnect db "DBQ=c:\data\test.mdb;DRIVER={Microsoft Access Driver (*.mdb)};",0

.data?
buffer db 1024 dup(?)
OutStringLength dd ?

.code
.....
invoke SQLDriverConnect, hConn, hWnd, addr strConnect, sizeof strConnect, addr buffer, sizeof buffer, addr OutBufferLength, SQL_DRIVER_COMPLETE

断开与数据源的连接

在连接顺利完成后,我们就可以对数据源进行查询及其他操作.这些将在下一节讨论.现在假设我们已完成了对数据源的操作,就可以通过调用SQLDisconnect来断开与它的连接. 这个函数非常简单(就象那悲伤而冷酷的现实:毁灭总比创造容易的多).它只需要一个参数:连接句柄。

invoke SQLDisconnect, hConn

释放连接与环境句柄

在顺利地断开连接后,我们现在可以调用SQLFreeHandle函数来销毁连接句柄和环境句柄. 这是由ODBC 3.x提供的新函数.它替代了SQLFreeConnect, SQLFreeEnvSQLFreeStmt函数. SQLFreeHandle语法如下:

SQLFreeHandle proto HandleType:DWORD, Handle:DWORD

For example:

invoke SQLFreeHandle, SQL_HANDLE_DBC, hConn
invoke SQLFreeHandle, SQL_HANDLE_ENV, hEnv

[<<] [index] [>>]


[Iczelion's Win32 Assembly Homepage]

[The Chinese Portion Is Translated By Orochi ,2000.8.21 ]