简介:这是一份面向工业自动化及组态监控学习者的操作型教程文档,讲解力控组态软件与Microsoft Access数据库进行数据交互的完整方法。内容从力控新建工程、新建窗口和Access数据表开始,包括设计ID数字型与Name文本型字段、创建中间变量、配置系统数据源,以及使用SQLConnect、SQLInsert、SQLDisconnect三个数据库函数依次完成连接、写入、断开操作,最后介绍力控数据表绑定与运行结果验证。文档以分步图文步骤呈现,特别提示了表名称、字段名称必须保持一致、数据源末尾需加分号等易错细节,能帮助初学者减少调试时间。资源包仅含1个PDF文件,大小约1.85MB,结构紧凑,便于按章节查阅与对照实操。目前已有484人学习使用,适合组态软件入门者、自动化专业学生以及需要将现场采集数据写入关系型数据库的工程师参考,也可作为工业数据采集相关课程的补充资料。
1. 力控与Access数据库:组态软件做历史数据落地的捷径
力控组态软件在中小型工控项目里几乎是标配,而 Access 数据库则是那个“看着不起眼,但真能解急”的轻量级存储。很多现场把历史数据写在 CSV 里,等到月底要做曲线对比、报警追查时,才发现文件多到让人抓狂。力控与 Access 数据库的对接,就是把实时变量、报警记录、操作日志直接写进带结构的数据表里,查询时用一句 SQL 搞定。这篇笔记围绕“力控 + Access”讲清楚选型边界、ODBC 配置、力控 SQL 函数、归档设置和 5 个高频翻车点,让新人能按步骤复现,熟手也能直接抄参数。
2. 为什么选 Access 而不是 SQL Server:选型理由与适用边界
2.1 力控数据存储的三种常见方式
力控的实时数据库在内存里,历史数据总要落到硬盘上。常见的保存方式有三种:纯文本 CSV、Access 数据库、SQL Server/MySQL 等外部数据库。
纯文本最简单:力控自带“数据转储”功能,按天生成 CSV 文件。好处是零配置,拷走就能看;坏处是文件数量多,查询时要么用 Excel 打开一个个翻,要么自己写脚本解析。现场数据一多,CSV 文件在 U 盘里拷贝都会等半天,而且没有索引,按时间范围取一段数据得从头扫到尾。
Access 数据库是工控圈里最常被轻视的方案。它本质上是一个文件型数据库,不需要安装服务端,只要系统里有 ODBC 驱动,力控就能通过 SQL 语句直接读写。对于变量点数几百个、历史周期几秒钟的中小场景,Access 的响应速度完全够用。同时,力控的历史趋势、报表查询、事件记录都能绑定同一个数据库文件,后期交给业主也方便——不用教他们维护数据库服务,只要定期备份那一个 .accdb 文件就行。
SQL Server 和 MySQL 在大型项目里是正解,但一个工控机项目往往没有人专门维护数据库服务。装好以后,补丁、服务启动、账号权限、防火墙隔离,任何一个环节出问题都是麻烦。我见过不少项目因为 SQL Server 的登录名密码和 Windows 更新冲突,导致数据中断一周。除非客户明确要求,或者变量点数超过千点,否则用 Access 做历史数据归档是性价比更高的选择。
2.2 Access 数据库的适用场景与硬边界
Access 的适用场景可以从几个维度判断:并发客户端只有一个力控进程;数据量每天新增不超过几十万行;保存周期不超过一年;单表行数控制在 50 万行以内。满足这四条,Access 用起来会很舒服。典型的现场是换热站、泵房、小型水处理、实验室环境监控、烘干窑等设备改造类项目,这些项目的特点是变量点少、数据变化慢、没有专职 IT 人员。
硬边界也很清晰:Access 在多个进程同时写同一张表时,会锁定数据库文件,导致“不能更新数据库”的报错。虽然力控只有一个进程,但如果你同时开着力控和 Excel 去访问同一个文件,也会遇到锁库。单表数据量超过 100 万行后,带排序的查询会明显变慢,插入速度也会从毫秒级退化到几百毫秒。更尴尬的是 Access 单文件上限是 2GB,接近上限时数据库很容易损坏,损坏后恢复数据非常耗时间。
所以我的选型原则很俗:能预知数据库文件会超过 1GB 的项目,趁早换 SQL Server;否则用 Access 做低成本方案,并在交付文档里写明建议使用年限。千万别把 Access 当数据仓库,它只是一台现场的“记账本”。如果客户非要长时间存几十个变量秒级数据,我会直接告诉他 Access 扛不住,这不是优化能解决的。
2.3 如何规划数据表结构并选择 .mdb 还是 .accdb
力控写 Access 的表结构建议自己手动建。为什么?因为力控自动建表的字段名和字段类型往往和你想的有出入,后期查询时还得改。我一般会建两张表:一张实时历史表,一张报警事件表。历史表字段如下:
| 字段名 | 类型 | 说明 |
|---|---|---|
| TagName | VARCHAR(100) | 变量名 |
| TagValue | DOUBLE | 数值 |
| Quality | SMALLINT | 质量戳,0 好 1 坏 |
| RecordTime | DATETIME | 记录时间 |
报警表类似,但字段里要有报警描述、报警级别、确认状态等。字段名的重点是:不用中文,不用空格,不用保留字。比如不要用 TIME 作为字段名,Access 里会有一堆麻烦。力控的 SQL 函数对中文字段名的兼容性很玄学,字符集一不对,查询就返回空。我见过一个项目,数据库字段叫“温度”,力控脚本里写[温度]才能查到,但换一台电脑又不行。最后改成Temp_Zone1才彻底消停。
关于文件格式,建议使用 .accdb 而不是旧版 .mdb。.accdb 支持数据类型更丰富,且能用到 64 位 ACE 驱动。要注意的是,老版本的力控(比如 ForceControl 6.x 早期)可能不认 .accdb,只认 .mdb。所以在确定格式之前,先看力控版本。如果力控确实太老,就在 Access 里把数据库另存为 .mdb 格式。建表 SQL 无论哪种格式都一样:
CREATE TABLE HisData ( TagName VARCHAR(100), TagValue DOUBLE, Quality SMALLINT, RecordTime DATETIME );注意 Access 的 DOUBLE 对应 SQL 标准 FLOAT,但你用 ODBC 创建时可以直接写 DOUBLE。如果你在 Access 中用设计视图建表,把「允许空字符串」设为否,避免写入空字符串时出现别的错误。
3. 力控连接 Access 数据库:从 ODBC 驱动配置到测试连接
3.1 第一步:装对驱动,分清 32 位和 64 位
力控安装到 64 位 Windows 系统上时,最容易踩的第一个坑就是驱动位数。访问 Access 数据库要靠 Microsoft ODBC 驱动,常见的有两代:老一代是Microsoft Access Driver (*.mdb),只有 32 位;新一代是Microsoft Access Driver (*.mdb, *.accdb)(ACE),有 32 位和 64 位两个版本。
很多工程师在 64 位系统上只装了 Office 附带的 64 位 ACE 驱动,然后发现力控还是连不上,报错提示“请先安装 Access 数据库 64 位系统驱动程序”。其实这句话更深层的含义是:当前发起连接的进程是 64 位,但它找不到可用的驱动。反过来,如果力控是 32 位的老版本,它会作为 32 位进程去访问 ODBC,这时需要的是 32 位驱动和 32 位 DSN。
常见做法是把两个版本的 ACE 驱动都装上。直接装容易冲突:如果系统里已经安装了 32 位 Office,双击 64 位 ACE 安装包会被拒绝。解决办法是下载 Office 兼容包自带的 ACE 程序集,用管理员的命令行安装。但这不是什么高招,更多时候我们应该先看力控的版本。在力控开发环境的“关于”窗口里能看到版本号,多数老项目用的是 32 位力控,那么只用 32 位驱动就行。
这里还有一个细节:力控的历史 SQL 存储功能可能依赖 MDAC/ADO 组件,Windows 10/11 自带 MDAC,但有些精简系统把组件减掉了。如果驱动装好但连接依然失败,去“控制面板-程序和功能-启用或关闭 Windows 功能”里检查“Microsoft ODBC Driver”和“远程差分压缩”,补装后重启电脑。
3.2 第二步:在 ODBC 管理器里创建 DSN
ODBC 数据源管理器的坑很隐蔽。64 位系统里,odbcad32.exe有两个:C:\Windows\System32\odbcad32.exe是 64 位的,C:\Windows\SysWOW64\odbcad32.exe是 32 位的。你在开始菜单搜索“ODBC”打开的那个,往往是 64 位版本。如果力控是 32 位,你用 64 位管理器建的 DSN 它根本看不到。
打开正确版本后,切到“系统 DSN”或“用户 DSN”,点击“添加”,选择驱动名称:
Microsoft Access Driver (*.mdb, *.accdb)注意不要选成Microsoft Access Driver (*.mdb),那个旧驱动在 64 位系统上可能不显示或报错。然后设置数据源名,比如ForceControlDB,点击“选择”按钮指到你要访问的 Access 文件。建议提前把数据库文件放到一个固定路径,比如C:\ForceControlData\db.accdb,不要放在桌面或 U 盘上,否则 ODBC 会记挂一个不存在的路径。测试连接显示成功即可。
命令行方式也可以建 DSN,但没必要。这里列一下打开命令方便确认:
# 32位力控对应32位ODBC管理器 C:\Windows\SysWOW64\odbcad32.exe # 64位应用对应64位ODBC管理器 C:\Windows\System32\odbcad32.exe我在现场的习惯是,在 SysWOW64 和 System32 里各打开一次,都建一个同名 DSN。这样无论力控的模块是 32 位还是 64 位,都不会因为 DSN 找不到而翻车。代价只是多花一分钟,但能省掉后面一晚上的排查时间。另外,DSN 名称不要用纯数字,有些版本力控会把数字开头的 DSN 解析成十六进制数,这又是另一个玄学问题。
3.3 第三步:在力控里配置连接并测试
力控的脚本支持类似 C 语言的语法,数据库连接通过 SQLConnect 函数建立。DSN 建好以后,在画面脚本或全局脚本里写:
// SQLHandle 是连接号,定义成整型变量 int SQLHandle; // 使用 DSN 连接,用户名为空,密码为空 SQLConnect(SQLHandle, "DSN=ForceControlDB;UID=;PWD=;"); // 判断连接是否成功 if (SQLHandle >= 0) { // 这里可以继续执行 SQL } else { // 打印错误信息到运行画面 }参数说明:ForceControlDB是刚才创建的 DSN 名;UID和PWD在 Access 里一般不设置,但保留空值让连接串更完整。连接成功后,SQLHandle 会大于等于零;失败时返回负值,通常是 -1。如果失败,先用 Access 打开数据库测试,然后回到 ODBC 管理器点“测试连接”,确定问题在驱动还是力控配置。
有些工程师为了省事,不建 DSN,直接在力控里写连接字符串:
SQLConnect(SQLHandle, "Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=C:\data\db.accdb;");这种做法在力控里也能用,但字符串里的分号和大括号容易被脚本解析器误伤。我吃过一次亏:连接串在别的组态软件里正常,到力控里就把分号当成了语句分隔符,报语法错误。所以正规做法是建 DSN,力控脚本里只写 DSN 名。如果实在要用连接字符串,建议用变量拼接方式,先用一个文本变量保存连接串,再传给 SQLConnect。
4. 在力控里读写 Access:SQL 函数、归档配置与画面查询
4.1 力控 SQL 函数组的基本用法
力控的 SQL 函数是一套内建脚本接口,常用的是这几个:
| 函数 | 作用 |
|---|---|
| SQLConnect | 建立连接 |
| SQLExec | 执行插入、删除、更新等不返回结果集的 SQL |
| SQLOpen | 执行查询,打开结果集 |
| SQLGet | 从结果集取一行或一个字段 |
| SQLClose | 关闭结果集或连接 |
先连接,再执行。比如往历史表里写一条数据:
// 假设 SQLHandle 已经连接成功 string sSql; sSql = "INSERT INTO HisData (TagName, TagValue, Quality, RecordTime) VALUES ('Tag_P1', 23.56, 0, Now())"; if (SQLExec(SQLHandle, sSql) == 0) { // 执行成功 }逻辑说明:这条语句直接把实时变量的值写进去。实际应用时数值应该来自力控实时变量,所以写法要拼接字符串:
float fVal; fVal = Tag_P1; // 力控的实时变量 string sTime; sTime = StrFromDateTime(Now(), 2); // 格式化时间 string sSql; sSql = "INSERT INTO HisData (TagName, TagValue, Quality, RecordTime) VALUES ('Tag_P1', " + StrFromReal(fVal, 2) + ", 0, #" + sTime + "#)"; SQLExec(SQLHandle, sSql);注意这里时间常量用#包裹,不是单引号。Access 里Now()可以直接写在 INSERT 语句里,但如果你要精确到秒并能和查询条件匹配,最好显式传入时间字符串。力控的StrFromDateTime函数格式在不同版本不一样,有的返回yyyy-mm-dd hh:mm:ss,有的带毫秒,建议先用一个文本变量打印出来看看。
4.2 历史数据归档到 Access 的配置步骤
如果每个变量的数据都要靠脚本插入,不仅脚本复杂,还会因为扫描周期不同步导致数据不全。力控本身有“历史数据”功能,可以直接把数据源设定为 SQL。
具体步骤:在力控开发环境中找到“数据库组态”或“历史数据”,双击要归档的变量,在存储属性里选择“SQL”,然后填写表名、DSN 名和存储周期。力控会自动生成插入语句,你只需要保证表结构和字段名匹配。
在配置之前先手动建表,避免力控自动建表产生意外。我建议表字段顺序固定,并在 Access 那边设置自动编号字段作为主键,否则力控在插入时可能因为无法生成唯一 ID 而报错。
存储周期设置多久合适?要看变量变化快慢。温度、液位这类慢变量,5 秒到 10 秒一个点就够;流量压力这类需要密集采样的,1 秒或 2 秒。注意:Access 写盘是有 IO 开销的,几百个变量每 1 秒写一条,意味着每秒几百次 INSERT,32 位驱动很快会卡。这时候合并写入会好一些,但力控的历史 SQL 存储一般是逐条写,所以变量点数多时要谨慎。如果变量点数超过 500 个,建议把存储周期拉到 5 秒以上,或者改用 SQL Server。
还有一点:力控的历史 SQL 存储是后台线程执行的,配置好以后先跑一小时,再打开 Access 看记录数和字段值是否正常。别等到第二天发现表里全是空值,那可能是力控把真实变量名和表字段名搞混了。
4.3 用 SQL 查询在画面上做报表
读数据比写数据更常用。力控画面里有一个“数据表”或“曲线”控件,把查询结果绑定上去,操作人员就能在触摸屏上查历史。
关键 SQL 是用时间段过滤:
SELECT TagName, TagValue, RecordTime FROM HisData WHERE TagName = 'Tag_P1' AND RecordTime >= #2025-01-01 00:00:00# AND RecordTime <= #2025-01-31 23:59:59#这里两个日期常量用#括起来,是 Access 的语法。如果改写成字符串,力控通过 ODBC 查询时会把它当成文本比较,导致一条数据都查不出来。最常见的现象是:在 Access 里用查询设计器做同样的条件能出结果,但力控里返回空。这就是日期常量写法错了。
脚本里可以用 SQLOpen 打开结果集,再用 SQLGet 逐行取数:
string sSql; sSql = "SELECT TagValue, RecordTime FROM HisData WHERE TagName='Tag_P1' ORDER BY RecordTime DESC"; int rc; rc = SQLOpen(SQLHandle, sSql); if (rc >= 0) { float fVal; // 循环取出第一列,实际根据你的列数来 while (SQLGet(SQLHandle, 1, fVal) == 0) { // 填充到画面表格控件或数组 } SQLClose(SQLHandle); }注意 SQLGet 的第二个参数是列序号,从 1 开始,而不是 0。这个细节非常容易被忽略,写成 0 后取出来的都是空。另外,查询结果集用完必须 SQLClose,否则力控运行一段时间会报“连接资源不足”甚至崩溃。画面里的数据表控件一般有行数限制,一次查询不要超过 10000 行,否则界面刷新会卡死。分页查询在 Access 里用TOP加子查询,虽然麻烦但比一次性拉全量数据稳健。
5. 避坑:Access 数据库连接常见的 5 个问题排查
5.1 报错“请先安装 Access 数据库 64 位系统驱动程序”
现象:力控在运行启动或第一次执行 SQLConnect 时弹出该提示,进程直接退出或连接返回负值。
原因:力控的进程是 64 位,或者力控内部调用了 64 位组件,而系统中没有安装 64 位的 Microsoft Access 驱动。另一个常见情况是驱动安装类型不完整,比如只装了 Office 自带的 32 位 Jet 驱动,缺少 ACE 64 位驱动。
解决:先确认系统架构和力控位数。安装 Microsoft Access 数据库引擎 2016 可再发行版(64 位)。安装命令如下,避免和 32 位 Office 冲突:
# 以管理员身份运行,/passive 表示安静安装 AccessDatabaseEngine_X64.exe /passive如果安装时提示已有 32 位 Office,不能继续,可以试试卸载 32 位 Office 后再装,或者在命令行用/quiet强制安装。实际项目中我见过一个更简单的绕过方法:不用 64 位驱动,改用 32 位力控和 32 位驱动,两边摆齐就能避开这条报错。注意:64 位系统上装 32 位 ACE 驱动没有任何问题,只要你的力控进程是 32 位的。
5.2 64 位引擎不支持 DBC 数据,只支持 Access 数据
现象:ODBC 测试连接时选择 Access 驱动,但报错“64 位引擎不支持 DBC 数据,只支持 Access 数据”。
原因:ODBC 驱动选择错误。Microsoft 的驱动列表里有两个易混项:一个用于 Access 的 mdb/accdb,一个用于 Visual FoxPro 的 DBC 数据库。如果连接串里的 Driver 名称写成Microsoft Visual FoxPro Driver,64 位 ACE 当然不认识。还有一种情况是数据库文件本身扩展名是 .dbc,而不是 .mdb/.accdb,ACE 引擎只接受 Access 格式。
解决:检查 DSN 的驱动名称,确保是:
Microsoft Access Driver (*.mdb, *.accdb)如果用的是连接字符串,也改成这个名称。文件扩展名不对的话,把 .dbc 文件在 Access 中打开并另存为 .accdb 格式。如果你手上只有 .dbc 文件,且无法转换,那就换用 VFP OLE DB 提供程序,不过这需要额外安装 Visual FoxPro 组件,工控机上不建议折腾,直接让客户要一份 Excel 导出更省事。
5.3 测试连接正常,但力控写入时提示数据库被锁定
现象:ODBC 测试连接显示成功,力控执行 INSERT 时返回“不能更新数据库”或“数据库文件已锁定”。
原因:Access 文件放在受保护目录,或者文件被以独占方式打开。一种隐蔽情况是:有人用 Excel 或另一个程序打开了该 Access 文件,导致文件锁。还有可能是数据库文件所在目录没有写权限,比如放在 Program Files 下,Windows 的 UAC 会拦截写操作。
解决:把数据库文件放到C:\ForceControlData这类普通目录,并给 Users 组授予完全控制权限。检查是否有其他程序占用,关闭所有打开该文件的程序。如果还不行,在 DSN 配置里把“独占”选项去掉。DSN 默认不是独占,但某些自定义连接字符串里会带Exclusive=1,删掉即可。另外,Access 的共享模式需要在“选项”里设置“默认打开模式”为“共享”,这个设置存储在注册表里,机器重启后会生效。
5.4 数据量上来以后,写入越来越慢,CPU 占用高
现象:运行几天后,力控的写库周期从每秒完成变成几秒才完成,历史数据开始丢失,画面趋势出现断层。
原因:Access 单表行数接近几十万后,索引和表页的维护开销急剧上升。另外,如果表上建了多个索引,每次插入都要更新所有索引,写入速度成倍下降。还有一个隐藏因素是 Access 文件所在磁盘碎片化严重,机械盘上尤其明显。
解决:按月分表,表名带月份后缀HisData_202501。力控的历史配置里可以通过脚本动态修改表名,或者在存储过程里定期重建当前表。如果不想改表,就用DELETE FROM HisData WHERE RecordTime < ...定期清理旧数据。不过大规模删除后再插入,文件会有碎片,最好每月执行一次压缩修复。压缩方法见第 6 章。如果数据量已经到了每天几十万行,建议直接迁移到 SQL Server,别在 Access 上继续加固了。
5.5 中文路径、中文表名导致查询不到数据
现象:连接正常,SELECT 也能返回,但查询条件带有中文时结果为空;或者写入的中文变成乱码。
原因:力控脚本的字符集和 ODBC 驱动转码不一致。尤其在代码页为 936 的 Windows 和 UTF-8 的组态脚本之间,中文会被转义成?。力控的某些版本用 ANSI 编码保存脚本,某些用 UTF-8,同一个中文字符串在不同版本间复制会出问题。
解决:数据库文件路径、表名、字段名全部用英文。中文字符串内容可以写入,但前提是表中字段类型是字符串且驱动支持。实测中,中文写进去能存,但查询时用中文条件匹配经常失效。替代方案:增加一个唯一英文编号字段作为查询条件,中文内容只做显示。如果必须查询中文,试试在 SQL 里把条件两边套上 Format() 函数统一大小写,但这也不保证成功。我一般建议直接放弃中文条件,改用时间范围加变量名。变量名也用英文,别在力控里定义“温度1”之类的名称,否则后面所有报表都得磕磕绊绊。
6. 进阶:Access 数据库自动备份与文件压缩修复技巧
Access 是文件型数据库,备份最直接的方法是拷贝文件。但力控正在写库时直接拷贝文件,容易出现文件占用或拷贝出不一致的数据。更稳妥的做法是在力控的全局脚本里写一个定时备份逻辑。
在力控的“应用程序”组件里打开全局脚本,用定时器每 24 小时执行一次备份命令。常见做法是调用系统命令copy,但要注意执行时不能有另一个进程锁定数据库。力控的 SQL 操作完成后,会短暂释放文件锁,利用这个窗口执行复制:
// 全局脚本,每天凌晨1点执行 if (Hour(Now()) == 1 && Minute(Now()) == 0) { // 先把数据库连接关闭 SQLClose(SQLHandle); // 用copy命令备份数据库文件 Run("cmd.exe /c copy /Y C:\\ForceControlData\\db.accdb C:\\ForceControlData\\backup\\db_20250101.accdb"); // 重新连接数据库 SQLConnect(SQLHandle, "DSN=ForceControlDB;UID=;PWD=;"); }这段脚本说明了思路:备份前关连接、备份后重新连。Run是力控的启动外部程序函数,参数里如果有中文路径会很敏感,所以要求路径全英文。备份文件名里带上日期,方便恢复时找时间点。别把备份文件放在同一个盘符下,我见过硬盘坏道把原库和备份一起带走的惨剧。
另一个实用技巧是压缩修复。Access 文件在长时间插入删除后体积膨胀,可以使用 ACE 驱动的 CompactDatabase 功能。但力控脚本不方便直接调用 COM 接口,我可以借助 VBScript:
' compact.vbs 放在项目目录下 Option Explicit Dim engine, source, dest source = "C:\ForceControlData\db.accdb" dest = "C:\ForceControlData\db_compact.accdb" Set engine = CreateObject("DAO.DBEngine.120") engine.CompactDatabase source, dest, , , ";PWD="然后在力控里定时调用Run("wscript.exe C:\\ForceControlData\\compact.vbs")。执行后把原文件替换成压缩后的文件。需要注意:压缩前同样要先关闭力控的 SQL 连接,否则文件锁会阻碍压缩。压缩操作每分钟可能删掉几十 MB 的废弃页,对长时间运行的项目有明显效果。替换文件时,先改名原库为 .bak,再把压缩后的文件改名为正式文件名,这样即使替换失败还能手动改回来。
最后说一个验证数据完整性的习惯。我每次完成力控和 Access 对接以后,都会在画面里放一个“数据自检”脚本,查询最近一小时的数据条数:
SELECT COUNT(*) AS Cnt FROM HisData WHERE RecordTime >= #2025-01-01 00:00:00#如果实际变量按 5 秒一条,一小时应该有 720 条左右。数量对不上,就去检查扫描周期、驱动位数和表结构,而不会急着改脚本。这个习惯帮我排掉过很多隐形问题。Access 这个方案上限很低,但用好它,确实是小项目的后悔药。希望帮到你。
本文还有配套的精品资源,点击获取