链接表能删了: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 的价值在往后走——等你开始需要存储过程、输出参数、事务控制那套代码不用大改加参数就行。

相关新闻

AI 协作完整流程:从任务输入到可验证产出

AI 协作完整流程:从任务输入到可验证产出

AI 协作完整流程:从任务输入到可验证产出 版本:2026-07-16 适用对象:使用 AI 处理写作、研究、代码和知识工作的个人或小团队 核心目标:让 AI 不只是“生成答案”,而是参与一套可审阅、可验证、可回写、可演化的协作闭…

2026/7/23 22:01:37阅读更多 →
51单片机从零到实战(13)——毕设常用ADC模块

51单片机从零到实战(13)——毕设常用ADC模块

第 13 篇:ADC 模数转换——让单片机"感知"模拟世界 温度、光线、声音、电压——这些是连续的"模拟量"。ADC 把它们变成单片机懂的"数字量"。STC89C52 没有内置 ADC,我们用 PCF8591 模块(I2C 接口,5…

2026/7/23 22:01:36阅读更多 →
解密企业通信安全防线:Avaya Aura 三层安全架构深度解析

解密企业通信安全防线:Avaya Aura 三层安全架构深度解析

一、统一通信的安全挑战:当电话网遇上数据网在传统电信时代,通信系统面临的主要风险是"盗打电话"(Toll Fraud)——即未经授权使用通信资源。然而,当统一通信将电话服务与企业数据网络融合之后,安…

2026/7/23 21:59:36阅读更多 →
光电幕墙简介

光电幕墙简介

光电幕墙 光电幕墙,即粘贴在玻璃上,镶嵌于两片玻璃之间,通过电池可将光能转化成电能。这就是--太阳能光电幕墙。它是用光电池、光电板技术,把太阳光转化为电能,它关键的技术是太阳能光电池技术。太阳能光电池是利用太阳光的光子能量,使得被照射的电解液或者半导体材料的电…

2026/7/23 23:24:00阅读更多 →
工业一体机Linux系统部署实战:从系统安装到工业通信环境搭建

工业一体机Linux系统部署实战:从系统安装到工业通信环境搭建

工业一体机是面向工业场景的集成化计算终端,通常预装Windows或Linux操作系统,支持串口通信、GPIO控制、工业总线协议等工业级接口。在ARM架构工业一体机上部署Linux系统并搭建工业通信开发环境,是工业自动化项目的常见基础工作。之前在项目里…

2026/7/23 23:24:00阅读更多 →
Kimi K3引发华尔街震动:算力转化与商业化双突破,重塑行业估值逻辑?

Kimi K3引发华尔街震动:算力转化与商业化双突破,重塑行业估值逻辑?

让华尔街紧张的,其实是Kimi K3的算力转化效率?最近一周,华尔街陷入对芯片产业的“信任危机”。费城半导体指数一周内跌12.5%入技术性熊市,17家投行下调AI芯片企业目标价,高盛称“算力扩张时代”或近尾声。震荡源于月之…

2026/7/23 23:24:00阅读更多 →
直角行星减速机替换中的方向问题:PXR与PAMG选型分析

直角行星减速机替换中的方向问题:PXR与PAMG选型分析

直角行星减速机替换中的方向问题:PXR与PAMG选型分析 一、为什么直角减速机替换更复杂? 普通同轴行星减速机的输入轴和输出轴处于同一轴线上,主要核对轴向尺寸即可。 直角行星减速机的输入轴与输出轴呈90布置。原设备使用PXR时,可以…

2026/7/23 23:24:00阅读更多 →
放开能力与坚守底线:Anthropic 调整 Claude Fable 5 访问策略全解析

放开能力与坚守底线:Anthropic 调整 Claude Fable 5 访问策略全解析

作为 Anthropic 新一代高阶自主 Agent 与编程模型,Claude Fable 5 凭借 100 万 Token 的超长上下文窗口以及支持跨多天的长流程任务处理能力,一经推出便备受瞩目。然而,伴随着顶尖能力的释放,安全与合规风险也随之而来。近期&…

2026/7/23 23:24:00阅读更多 →
LeetCode Hot100(2.字母异位词分组)

LeetCode Hot100(2.字母异位词分组)

2.字母异位词分组题目给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。示例 1:输入: strs ["eat", "tea", "tan", "ate", "nat", "bat"]输出: [["bat"],[&…

2026/7/23 23:22:00阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/23 0:56:31阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/23 0:56:31阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/23 0:56:31阅读更多 →
Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具 【免费下载链接】chitchatter Secure peer-to-peer chat that is serverless, decentralized, and ephemeral 项目地址: https://gitcode.com/gh_mirrors/ch/chitchatter Chitchatter是一款革命性的安…

2026/7/23 0:00:28阅读更多 →
从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

更多请点击: https://intelliparadigm.com 第一章:从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表) 当AI副业主理人不再仅满足于单次服务交付,而是主动构建可复用、可裂变、可…

2026/7/23 0:00:28阅读更多 →
油泥处理设备哪里能买到

油泥处理设备哪里能买到

油泥处理设备哪里有?这是许多从事油田、炼化、清罐业务的从业者最关心的问题。根据河南三丰环保设备有限公司的行业经验,选购油泥处理设备的核心在于设备能否适配当地环保法规与原料特性,而非单纯看价格。该公司总经理王钦田先生指出&#xf…

2026/7/23 0:00:28阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/23 22:58:43阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/23 18:58:18阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/23 18:58:18阅读更多 →