链接表能删了:Access 直连 SQL Server,DAO 绑窗体 + ADO 参数查询完整代码

发布时间:2026/7/23 22:01:02

链接表能删了:Access 直连 SQL Server,DAO 绑窗体 + ADO 参数查询完整代码
摘要后台是 SQL Server 却不想用链接表本文介绍 DAO 直连绑定窗体和 ADO 参数化查询两种方案配完整可运行代码直接拿走用。access开发|access培训|access框架|请添加edonsoft。Hi大家好上一篇讲了 Access 和 SQL Server 的差别。有读者看完之后问了一个很实际的问题后台已经是 SQL Server前端 Access 用的是链接表但现在不想用链接表了有没有别的办法让窗体继续能查数据、能编辑这个需求我遇到过不止一次原因也各不相同——有的是网络环境里链接表刷新太慢有的是服务器迁移了链接路径失效还有的是想做更严格的权限控制不想让 Access 直接看到表结构。办法有两种。一种是 DAO 直连用DBEngine.OpenDatabase在 VBA 里打开 ODBC 连接把记录集直接绑给窗体新增、修改、删除全部照常体验和链接表几乎没差别。另一种是 ADO 参数化查询用ADODB.Command带参数跑 SQL把结果填进列表框或子窗体更适合复杂筛选、存储过程调用以及需要控制事务的保存操作。两种都给完整代码。先说 DAO 直连DAOData Access Objects是 Access 的原生数据访问接口很多人不知道它其实也能不靠链接表直接连 ODBC 数据源。做法是用DBEngine.OpenDatabase打开一个 ODBC 连接然后拿到的DAO.Recordset直接赋给窗体的Recordset属性窗体就有数据了。这种方式最大的好处是窗体保持绑定状态新增、修改、删除照常用Access 的导航按钮、记录锁都还在几乎和链接表的使用体验一样只是数据源换成了 ODBC 直连。DAO 方案完整代码新建一个标准模块命名modSQLConn把下面的连接字符串函数放进去后面窗体代码会用到Option Compare Database Option Explicit 返回 SQL Server 无 DSN 连接字符串 根据实际情况修改 SERVER、DATABASE Public Function SQLConnStr() As String SQLConnStr ODBC; _ DRIVER{ODBC Driver 18 for SQL Server}; _ SERVERSQL01; _ DATABASESalesDb; _ Trusted_ConnectionYes; _ EncryptYes; _ TrustServerCertificateYes; End Function然后打开需要绑定的窗体设计视图把窗体的记录源清空在窗体模块里写Option Compare Database Option Explicit 注意必须声明在模块顶部不能放在 Form_Load 里 生命周期和窗体绑定窗体关闭前不能释放 Private mDb As DAO.Database Private mRs As DAO.Recordset Private Sub Form_Load() Dim sql As String 打开 ODBC 直连不用预先建 DSN dbDriverNoPrompt连接失败直接报错不弹驱动选择框 Set mDb DBEngine.OpenDatabase( _ , dbDriverNoPrompt, False, SQLConnStr()) 写你真正需要的查询必须包含主键列否则记录集不可更新 sql SELECT OrderID, CustomerID, OrderDate, Amount, Remark _ FROM dbo.Orders _ ORDER BY OrderDate DESC; dbOpenDynaset动态集支持编辑 dbSeeChanges表有 IDENTITY 自增列时必须加否则新增报错 Set mRs mDb.OpenRecordset(sql, dbOpenDynaset, dbSeeChanges) 把记录集绑给窗体完成后窗体控件自动按字段名匹配 Set Me.Recordset mRs End Sub Private Sub Form_Unload(Cancel As Integer) 窗体关闭时释放资源顺序不能反 If Not mRs Is Nothing Then mRs.Close Set mRs Nothing End If If Not mDb Is Nothing Then mDb.Close Set mDb Nothing End If End Sub窗体里的文本框控件名字只要和查询字段名一致不区分大小写绑定自动生效不需要手动设控件来源但是你的控件一定要添加控件来源。有三个地方容易出问题写这段代码之前先说清楚。mDb和mRs必须声明在窗体模块顶部不能放在Form_Load里。放进过程里就成了局部变量Form_Load跑完就释放窗体打开之后数据随时会变成空白或者弹出对象无效的错误。这是我见过最多人踩的地方而且报错时机不固定有时候立刻报有时候要等用户翻几页记录才出。查询必须包含主键且查询本身可更新。两表联接、带GROUP BY、带DISTINCT的查询基本上都是只读的这种结果集赋给窗体之后能看数据但改不了。如果窗体只需要显示问题不大如果需要编辑就得把查询拆开或者改用 ADO 加存储过程来保存。dbSeeChanges这个参数SQL Server 表有IDENTITY自增列时必须加。不加的话新增一条记录之后 Access 找不到刚插入的那行会弹找不到记录。加上之后 Access 在 INSERT 完成后会自动定位到新行这个问题就消失了。加筛选条件如果窗体需要按条件筛选比如按订单日期范围不要拼接 SQL 字符串改用Recordset.FilterPrivate Sub btnFilter_Click() Dim d1 As String Dim d2 As String 取文本框里的日期转成 SQL Server 认识的格式 d1 Format(Me.txtDateFrom, yyyy-mm-dd) d2 Format(Me.txtDateTo, yyyy-mm-dd) Filter 条件用字段名日期用单引号括起来 mRs.Filter OrderDate d1 AND OrderDate d2 用筛选后的克隆集重新绑窗体 Set Me.Recordset mRs.OpenRecordset() End Sub如果筛选条件变化很大比如字段都不固定更简单的做法是重新执行mDb.OpenRecordset用新 SQL 替换旧的再重新赋给Me.Recordset。再说 ADO 参数化查询ADOActiveX Data Objects连接 SQL Server 时走 OLE DB 或 ODBC写法和连接其他数据库基本一样。我一般在这几种情况下选 ADO 而不是 DAO筛选条件多、带多个参数的查询需要调用 SQL Server 存储过程执行写入操作时需要拿回影响行数或者输出参数。ADO 的一个重要习惯是参数化——用?占位符传值不把变量直接拼进 SQL 字符串。日期格式、单引号转义这些问题直接绕开SQL 注入的风险也没有了。我见过不少人图省事用WHERE CustomerID Me.cboCustomer这种拼法字段是数字还好一旦遇到字符串或者日期调试起来很麻烦。ADO 公共模块用 ADO 之前要先在 Access 引用库里勾上Microsoft ActiveX Data Objects。VBE 菜单 → 工具 → 引用找到Microsoft ActiveX Data Objects 6.1 Library或者 2.8装了什么版本就选哪个勾上确定。没有这一步代码里的ADODB.Connection会报用户自定义类型未定义。新建标准模块modADOOption Compare Database Option Explicit 建立 ADO 连接成功返回 ADODB.Connection失败返回 Nothing 调用方负责关闭和释放 Public Function ADO_Connect() As ADODB.Connection Dim conn As ADODB.Connection Set conn New ADODB.Connection OLE DB Provider for SQL Server MSOLEDBSQL 是微软 2018 年后推荐的新驱动需独立安装 https://learn.microsoft.com/zh-cn/sql/connect/oledb/download-oledb-driver-for-sql-server 如果没装换成 SQLNCLI11SQL Server 2012 自带 ProviderSQLNCLI11; OLE DB Windows 集成验证用 Integrated SecuritySSPI 不是 ODBC 的 Trusted_ConnectionYes那个 OLE DB 不认 改用 SQL 账号的话替换为UIDsa;PWDyourpwd; conn.ConnectionString _ ProviderMSOLEDBSQL; _ ServerSQL01; _ DatabaseSalesDb; _ Integrated SecuritySSPI; _ TrustServerCertificateyes; On Error GoTo ConnErr conn.Open Set ADO_Connect conn Exit Function ConnErr: Set conn Nothing Set ADO_Connect Nothing MsgBox 连接 SQL Server 失败 Err.Description, vbCritical End Function如果机器上没有 MSOLEDBSQL也可以换成 ODBC 方式ProviderMSDASQL;DRIVER{ODBC Driver 18 for SQL Server};SERVERSQL01;...两种写法功能上没区别Driver 18 装了就能用。参数化查询 Demo按客户和日期范围查询订单 查询订单结果填入列表框 lstOrders lstOrders 的列数需要提前设好列宽也要配好 Private Sub btnQuery_Click() Dim conn As ADODB.Connection Dim cmd As ADODB.Command Dim rs As ADODB.Recordset Dim rows As String Set conn ADO_Connect() If conn Is Nothing Then Exit Sub Set cmd New ADODB.Command cmd.ActiveConnection conn 参数用 ? 占位不拼字符串 cmd.CommandText _ SELECT OrderID, CustomerName, OrderDate, Amount _ FROM dbo.Orders _ WHERE CustomerID ? _ AND OrderDate BETWEEN ? AND ? _ ORDER BY OrderDate DESC; cmd.CommandType adCmdText 按顺序追加参数类型、方向、大小、值 adInteger, adDate, adDate cmd.Parameters.Append cmd.CreateParameter(CustID, adInteger, adParamInput, , CLng(Me.cboCustomer)) cmd.Parameters.Append cmd.CreateParameter(D1, adDate, adParamInput, , CDate(Me.txtDateFrom)) cmd.Parameters.Append cmd.CreateParameter(D2, adDate, adParamInput, , CDate(Me.txtDateTo)) Set rs cmd.Execute 用 ValueList 方式填列表框 也可以改用 rs 直接赋给子窗体的 Recordset rows Do While Not rs.EOF rows rows rs(OrderID) ; _ rs(CustomerName) ; _ Format(rs(OrderDate), yyyy-mm-dd) ; _ Format(rs(Amount), #,##0.00) ; rows rows Chr(10) rs.MoveNext Loop rs.Close conn.Close Set rs Nothing Set cmd Nothing Set conn Nothing Me.lstOrders.RowSourceType Value List Me.lstOrders.RowSource rows End Sub参数化执行 Demo保存一条订单 保存窗体上的订单数据到 SQL Server 成功返回 True失败返回 False Public Function SaveOrder( _ ByVal customerID As Long, _ ByVal orderDate As Date, _ ByVal amount As Currency, _ ByVal remark As String _ ) As Boolean Dim conn As ADODB.Connection Dim cmd As ADODB.Command Set conn ADO_Connect() If conn Is Nothing Then SaveOrder False Exit Function End If Set cmd New ADODB.Command cmd.ActiveConnection conn cmd.CommandText _ INSERT INTO dbo.Orders (CustomerID, OrderDate, Amount, Remark) _ VALUES (?, ?, ?, ?); cmd.CommandType adCmdText cmd.Parameters.Append cmd.CreateParameter(CustID, adInteger, adParamInput, , customerID) cmd.Parameters.Append cmd.CreateParameter(Date, adDate, adParamInput, , orderDate) cmd.Parameters.Append cmd.CreateParameter(Amount, adCurrency, adParamInput, , amount) cmd.Parameters.Append cmd.CreateParameter(Remark, adVarWChar, adParamInput, 500, remark) On Error GoTo SaveErr cmd.Execute conn.Close Set cmd Nothing Set conn Nothing SaveOrder True Exit Function SaveErr: MsgBox 保存失败 Err.Description, vbCritical If Not conn Is Nothing Then conn.Close Set cmd Nothing Set conn Nothing SaveOrder False End Function调用的地方很简单Private Sub btnSave_Click() If SaveOrder(Me.cboCustomer, Me.txtDate, Me.txtAmount, Me.txtRemark) Then MsgBox 保存成功, vbInformation Me.txtAmount Null Me.txtRemark Null End If End Sub调用 SQL Server 存储过程如果保存逻辑放在 SQL Server 存储过程里——比如要做库存扣减、写操作日志、或者要保证多张表同时写入——ADO 也可以直接调把CommandType换成adCmdStoredProc就行。假设 SQL Server 端有这样一个存储过程CREATEPROCEDUREdbo.usp_AddOrderCustomerIDINT,OrderDateDATE,AmountDECIMAL(18,2),RemarkNVARCHAR(500),NewOrderIDINTOUTPUT-- 返回新生成的订单号ASBEGINSETNOCOUNTON;INSERTINTOdbo.Orders(CustomerID,OrderDate,Amount,Remark)VALUES(CustomerID,OrderDate,Amount,Remark);SETNewOrderIDSCOPE_IDENTITY();ENDVBA 这边这样调Public Function CallAddOrder( _ ByVal customerID As Long, _ ByVal orderDate As Date, _ ByVal amount As Currency, _ ByVal remark As String, _ ByRef newOrderID As Long _ ) As Boolean Dim conn As ADODB.Connection Dim cmd As ADODB.Command Set conn ADO_Connect() If conn Is Nothing Then CallAddOrder False Exit Function End If Set cmd New ADODB.Command cmd.ActiveConnection conn cmd.CommandText dbo.usp_AddOrder cmd.CommandType adCmdStoredProc 改这里 输入参数 cmd.Parameters.Append cmd.CreateParameter(CustomerID, adInteger, adParamInput, , customerID) cmd.Parameters.Append cmd.CreateParameter(OrderDate, adDate, adParamInput, , orderDate) cmd.Parameters.Append cmd.CreateParameter(Amount, adCurrency, adParamInput, , amount) cmd.Parameters.Append cmd.CreateParameter(Remark, adVarWChar, adParamInput, 500, remark) 输出参数adParamOutput不传值执行后从这里读回来 cmd.Parameters.Append cmd.CreateParameter(NewOrderID, adInteger, adParamOutput, , 0) On Error GoTo SPErr cmd.Execute newOrderID cmd.Parameters(NewOrderID).Value 读取存储过程返回的新订单号 conn.Close Set cmd Nothing Set conn Nothing CallAddOrder True Exit Function SPErr: MsgBox 调用存储过程失败 Err.Description, vbCritical If Not conn Is Nothing Then conn.Close Set cmd Nothing Set conn Nothing CallAddOrder False End Function这种写法Access 前端不需要知道存储过程里写了什么库存怎么扣、日志怎么写、哪几张表要联动都在 SQL Server 里处理VBA 只管传参数、拿结果。两种方案怎么选我自己的习惯是这样区分的场景推荐方案窗体需要连续编辑多条记录新增、修改、删除频繁DAO 直连绑定筛选条件复杂、带多个参数的查询ADO 参数化查询需要调用存储过程或有事务、返回输出参数ADO Command只读报表、统计汇总ADO 查询结果填子窗体或列表框核心业务录入有严格的校验和审计要求非绑定窗体 ADO 调存储过程保存两种方案在同一个项目里混用很常见。比如查询列表用 ADO点进某条记录打开编辑窗体用 DAO 绑定——查询这边灵活编辑这边省事各取所长。还有一种更轻量的方式是传递查询Pass-through Query在 Access 查询设计器里直接建连接字符串写 SQL Server ODBC 地址SQL 在服务器端跑结果返回给 Access。适合只读查询或者不需要在 VBA 里动态拼参数的场景。这个我之前专门写过这里不重复了。去掉链接表之后DAO 方案改动最小和原来链接表绑窗体的体验几乎没差别迁移起来也快。ADO 的价值在往后走——等你开始需要存储过程、输出参数、事务控制那套代码不用大改加参数就行。

相关新闻

【RT-DETR涨点改进】TGRS 2026 | 卷积创新改进篇 | 引入 3DSBE 三维光谱瓶颈增强模块,增强模型对通道间互补信息的利用能力,助力高光谱目标检测、遥感目标检测任务,有效涨点

【RT-DETR涨点改进】TGRS 2026 | 卷积创新改进篇 | 引入 3DSBE 三维光谱瓶颈增强模块,增强模型对通道间互补信息的利用能力,助力高光谱目标检测、遥感目标检测任务,有效涨点

2026/7/23 21:51:02

一、本文介绍 🔥本文给大家介绍使用 3DSBE 三维光谱瓶颈增强模块 改进RT-DETR网络模型,主要作用是在特征提取阶段强化不同通道或波段之间的相关性,减少冗余信息,并为后续多尺度融合提供更具判别力的特征表示。该模块通过空间下采样与通道扩展降低计算负担,再采用主、辅双…

为什么你的AI自动化项目卡在85%?资深架构师亲授“最后一公里”攻坚清单

为什么你的AI自动化项目卡在85%?资深架构师亲授“最后一公里”攻坚清单

2026/7/23 21:51:02

更多请点击: https://kaifayun.com 第一章:为什么你的AI自动化项目卡在85%? 当模型在验证集上稳定达到84.7%–85.3%准确率却再难提升时,问题往往不在算法本身,而在于数据闭环的断裂与工程化落地的盲区。大量团队将精力…

AgentLock 首跑不要先测“能否拦截”:先验证 ALLOW、DENY、DEFER 与版本边界

AgentLock 首跑不要先测“能否拦截”:先验证 ALLOW、DENY、DEFER 与版本边界

2026/7/23 21:51:02

很多 Agent 安全测试一上来就塞一段提示注入,然后看工具有没有被拦住。这个顺序不可靠:如果你没有记录安装的版本、策略文件、上下文来源和最终决策,测试结果无法复现。我在 AgentLock 的首跑里先做四件事。第一,分清证据版本。Do…

Adam优化器原理与实践:深度学习中的自适应学习率技术

Adam优化器原理与实践:深度学习中的自适应学习率技术

2026/7/24 4:01:19

1. Adam优化器深度解析:从理论到实践的全方位指南在深度学习训练过程中,优化器的选择直接影响模型收敛速度与最终性能。2014年由Kingma和Ba提出的Adam优化器,凭借其自适应学习率特性与出色的工程实践表现,迅速成为深度学习领域的标…

【企业级AI报告引擎构建手册】:零代码接入+合规审计+多源融合——某世界500强内部培训绝密文档首度公开

【企业级AI报告引擎构建手册】:零代码接入+合规审计+多源融合——某世界500强内部培训绝密文档首度公开

2026/7/24 4:01:19

更多请点击: https://codechina.net 第一章:AI 做数据分析报告 人工智能正从根本上重塑数据分析的工作流——从原始数据接入、自动清洗、特征识别,到可视化呈现与自然语言结论生成,端到端报告生成已进入实用阶段。现代AI分析工具…

一次构建两种包:Debug 夹具与 Release 正式包的“物理文件切换“隔离

一次构建两种包:Debug 夹具与 Release 正式包的“物理文件切换“隔离

2026/7/24 4:01:19

做有网络/硬件依赖的 App,迟早会遇到这个矛盾:开发期:没有真机麦克风、没有真实 API Key,也要能演示完整流程。所以需要一套假数据(我们叫 DevFixture / Fake 服务),最好还能一键切换 8 种预置场…

大语言模型请求响应周期全解析:从API调用到错误处理

大语言模型请求响应周期全解析:从API调用到错误处理

2026/7/24 4:01:19

在大语言模型(LLM)应用开发过程中,很多开发者虽然能够调用API完成基本功能,但对请求响应周期的完整流程缺乏系统理解。当遇到"token exchange failed"、"request timed out"、"response exceeded token …

智慧医疗全景指南:从院内诊疗到远程健康管理的系统性数字化解决方案评估

智慧医疗全景指南:从院内诊疗到远程健康管理的系统性数字化解决方案评估

2026/7/24 4:01:18

随着信息技术的不断进步,智慧医疗正在快速发展,改变传统医疗模式。这一转变不仅提升了医院的运营效率,也改善了患者的治疗体验。本文将全面分析智慧医疗的数字化解决方案,从院内诊疗到远程健康管理,涵盖市场趋势、主要…

MSPM0 RTC寄存器深度解析:从基础概念到实战配置

MSPM0 RTC寄存器深度解析:从基础概念到实战配置

2026/7/24 3:51:18

1. 项目概述:深入MSPM0 RTC寄存器世界在嵌入式系统开发中,实时时钟(RTC)模块的重要性怎么强调都不为过。它不仅仅是系统里的一个“电子表”,更是维系设备时间基准、实现定时唤醒、记录关键事件时间戳的“心脏”。尤其是…

微服务进阶:服务网格与Istio

微服务进阶:服务网格与Istio

2026/7/23 3:40:08

541|微服务进阶:服务网格与Istio 上篇文章我们聊了微服务的基本概念和拆分方法。 但微服务多了,问题也多了: 服务之间怎么通信? 怎么监控每个服务的调用链路? 熔断、限流、重试怎么做? 安全认证怎么统一? 以前这些都靠SDK库(比如Hystrix、Feign),每个服务都要集成…

零售超级终端全域协同:ShareKit 碰一碰商品流转业务落地案例

零售超级终端全域协同:ShareKit 碰一碰商品流转业务落地案例

2026/7/23 4:40:05

一、零售门店全域协同业务背景与行业痛点 1.1 门店超级终端设备矩阵(连锁便利店/商超标准配置) 自助收银Kiosk一体机:顾客结算、自助核销优惠券、商品素材预览;运营折叠平板:店长后台商品上新、图片录入、活动配置、…

噗叽短视频界面分析

噗叽短视频界面分析

2026/7/23 1:54:13

1 和小红书类似,可以采用类似判断方法------------其实他比小红书好判断,因为他没有图片,控件位置几乎是固定的,都不用判断------------2 因为他没有点赞按钮------------而且几乎所有控件位置都是完全一样的,所以我就…

Django毕设项目:基于 Django 的 智能化学生综合素质测评审核系统 校园学生评优评奖综合管理系统(源码+文档,讲解、调试运行,定制等)

Django毕设项目:基于 Django 的 智能化学生综合素质测评审核系统 校园学生评优评奖综合管理系统(源码+文档,讲解、调试运行,定制等)

2026/7/24 0:01:07

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

[具身智能-634]:Python 封装的地平线 VIO 多媒体库:libsrcampy库详解

[具身智能-634]:Python 封装的地平线 VIO 多媒体库:libsrcampy库详解

2026/7/24 0:01:07

srcampy /libsrcampy 名称释义先明确结论: 官方文档没有公布标准化英文全称,是地平线内部项目缩写;行业公认拆解如下:srcampy Source Amplifier Python bindingsrc Source(图像源:MIPI Sensor、视频源&am…

用Highcharts 创建可拖拽三维散点立方体3D图表

用Highcharts 创建可拖拽三维散点立方体3D图表

2026/7/24 0:01:07

该案例基于Highcharts scatter3d 三维散点图实现空间立方体散点可视化,核心特色:三维 X/Y/Z 三轴空间,所有散点分布在 0~10 立方体空间内;散点使用径向渐变实现立体 3D 圆球质感;支持鼠标 / 触屏拖拽画布,…