做自动化项目的同行应该都有这种体会设备运行数据散落在PLC里甲方说要历史趋势曲线、要报表、要对接MES光靠WinCC自带的变量归档根本不够用。最近我在搞西门子博图TIA Portal环境下的WinCC历史数据存储方案被问得最多的就是一句话怎么把实时变量怼进SQL数据库。今天这篇就把整个流程从头盘一遍从选型、配置到脚本落地再到几个真正会让你卡住好几天的坑全部说透。内容面向正在用博图WinCC做上位机的电气工程师和工控项目负责人尤其是那些项目里明确要求历史数据要能查、能导、能对接其他系统的同行。1. 为什么放着现成的归档不用非要自己怼数据库1.1 自带变量归档的尴尬处境WinCC自带的变量归档Tag Logging其实不难用组态软件里勾几个选项历史数据自动落盘画面上拖一个趋势控件就能看曲线。但是真正做过项目的都清楚这套归档在稍微正式一点的场景下非常尴尬。数据存在私有格式的归档文件里甲方想要月度报表你没法直接跑一条SQL语句查出来MES/WMS系统要对接历史数据WinCC归档没有标准的对外接口只能靠WinCC的开放接口二次开发数据量一上去归档文件膨胀之后备份、迁移、恢复都是麻烦事时间长了甚至会出现文件损坏、查询越来越慢的情况。还有一类需求是自带归档完全搞不定的审计追溯。比如制药、食品行业要满足批次追溯要求每一次温度、压力的变化都带着时间戳和质量状态写进独立数据库并且要保留原始记录不可篡改。这已经不是趋势曲线的问题而是数据治理的问题。把变量直接写入SQL Server好处是显而易见的数据库是标准货任何报表工具、上位系统都能直接读表结构自己说了算想怎么设计就怎么设计数据可以按项目、按批次、按设备分开存查询灵活备份迁移有成熟的数据库运维体系不用被WinCC的私有格式绑死。1.2 什么样的项目才值得上SQL方案先说清楚不是所有项目都适合把历史数据怼进SQL数据库。我个人会把项目分成三类只要看实时曲线、存个几周趋势直接WinCC自带的变量归档半小时搞定别折腾数据量中等几百个点以内但需要跨系统查询、报表分析、审计追溯这种最适合自定义SQL存储海量数据、毫秒级采样、长期保存建议上专门的时序数据库或者工业数据平台SQL Server硬扛会很吃力。判断标准很简单先问甲方数据存下来之后要干什么。如果答案是做分析、做报表、对接系统那SQL方案就是刚需如果只是坏了能回放一下那用自带归档就够了。上SQL方案之前一定先想清楚这个边界不然就是给自己找活儿干。1.3 这个方案到底解决什么问题自打我开始分享这个方案发现很多同行其实搞混了两件事把实时变量写进SQL数据库本质上是解决数据如何从WinCC运行系统中拿出来落成一个可以自由操作的数据库记录的问题而不是解决怎么画一条好看的趋势曲线的问题。曲线显示是下游的事上游的数据管道没打通后面全是空中楼阁。所以本文的方案目标定义得很明确在博图WinCC运行环境下通过系统脚本按设定周期把实时变量的值写入SQL Server数据库表。数据管道打通之后至于你是用WinCC的趋势控件读数据库、用Power BI连库做报表还是写个Web页面展示实时数据那就是各显神通了。这个定位在后面选型、踩坑的时候会反复帮我们做决策。2. 方案选型ODBC直连还是中间件转发2.1 三种主流做法的对比把WinCC的实时变量送进数据库业界常见的有三条路一是WinCC内部脚本直连数据库二是通过中间层比如OPC UA服务器或者独立的数据采集服务来转发三是上一台工业网关硬件协议转换之后写入数据库。先说脚本直连。WinCC全局脚本支持VBScript和C脚本可以在脚本里创建ADO连接对象直接连数据库执行INSERT语句。优点是没有额外硬件、没有中间环节整个过程都在WinCC内部完成部署就是一台工控机非常适合中小规模项目缺点是和WinCC运行系统强耦合如果脚本写得不好比如频繁开闭连接反而会影响WinCC的实时性。但这个问题可以通过缓存和批量写入来规避后面会细说。再说OPC UA中间件。博图WinCC本身可以作为OPC UA服务器把变量暴露出来然后由部署在另一台机器上的服务订阅这些变量再写入数据库。这种做法的好处是数据采集和数据库解耦即使WinCC重启采集服务还在持续写数坏处是多了一台机器、多了一个服务架构复杂度上升而且OPC UA订阅的配置、质量戳的处理、断线重连的逻辑都要自己维护现场调试周期明显拉长。第三种网关硬件适合老设备改造或者PLC直接采集不适合WinCC场景这里就不展开了。三种方式放在一起对比选型思路会更清楚维度WinCC脚本直连OPC UA中间件硬件网关部署成本低一台工控机搞定中需要额外服务器高需要购买硬件维护复杂度低中中对WinCC的耦合强弱弱适用规模中小规模中大规模协议改造场景扩展能力一般强可对接多处一般2.2 我为什么推荐VBS脚本加ODBC直接说结论如果项目只是把几十上百个变量按秒级周期存进SQL Server甲方要求能查能导报表那WinCC内置的VBS脚本加ODBC就是性价比最高的方案。理由有三点。第一WinCC本身就内置了脚本运行时不需要引入新的组件。博图WinCCV14以上的全局脚本用VBS或C都行我习惯用VBS语法简单、调试直观数据库操作用ADODB对象写起来跟写Excel宏差不多电气工程师上手也快。第二ODBC数据源把数据库连接参数集中管理。我们在Windows里配好系统DSN脚本里只写DSN名字和账号密码SQL Server的实例名、端口、库名都封装在DSN里。换数据库服务器的时候只改DSN不用改脚本。这个设计在项目实施中非常实用因为甲方经常会临时给你换一台数据库服务器。第三纯内网部署安全性可控。工控网段一般不允许直接访问外网脚本直连数据库只涉及内网服务器不会引入额外的网络策略问题。相比OPC UA中间件要在防火墙上开端口脚本直连的方案在现场更容易过审。当然这个方案的代价也很明确数据采集的可靠性完全依赖WinCC运行系统和脚本本身。如果WinCC是冗余架构那需要额外处理脚本只在主服务器上运行的问题如果数据量很大脚本的执行频率和数据库写入性能会成为瓶颈。这些在项目初期就要有预期。2.3 版本与环境的搭配逻辑动工之前先把版本关系捋清楚这是最容易被忽略的。WinCC是西门子家的软件数据库操作最终走的是Windows ODBC驱动而SQL Server的版本和Windows Server版本、WinCC版本之间有很多微妙的关系。以我实测过的组合为例博图WinCC V15.1专业版跑在Windows Server 2016上数据库用SQL Server 2014/2017都正常。如果有老项目用的是WinCC 7.x那对应的是早期的SQL Server版本迁移数据时就要注意版本兼容问题。比如有人问SQL Server 2012的数据库备份2008能用吗答案很直接备份文件不能直接恢复到低版本跨大版本恢复经常出现脚本不兼容我后面踩坑那章会专门讲。另外补充一句如果你的项目有国产化要求数据库要换成达梦这类国产数据库整个流程思路是通用的但ODBC驱动、SQL语法细节会有不少差异建议在选型阶段就让数据库厂家提供对应的ODBC驱动并做连通性测试别等代码写完了再换库那才是真的欲哭无泪。3. 手把手配置流程从SQL Server建库到WinCC脚本落地3.1 SQL Server侧的准备三步必须做数据库侧的准备工作很多人觉得装好SQL Server就能用了其实还差得远。要让WinCC的工控机能连上数据库至少有三件事必须做对。第一步启用混合身份验证模式并用一个固定账号。SQL Server默认是Windows身份验证而WinCC脚本跑在工控机上用的服务账号不一定是数据库服务器的域账号所以最省事的做法是把登录模式改成SQL Server和Windows混合认证然后建一个独立的数据库账号比如wincc_user只授权目标数据库的读写权限。我个人的习惯是尽量不要直接用sa万一脚本里连接串泄露至少不会把整个服务器搭进去。第二步启用TCP/IP协议。SQL Server的默认实例经常只开了Shared Memory和Named PipesODBC连接走TCP/IP时直接报连接超时或者握手错误。打开SQL Server配置管理器找到实例的TCP/IP协议启用然后在IP地址页签里确认监听端口是1433TCP端口填上1433重启SQL Server服务。这一步做完你用本机ODBC测试才能通。第三步防火墙放行1433端口。工控机的Windows防火墙或者服务器端防火墙都要放行TCP 1433不然其他机器连数据库服务器全部失败而且你自己看着SQL Server明明在跑就是连不上。踩过一次之后我学乖了做连通性测试一定从工控机上测不要在装SQL Server的机器本身上测因为本机测试走的是Shared Memory根本不能代表外部连接。3.2 建库建表表结构设计比写脚本更重要数据库表设计是整个方案的根。我见过不少同行上来就写INSERT语句结果变量一多、需求一变表结构改起来要命。针对WinCC实时变量的历史存储我的建议是建一张主表字段包含这几个核心维度变量名TagName字符串类型比如Boiler_Temperature变量值TagValue用float或者real类型但要注意WinCC的变量类型不全是浮点还有bool和字符串所以如果变量类型复杂建议把所有值先转成字符串存查询时再转换时间戳TagTimedatetime类型精确到毫秒可以用datetime2质量戳Qualityint类型对应WinCC的变量质量码正常是0异常是非0查询时可以过滤异常数据。建表语句示例CREATE TABLE dbo.TagHistory ( ID INT IDENTITY(1,1) PRIMARY KEY, TagName NVARCHAR(120) NOT NULL, TagValue NVARCHAR(50) NOT NULL, TagTime DATETIME2(3) NOT NULL, Quality INT NOT NULL DEFAULT 0 ); CREATE INDEX IX_TagHistory_TagName_TagTime ON dbo.TagHistory (TagName, TagTime);这里两个细节值得说明。第一我特意把TagValue设计成NVARCHAR而不是纯数值类型是因为生产现场的变量五花八门数字、开关量、字符串都有。用float存字符串变量会报错用NVARCHAR就都能接住。数值计算、排序、比较在查询时用CAST转换即可牺牲一点性能换来通用性很划算。第二索引一定要建在TagName, TagTime组合上因为几乎所有的历史查询都是查某个变量在某段时间内的值。没有这个索引数据量过万之后查询速度会肉眼可见地变慢。3.3 ODBC数据源配置名称别任性在工控机上打开ODBC数据源管理器在系统DSN里新建一个数据源。驱动选SQL Server Native Client或ODBC Driver 17 for SQL Server都可以老项目推荐用Native Client兼容性好新装系统用新的ODBC Driver也行关键是要和WinCC运行的位数匹配——WinCC 64位就用64位数据源管理器和64位驱动。配置DSN时服务器填SQL Server的IP或者机器名数据库选我们建好的HistoryDB身份验证填刚才建的账号。这里要特别提醒DSN的名字在WinCC脚本里是直接引用的命名不要带空格和特殊字符不要用中文。我见过某现场把DSN命名成生产数据库1结果VBS脚本中文编码一乱直接连库失败排查了半天最后发现是DSN名字在WinCC里读出来变乱码。老老实实用英文名比如WinCC_History_DSN。3.4 写入效率问题的提前预防在开始写WinCC脚本之前先思考一个关键问题数据库写入的效率瓶颈在哪里每一条INSERT语句都是一次数据库事务。如果脚本每秒执行一次每次插入一条记录对于几十个变量那就是每秒几十次事务。SQL Server处理这点量本身没什么问题但ODBC连接的建立是非常昂贵的操作——每次连接都要经过TCP握手、认证、分配句柄对实时性要求较高的WinCC系统来说这些额外开销会产生明显影响。所以我的设计思路是在WinCC运行系统里维持一个全局连接脚本周期触发时复用这个连接而不是每次触发都新建连接。更进一步如果数据量较大可以先把记录积攒在脚本的字典或数组里每隔几秒或者攒够几十条再一次性批量插入。这个优化在第6章会详细说但建表阶段就要有这个意识表结构要为批量插入留好余地。4. WinCC侧脚本实现从零写一段能跑的VBS4.1 WinCC全局脚本的基本结构WinCC里的全局脚本Global Script和画面脚本不一样它可以设置独立的触发器按周期、按变量变化或者按事件来执行。这也是我们把实时变量写入SQL数据库的主阵地。在博图WinCC中右键全局脚本新建一个VBS脚本函数然后设置触发器。对于连续工艺参数温度、压力、流量推荐用周期触发触发周期根据实际需要设一般1秒、5秒或者10秒都行不必追求太快。对于设备的启停状态、报警信号这类开关量用变量变化触发更合理不需要存一堆还是0的重复记录。脚本的核心逻辑是四步第一步拿到要写入的变量值第二步组装INSERT语句第三步通过ADODB连接执行SQL第四步处理错误和断线。下面是一段能直接跑起来的基础示例 定义连接对象 Dim conn, strSQL Set conn CreateObject(ADODB.Connection) 连接ODBC数据源 conn.ConnectionString DSNWinCC_History_DSN;UIDwincc_user;PWDYourPassword; conn.Open 读WinCC变量这里用HMIRuntime Dim tagValue tagValue HMIRuntime.Tags(Boiler_Temperature).Read 组装插入语句 strSQL INSERT INTO dbo.TagHistory (TagName, TagValue, TagTime, Quality) VALUES ( _ Boiler_Temperature, tagValue , GETDATE(), 0) 执行 conn.Execute strSQL 关闭连接 conn.Close Set conn Nothing这段代码演示的是最基本的情况实际上有几个地方要改第一对象的创建、连接、执行、关闭都应该包在错误处理里第二不要每条记录都新建连接和关闭连接那会让数据库端的连接池频繁起停影响性能第三GETDATE()取的是数据库服务器的时间如果你需要精确对齐WinCC系统的采样时间应该把时间戳作为参数传进去而不是用数据库时间。4.2 变量读取的正确姿势在VBS里读WinCC变量最常用的方法是HMIRuntime.Tags(变量名).Read。但这里有个容易踩的坑如果变量在多个画面中被使用或者脚本运行频率很高用名称索引的方式会有性能开销。更稳妥的方法是在脚本启动时先把变量对象缓存到数组里每次触发时用缓存的对象引用而不是每次都按名称查找。还有一种情况你读到的变量值类型不是简单的数值比如结构变量、数组变量直接用字符串拼INSERT语句会碰到类型转换的问题。我的习惯是先判断VarType把数值统一格式化字符串变量用单引号包裹并处理转义布尔值转成0/1这样表里的数据才干净。4.3 触发器设置周期、变化还是事件WinCC的触发器模式有三种对应的使用场景完全不同周期触发适合模拟量连续采样。1秒一次最常用。注意周期不要太短我见过有人设100毫秒想把趋势做细结果数据库写入成为瓶颈反而拖慢了WinCC本身。变化触发适合开关量、离散量。设备状态从0变成1时写一条减少冗余数据。事件触发适合报警、操作记录。比如操作员确认了一条报警、修改了配方参数这时候写一条审计记录。实际项目中一张表也可以被多个触发器不同的脚本写入只要表结构一致即可。比如周期采样写一条报警事件再写一条用时间戳和变量名区分就好了。4.4 脚本调试与日志脚本写完之后直接在WinCC里调试有个麻烦VBS报错只给一行脚本语句未结束这类提示根本不知道哪一根线断了。我的土办法是写日志。在脚本里加一个简单的文本日志函数每次连接失败、执行失败、或者SQL语句拼完都把关键信息写到一个文本文件里。Sub WriteLog(msg) Dim fso, f Set fso CreateObject(Scripting.FileSystemObject) Set f fso.OpenTextFile(D:\WinCC_Log\sql_log.txt, 8, True) f.WriteLine Now - msg f.Close End Sub这个日志功能看起来很朴素但现场调试的时候真能救命。数据库连不上日志里第一行就告诉你连接字符串用的DSN是哪个、报了什么错误代码而不是让你对着WinCC的报错弹窗猜谜。我一直建议同行哪怕正式交付之后也保留这个日志甲方某天过来说数据好像断了看日志三分钟就能定位是网络、数据库还是脚本的问题。5. 踩坑实录从握手错误到脚本未结束5.1 WinCC与SQL Server的握手错误先说我遇到最多的报错连接数据库时报物理连接不是握手错误或者握手初始化失败。这个报错看起来是网络问题其实八成是ODBC驱动和SQL Server实例的配置不匹配。有一次现场就是这个报错我在工控机上用ODBC测试连接本机测试是好的一放到WinCC脚本里就报握手错误。后来发现WinCC是64位脚本运行的VBS宿主是64位但系统DSN里配置的数据源用的是32位ODBC驱动两边的位数对不上。解决办法很简单重新建一个64位的系统DSN驱动选64位的SQL Server Native Client问题立刻消失。如果你遇到类似报错排查链路建议按这个顺序先确认工控机能ping通数据库服务器再确认数据库服务器TCP/IP协议已启用、监听端口是1433然后确认ODBC数据源的位数和WinCC位数一致最后确认防火墙没拦。这个链路能解决90%的握手类问题。5.2 脚本语句未结束的真相脚本语句未结束是WinCC VBS脚本里最常见的报错之一而且这个报错特别有迷惑性它经常在脚本逻辑没错的情况下出现。我遇到过两种情况比较典型。第一种是字符串拼接时中文引号混进去了。在中文输入法状态下写VBS双引号容易打成中文全角引号脚本解析器直接懵了报语句未结束。排查方法就是把整段脚本的引号全部替换成半角引号尤其在注释里也要注意注释里的全角字符在某些情况下会让解析器行为异常。第二种是续行符后面有空字符。VBS的续行符是下划线但要求下划线前面必须有空格下一行前面不能有注释。WinCC的脚本编辑器有时候会自动在某些行前面插入缩进缩进本身没事但如果下一行是注释续行就断了。我的习惯是字符串拼接尽量写在一行内宁可长一点别用续行符就为了减少这类坑。5.3 时间字段引发的灵异事件历史数据里时间戳是灵魂但时间字段恰恰是踩坑重灾区。WinCC变量读出来的是Variant类型直接拼进INSERT语句时如果变量值本身不带日期格式会发现写入的TagTime对不上或者直接报从字符串转换到datetime失败。举个我遇到过的例子甲方要求精确记录每一次温度采样的时间WinCC脚本里我用Now()函数生成时间戳本地时间和数据库服务器时间差了8小时写入的数据全都穿越了。问题出在工控机的时区设置和数据库服务器的时区不一致服务器用的是UTC。后来统一把两边时区调整为北京时间确认数据库服务器和工控机的时间同步问题解决。另一个细节是SQL语句里的字符串日期格式。VBS拼日期字符串时用FormatDateTime(Now, 2)得到的是短日期格式但不同语言区域下短日期格式不一样有的带上午/下午拼进SQL就出错。稳妥的做法是用ISO格式Year(Now) - Right(0 Month(Now), 2) - Right(0 Day(Now), 2) Right(0 Hour(Now), 2) : Right(0 Minute(Now), 2) : Right(0 Second(Now), 2)规规矩矩不要相信Windows的区域设置。5.4 SQL Server版本之间的户口迁移有些工控项目是多年老系统数据库要整体迁移或者从旧服务器备份恢复到新服务器。行业里就有人问SQL Server 2012的数据库备份2008能用吗这类问题在工控圈太常见了因为老站点的工控机配置低装的SQL版本也老。先说结论SQL Server的备份文件往低版本恢复基本是走不通的用2012生成的备份不能直接恢复到2008。微软的备份格式是高版本向后兼容低版本低版本实例根本读不了高版本的备份文件。如果一定需要做只能用生成脚本的方式把表结构、数据、索引都脚本化到低版本服务器上重新执行但WinCC涉及的数据库往往包含大量的系统级对象和作业这种方式大概率会漏。我的建议是能升级就升级不能升级就用数据库导出工具把历史数据按表导出成CSV再导入到新库。数据表结构是自己定义的还好办如果是WinCC自动生成的归档库就别折腾了直接用WinCC自带的归档管理去迁移那才是它的强项。5.5 中文和特殊字符的暗雷最后提一个经常让人抓狂的暗雷变量值里的中文和特殊字符。如果某个变量是字符串型值可能是一号线#A段这种带井号、空格、中文的内容直接拼到SQL语句里要么被解析成注释要么因为编码不一致变成乱码。解决方案有两个一是写入之前用单引号把字符串引起来并把字符串里的单引号替换成两个单引号SQL的转义规则二是干脆不要用字符串直接拼接改用ADODB的Command对象通过参数化查询把变量值作为参数传入。参数化查询不仅安全还能避免很多编码和转义的问题我后期写的脚本全部改成了这种写法一次到位。6. 数据安全与性能优化批量写入、缓存机制、断线重连6.1 频繁连接数据库的代价如果按最基础的写法每条记录新建一个连接、执行完再关闭数据量小的时候看不出问题但项目上线跑一段时间就会暴露隐患。每秒钟几十次连接建立和关闭SQL Server会不断分配和释放内存WinCC的脚本引擎也在反复创建COM对象最终表现就是WinCC的操作响应变慢数据库服务器的日志里全是登录和退出记录磁盘IO也飙高。我自己在项目里测试过50个变量按1秒周期写入采用每条记录单独连接的方式数据库服务器的CPU占用率能到30%以上改成连接复用加批量写入后CPU占用率降到3%以下。这个差距是肉眼可见的方案设计时一定要把这一步考虑进去。6.2 连接复用与批量写入的实现思路连接复用的做法很简单把连接对象定义成全局变量在WinCC运行系统启动时创建一个连接之后所有脚本执行都复用这个连接。如果担心连接断开可以在每次执行前检查conn.State如果状态不是1adStateOpen就重新Open一次。这样既避免了频繁重建连接又能在连接意外断开时自动恢复。更进一步是批量写入。把要插的数据先放在一个集合里比如50条记录攒在一起然后用INSERT INTO ... VALUES (..), (..), (..)这种多值语法一次性提交。SQL Server处理这样的批量插入比50次单条插入要快一个数量级。代码实现也不复杂在脚本里维护一个数组达到一定数量就执行一次批量INSERT同时清空数组。注意批量INSERT的时候SQL语句的长度不能超过数据库的SQL长度限制一般50条一拼是安全的。6.3 断线重连与数据丢帧问题任何上位系统都可能遇到数据库服务器重启、网线被拔掉的情况。数据库连接断了之后如果脚本只是报个错那断线期间的数据就全丢了。历史数据存储方案里最怕的就是这个。我的处理思路是把数据分两层第一层是内存缓存第二层是磁盘缓存。内存缓存适合秒级短断线的场景数据库恢复之后把积攒的数据补写进去磁盘缓存适合长断线场景比如断网半小时内存肯定装不下那就先把记录写成CSV或者文本文件等连接恢复后由后台脚本读取文件补库。具体做法不复杂在脚本里维护一个失败计数器连续失败N次后就把待写入的记录附加到一个文本文件里同时定期检查数据库是否恢复恢复后先补文件数据再恢复正常写入。这个机制实现起来大概多花半天时间但能让方案在恶劣现场环境下不掉链子我觉得非常值。6.4 数据清理与备份策略历史数据是只增不减的跑几个月之后数据库文件可能膨胀到几十GB磁盘和备份都吃不消。方案设计阶段就要把数据生命周期策略定好。我常用来做的是按时间分区建表时就按月份做分区或者干脆写一个定期清理脚本删除超过保留期的记录。比如甲方要求保存一年那就每月跑一次清理任务删除一年前的明细数据。注意DELETE操作在数据量很大的时候也会锁表影响写入最好放在凌晨的生产空闲时段执行或者先归档到历史表再删除主表数据。备份策略上工控系统的数据库备份不需要像IT系统那么频繁但每周全量备份加每日增量备份是基本盘。备份文件不要放在系统盘最好放到单独的存储盘或者网络存储上不然服务器磁盘坏了数据和备份一起没那就真成了事故了。6.5 质量码的处理细节WinCC的变量除了数值还有一个质量码Quality Code表示当前值的可信程度。脚本读取变量时连接状态这些信息都隐含在质量码里。如果设备断线PLC不刷新数据变量值会保持最后一个正常值但这个值的质量码已经变了。如果我们不管质量码把这种假值也写进历史表报表里会出现连续一样的数值误导后续分析。所以我在写入逻辑里增加了一个判断读取变量值的同时读取质量码质量异常时把Quality字段写成非0值写入正常值为0。后续查询、做报表时可以用WHERE Quality 0把异常数据排除或者用质量码做数据有效性分析。这个细节不值多少钱但报表的可靠性能提高一大截。7. 方案落地后的扩展从数据库到可视化7.1 用WinCC的表格控件展示历史数据数据进了SQL Server之后下一步就是把它展示给甲方。WinCC自带的表格控件比如WinCC表格控件可以通过ADO绑定数据库的数据源在画面里以表格形式显示某个变量某段时间的记录。配置要点是把数据源指向ODBC DSN然后在SQL查询里写过滤条件比如按变量名、时间段查询。这个方式比自带的归档趋势控件灵活得多因为SQL是活给的想查什么查什么。7.2 用趋势控件读数据库画曲线如果想在画面上画历史趋势曲线也可以用WinCC的趋势控件把数据源绑定到SQL查询结果。不过这里有个容易掉进去的坑WinCC趋势控件对数据源绑定的时间格式很挑剔如果SQL查询返回的时间字段格式和控件期望的格式不匹配曲线会显示不出来或者乱序。处理方法是在SQL查询里就把时间格式化成控件能识别的字符串或者直接返回datetime类型字段不要返回文本时间。实际上我见过不少项目干脆不折腾WinCC自带控件了直接在WinCC画面里嵌入一个WebBrowser控件用HTML页面加JavaScript图表库比如ECharts从数据库拉数据画曲线。这样做的好处是图表样式完全可控、交互体验好缺点是HTML页面的开发量更大而且需要处理好WinCC运行系统与内网Web服务的通信。项目时间宽裕的时候这个方案效果更惊艳。7.3 给甲方交付时的数据校验清单方案交付前我习惯按一张清单做最终检查避免上线后才发现低级问题抽查写库时间是否和PLC时间对齐检查是否存在固定的时间偏差时区、时钟同步。把WinCC趋势图上的原始数据和数据库里的值做交叉比对确保没有数值缩比、类型转换错误。模拟一次数据库故障确认断线补录机制能正常工作。检查数据清理任务是否注册到计划任务防止长期运行没有清理导致磁盘满。确认数据库备份任务正常备份文件能被恢复。这个清单每一次都能抓出至少一两个问题强烈建议同行在交付前宁可多花半小时做一遍。
