
简介面向VB6编程学习者与需要维护老旧Access数据库项目的开发人员这份PDF文档聚焦VB6通过ADO操作Access数据库的常见方法。内容以实例为主覆盖数据库连接、记录集遍历、SQL增删改查及简单用户登录实现适合从零了解VB6Access交互的初学者。资源为单个PDF文件压缩包仅26KB体积小巧便于快速查阅核心代码片段。目前已有98人学习浏览。文档内含多个可直接套用的代码示例如例1演示查询并将字段加入组合框例2展示登录验证与添加、删除、更新语句写法例3、例4补充了窗体加载时连接数据库及状态判断的思路。读者可从中掌握ADO组件引用、Connection与Recordset对象的配合使用以及如何用Execute执行SQL命令从而独立编写常见数据库操作代码。1. 为什么VB6项目还要折腾Access数据库很多工厂的计件系统、学校的机房管理工具、银行的周边小系统至今还在用VB6搭配Access运行。Windows 10/11上这些程序照常工作但要改个报表逻辑、加个用户权限就得有人能读懂VB6代码里的数据库操作。最近整理一份《VB6Access编程中的数据库操作方法》的笔记里面几个例子覆盖了查询、登录、增删改原理到今天仍然成立。这篇文章不按文档顺序复述而是把ADO对象、连接字符串、Recordset遍历、SQL拼装这些容易出错的点单独拆开结合示例代码说明为什么要这么写。适合接手遗留项目的工程师也适合想用VB6快速做小工具的开发。需要提醒的是VB6操作Access通常不是直接打开mdb文件而是通过ADO组件建立桥梁。如果工程里没有引用Microsoft ActiveX Data Objects 2.7 Library写Dim cn As New ADODB.Connection时会直接提示“用户类型未定义”。下面从对象模型开始讲因为后面所有代码都建立在这些对象的基础上。2. ADO对象模型与连接字符串的选型2.1 引用ADO组件Microsoft ActiveX Data Objects 2.7在VB6编辑器菜单栏点击“工程”-“引用”从列表中找到并勾选Microsoft ActiveX Data Objects 2.7 Library。这是MDAC 2.7版本的组件VB6时代使用最广。有些精简系统里找不到这一项多半是MDAC或VB6 SP6运行库没有安装。安装SP6后引用列表里通常还会出现2.8版本但遗留项目大多保留2.7因为代码里用到的游标类型、锁类型枚举值在2.7和2.8里行为一致没有必要升级引起潜在兼容问题。引用之后代码里才能写New ADODB.Connection和New ADODB.Recordset。如果选择后期绑定即用CreateObject(ADODB.Connection)可以不勾选引用但这样没有智能提示运行时加载的可能是系统里最新版ADO某些枚举值需要手动定义不建议在维护项目里用。所以前期绑定是遗留VB6项目中的主流做法。2.2 Connection、Recordset、Command三个对象的分工ADO里三个核心对象各司其职Connection负责建立连接Recordset负责存放查询结果并支持游标移动Command负责执行命令、参数化查询。表格里列一下常用成员对象职责常用成员Connection建立与数据库的会话管理连接字符串和事务Open、Execute、Close、State、ConnectionStringRecordset存放SELECT结果集支持逐条遍历Open、MoveFirst、MoveNext、MoveLast、EOF、BOF、CloseCommand执行SQL命令或存储过程支持参数CommandText、Execute、Parameters实际编码中增删改可以直接用Connection.Execute执行因为不需要返回结果集查询最好用Recordset.Open因为可以遍历每一行。这样分工的好处是逻辑清晰查询走Recordset写操作走Connection.Execute避免在一个对象上混用太多方法。如果只是执行INSERT、UPDATE、DELETE根本不需要建立Recordset省掉额外的资源开销。2.3 连接字符串的写法与Access版本差异连接字符串是出错率最高的地方。标准写法如下Dim conn As ADODB.Connection Set conn New ADODB.Connection conn.ConnectionString ProviderMicrosoft.Jet.OLEDB.4.0;Data Source App.Path \aaa.mdb;Persist Security InfoFalse conn.OpenProvider指定OLE DB数据提供程序。.mdb文件对应Microsoft.Jet.OLEDB.4.0这是Access 2003及以前版本的引擎如果是.accdb文件则需要改成Microsoft.ACE.OLEDB.12.0并安装ACE运行库。Data Source后面是数据库文件的完整路径这里用App.Path动态获取程序所在目录比写死D:\路径更可靠。Persist Security InfoFalse表示连接成功后不保留密码等敏感信息对于无密码的Access数据库这个参数存在与否不影响连接但保留可以让代码更规范。有个坑需要记住Access数据库路径如果包含空格直接拼进连接字符串即可Jet引擎能正确处理。但如果路径里含有井号#或分号;就需要特殊处理。一般我建议先把连接字符串放到Debug窗口打印出来检查Debug.Print conn.ConnectionString这样能看到最终传给OLEDB的内容排查引号错位或路径截断问题比反复运行程序高效得多。还有一点Jet.OLEDB.4.0在64位系统上只能被32位进程调用VB6编译出来的EXE天然是32位所以没有影响但如果是C#等语言写的64位工具去连Access就必须把目标平台改成x86否则会报“未在本地计算机上注册Microsoft.Jet.OLEDB.4.0”。3. 从查询到遍历Recordset的打开方式与边界条件3.1 使用rs.Open执行SELECT连接建立后执行查询最常见的方法就是调用Recordset.Open。示例文档里是这么写的Dim cn As New ADODB.Connection Dim rs1 As New ADODB.Recordset Dim sql As String cn.Open ProviderMicrosoft.Jet.OLEDB.4.0;Data SourceD:\Mydb.mdb sql select * from 表名 rs1.Open sql, cn, adOpenKeyset, adLockReadOnly这里的rs1.Open一共四个关键参数分别是SQL字符串、活动连接对象、游标类型、锁类型。游标类型决定游标能否双向滚动以及是否能看到其他用户的修改。锁类型决定记录集打开后是否允许他人修改数据。表格对比一下选项值说明adOpenForwardOnly0只能向前移动最快默认值adOpenKeyset1可双向滚动能看到其他会话的修改但新记录不可见adOpenDynamic2可双向滚动实时看到所有修改资源消耗大adOpenStatic3静态快照不能看到其他会话的修改adLockReadOnly1只读默认值性能最好adLockPessimistic2悲观锁编辑时立即锁定数据源adLockOptimistic3乐观锁只有调用Update时才锁定adLockBatchOptimistic4批量更新锁如果只是把字段值填入下拉框没有任何修改需求用adOpenForwardOnly加adLockReadOnly就足够了速度也比adOpenKeyset快。示例里用adOpenKeyset其实是沿用了一些老代码的习惯不是必须。知道每种参数的含义才能根据场景选择。3.2 EOF与MoveNext不要忘记的循环终结条件遍历记录集最常见的写法是rs1.MoveFirst Do While Not rs1.EOF Combo1.AddItem rs1(字段名) rs1.MoveNext Loop rs1.Close记录集刚打开时游标停留在第一条记录上所以MoveFirst不是必须的但写上会让代码更明确。EOF是End Of File的意思当游标移动到最后一条记录之后EOF变为True。Do While Not rs1.EOF表示只要还有记录就一直循环。每次处理完一条记录必须调用MoveNext把游标推向下一条。如果漏掉这行游标永远停在第一条循环永不结束程序直接卡死。需要区分BOF和EOFBOF在游标位于第一条记录之前时是TrueEOF在游标位于最后一条记录之后是True。空记录集打开后BOF和EOF同时为True。所以判断有没有查询到结果只需要看rs1.EOF即可。用RecordCount判断是不可靠的因为某些游标类型下RecordCount会返回-1。3.3 带条件的查询防止SQL注入的引号转义实际开发中查询语句经常要拼接用户输入比如登录功能sql Select * From [UserInfo] where User UserName Rs.Open sql, Conn, 1, 3这段SQL在用户名为Alice时变成了Select * From [UserInfo] where UserAlice能正常工作。问题是如果用户输入的是ONeilSQL就变成了where UserONeil单引号提前闭合语法报错。更恶劣的输入是 or 11SELECT语句会返回所有记录登录直接绕过密码。正确的做法是拼接前把单引号替换成两个单引号这是Access SQL的转义规则UserName Replace(UserName, , ) sql Select * From [UserInfo] where User UserName 这样ONeil会变成ONeilSQL里解释为用户名的内容是ONeil既不会报错也不会注入。VB6下也能用ADO Command的参数化查询来彻底避免拼接但遗留项目里改造成本高。我一般建议先加一个Replace清洗再配合数据库权限限制至少能防住常规注入。4. 增删改与登录系统的完整实现4.1 用Conn.Execute执行INSERT/UPDATE/DELETE增删改操作不需要返回记录集直接用Connection.Execute执行SQL即可。示例文档给出三条语句 添加 SQL Insert Into [UserInfo](User,Password) Values(aaaa,1234) Conn.Execute SQL 删除 SQL Delete From [UserInfo] Where Useraaaa Conn.Execute SQL 更新 SQL Update [UserInfo] Set Passwordabcdefg Where Useraaaa Conn.Execute SQL三条SQL对应三种数据变更场景。INSERT用于插入新记录字段列表和值列表必须一一对应DELETE必须带WHERE条件否则会清空整张表UPDATE同样要确认WHERE条件否则会更新所有行。表名和字段名用方括号包住是为了避免与Jet引擎的保留字冲突比如User在某些上下文会被识别为函数。Execute方法还支持第二个参数返回受影响的行数Dim affected As Long Conn.Execute SQL, affected MsgBox 影响了 affected 条记录这个参数能帮我们确认SQL到底执行了几条比如更新时affected为0说明条件没匹配到任何行需要检查表里有没数据。4.2 登录系统示例拆解从InputBox到密码比对文档里的登录系统可以拆成下面这种清晰版本Private Sub Command1_Click() Dim Conn As New ADODB.Connection Dim Rs As New ADODB.Recordset Dim UserName As String, Password As String Dim sql As String Conn.Open ProviderMicrosoft.Jet.OLEDB.4.0;Data SourceD:\mydb.mdb UserName InputBox(请输入用户名) Password InputBox(请输入用户密码) 实际开发中应使用文本框输入这里仅为演示 sql Select * From [UserInfo] where User Replace(UserName, , ) Rs.Open sql, Conn, 1, 3 If Rs.EOF Then MsgBox 没有找到此用户 Else If Rs(Password) Password Then MsgBox 登录成功 Else MsgBox 密码错误 End If End If Rs.Close Conn.Close End Sub这里的核心是先通过用户名查记录再比较密码。注意SQL里只带用户名条件不带密码条件原因是如果同时把密码写进SQL查询不到记录时无法区分是用户名错误还是密码错误对于排查问题很不友好。先把用户记录取出来再用Rs(Password)和输入密码比对能给出明确的“没有找到此用户”和“密码错误”两种提示。登录判断里还隐含着空结果判断当用户名不存在时Rs.EOF为True直接进第一条分支。这比先取RecordCount再判断更可靠因为EOF是实时状态不会受游标类型影响。4.3 连接状态判断与资源释放数据库连接是有限资源用完必须关闭。打开连接前可以先判断状态避免重复打开If conn.State adStateClosed Then conn.Open End IfadStateClosed值为0adStateOpen值为1。文档例3是用Select Case把状态翻译成字符串方便弹窗调试。在生产代码里我们一般直接用If判断不需要显示给用户。关闭顺序有讲究先关Recordset再关Connection最后把对象引用置空rs.Close Set rs Nothing conn.Close Set conn Nothing如果先关ConnectionRecordset还持有连接引用连接可能关不掉或者触发运行时错误。Set Nothing是为了尽早释放COM对象在VB6里如果不写对象会等到过程结束时才释放连续打开多个窗体时资源占用明显增长。5. 进阶错误处理与防坑清单5.1 用On Error GoTo捕获数据库异常数据库操作容易出错常见问题包括路径不存在、表名拼错、SQL语法错误、文件被占用。VB6默认的错误弹窗只显示英文错误号和描述用户看不懂。可以给连接和查询过程加统一处理On Error GoTo ErrHandler conn.Open Exit Sub ErrHandler: MsgBox 错误 Err.Number Err.Description On Error Resume Next conn.Close Set conn NothingExit Sub放在成功路径末尾避免成功执行后掉进错误分支。Err.Number和Err.Description能拿到具体错误信息方便定位。On Error Resume Next放在关连接之前确保即使连接已经断开也不会再次触发错误。5.2 连接复用与全局连接对象如果多个窗体都要访问同一个Access数据库每次Open/Close连接会浪费不少时间。建议在标准模块里定义全局连接Public gConn As ADODB.Connection Public Sub OpenDB() Set gConn New ADODB.Connection gConn.Open ProviderMicrosoft.Jet.OLEDB.4.0;Data Source App.Path \app.mdb End Sub程序启动时调用OpenDB所有窗体共用这个连接。退出前统一关闭。这样能明显加快连表查询速度也方便维护连接字符串。5.3 防坑清单路径、Unicode、引擎兼容App.Path指向程序exe所在目录。如果程序装在C:\Program Files下Access数据库写操作可能因为目录权限失败应该把数据库放到App.Path下的可写子目录或要求管理员权限运行。Access文本字段里的中文和Unicode字符拼接SQL时注意字段类型设置为“文本”赋值语句两侧用单引号。如果出现乱码检查数据库字段排序规则或改用参数查询。.mdb和.accdb引擎不通用。Jet.OLEDB.4.0只能打开.mdbACE.OLEDB.12.0可以打开两种但需要预装ACE运行库。给客户部署时先把这些依赖装上。调试SQL时把拼接完成的sql打印到立即窗口Debug.Print sql然后复制这个字符串到Access查询设计器的SQL视图里直接执行比对结果。这样能快速定位是SQL语法问题还是VB6变量取值问题。本文还有配套的精品资源点击获取