news 2026/7/7 19:42:55

汇编语言全接触-37.连接数据源

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
汇编语言全接触-37.连接数据源

本教程中,我们将学习使用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, 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

ConnectionHandle. 要使用的连接句柄.

pDSN. 指向DSN的指针.

DSNLength. DSN的长度

pUserName. 指向用户名的指针

NameLength. 用户名的长度

pPassword. 指向该用户名所使用密码的指针

PasswordLength. 密码的长度

在最小情况下, 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

ConnectionHandle连接句柄

hWnd 应用程序窗口句柄.如果这个参数被置为NULL,驱动程序将不会为用户显示一个对话框来显示更多信息(如果有的话).

pInConnectString 指向连接字符串的指针. 这是一个ASCIIZ字符串,格式由要连接的具体ODBC驱动程序描述.它描述了驱动程序名、数据源及其他附加属性.连接字符串的具体描述请参见MSDN,这里不再细述.

InStringLength 连接字符串的长度.

pOutConnectString 指向将要被填入完整连接字符串的缓冲区的指针.这个缓冲区将至少有1,024字节长.这听上去使人困惑。事实上,我们提供的连接字符串会不完整,这时,ODBC驱动程序会提示用户更多信息.接下来ODBC驱动程序会根据所有可能的信息创建一个完整的连接字符串并将其放入缓冲区。即使我们提供的连接字符串已经可以工作了,这个缓冲区也会填入更多的属性值.这个参数的目的是我们可以保存完整连接字符串来为接下来的连接做准备。

OutBufferSize 由pOutConnectString指向的缓冲区的长度.

pOutConnectStringLength 指向一个双字的指针,用来接收由ODBC驱动程序返回的完整连接字符串的长度。

DriverCompletion 一个标志用来指示ODBC管理器/驱动程序是否将提示用户更多信息.但是,这个标志取决于是否在调用本函数时传送了hWnd 参数一个窗口句柄。如果没有,即使该标志被设置,ODBC管理器/驱动程序也不会提示用户.可能值如下:

SQL_DRIVER_PROMPT

ODBC驱动程序提示用户输入信息。驱动程序将利用这些信息来创建连接字符串.

SQL_DRIVER_COMPLETE

SQL_DRIVER_COMPLETE_REQUIRED

仅当用户提供的连接字符串不完全时, ODBC驱动程序才会提示用户.

SQL_DRIVER_NOPROMPT

ODBC驱动程序将不会提示用户.

例子:

.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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/7 19:24:29

SpringBoot整合Swagger:快速构建专业API文档的完整指南

SpringBoot整合Swagger:快速构建专业API文档的完整指南 【免费下载链接】springboot-guide SpringBoot2.0从入门到实战! 项目地址: https://gitcode.com/gh_mirrors/sp/springboot-guide 还在为手动维护API文档而烦恼吗?🤔…

作者头像 李华
网站建设 2026/7/7 0:05:30

SOA开发效率提升300%:AI对比传统开发全流程实测

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 开发一个物流跟踪SOA系统并进行效率对比:1. 传统方式手动开发核心服务(基准组) 2. 使用快马平台AI生成相同功能(实验组) …

作者头像 李华
网站建设 2026/7/7 2:36:37

注册表入门指南:从零开始学习Windows核心配置

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 创建一个交互式注册表学习应用,功能包括:1. 3D可视化注册表结构 2. 模拟操作沙盒环境 3. 常见场景分步指导 4. 安全操作测验 5. 实时错误检查。要求使用Elec…

作者头像 李华
网站建设 2026/7/7 9:09:26

告别快捷键冲突:让Reor AI笔记操作行云流水

"为什么按了快捷键却毫无反应?"这大概是每个Reor用户都曾遭遇的困扰。当你正沉浸于AI辅助的创作思绪中,突然发现最常用的CtrlN失灵了,那种挫败感足以打断所有灵感。别担心,今天我们就来彻底解决这个恼人的问题&#xff…

作者头像 李华
网站建设 2026/7/6 12:44:54

响应式编程VS传统编程:开发效率与性能全面对比

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 创建两个功能相同的服务:一个使用传统Spring MVC实现,一个使用Spring WebFlux实现。两个服务都要提供相同的REST API接口,包括用户认证、数据查询…

作者头像 李华
网站建设 2026/7/7 10:39:02

miniaudio左修剪节点:高效音频静音检测与智能剪辑技术详解

miniaudio左修剪节点:高效音频静音检测与智能剪辑技术详解 【免费下载链接】miniaudio Audio playback and capture library written in C, in a single source file. 项目地址: https://gitcode.com/gh_mirrors/mi/miniaudio miniaudio作为一款轻量级C语言音…

作者头像 李华