简介这份资源面向工业自动化工程师与WinCC初学者聚焦西门子WinCC监控系统的报警、变量数据读取与归档操作帮助解决从项目工程中提取历史数据、分析报警事件的实际问题。压缩包共41个文件约84KB以C#源码.cs为核心辅以resx与resources资源文件、exe可执行程序、config配置及pdb调试文件构成一个可运行的WinCC数据读取示例工程。工程内包含报警日志、变量记录、用户归档等多个功能窗体演示了连接WinCC数据库、构建SQL查询、处理结果集并导出数据的完整流程。已有380人学习下载适合希望掌握WinCC归档数据访问与数据库查询技巧的读者参考可据此理解WinCC项目结构、脚本读取思路及数据统计与可视化方法为数据驱动的生产优化提供实践基础。1. 从 ReadWinCCData_1.rar 说起WinCC 归档数据到底藏在哪手里拿到一个叫 ReadWinCCData_1.rar 的包旁边还跟着 WinCC、归档数据、数据库、工程几个词多数人的第一反应是这玩意儿是不是能直接读出 WinCC 里的历史曲线答案取决于你读的是哪一层。WinCC 的归档数据并不是一个躺在工程目录里、双击就能打开的表格文件它由运行系统在运行时写入按时间片滚动底层落在 SQL Server 的数据库里工程侧只保留组态和分段信息。所以“读 WinCC 归档数据”这件事本质是绕过画面直接和运行库、归档库打交道。适合谁做数据采集、报表对接、MES 集成、历史数据迁移的现场工程师以及手里有老 WinCC 工程、需要把趋势数据导出来做分析的人。下面按“先认清数据在哪、再动手连、最后避坑”的顺序讲透。2. WinCC 归档数据的存储结构与连接选型为什么不能直接拷 .db 文件2.1 归档分两类落库方式完全不同WinCC 的归档粗分两种过程值归档和消息归档。过程值归档又分快速归档和慢速归档快速归档按周期写慢速归档按归档周期压缩写。它们最终都进 SQL Server但表结构和写入节奏不一样。快速归档对应的是实时性要求高的变量慢速归档对应变化不频繁、需要长期保留的变量。消息归档则是报警和事件记录走的是另一套表。关键点在于WinCC 运行时会持有数据库连接归档写入是持续进行的。你如果直接去拷贝正在运行的 SQL Server 数据文件.mdf/.ldf大概率拿到的是不一致的快照甚至触发文件占用。常见做法是要么在 WinCC 停止运行时拷贝要么通过 SQL 查询在线读取。现场更推荐后者因为停运行系统意味着停产线监控。提示WinCC 的归档数据库默认命名和工程名相关常见的有以工程名加后缀的库具体名称以你现场 SQL Server 实例里看到的为准不要照搬网上的库名。2.2 连接方式选型SQL 直连、WinCC ODK、还是 OPC UA三条路适用场景不同方式适用场景优点限制SQL Server 直连只读历史归档、做报表灵活、可跨库查询需要知道表结构受权限限制WinCC ODK/脚本工程内取实时归档与 WinCC 集成好依赖 WinCC 环境部署重OPC UA跨系统、跨版本对接标准化、解耦需要 WinCC 侧配置服务器老版本支持有限如果你只是要把历史数据导出来SQL 直连是最短路径。如果你要在另一个系统里持续订阅OPC UA 更合适。ODK 适合已经在 WinCC 工程里做二次开发的场景。2.3 用 SQL 查询读取归档的最小步骤先确认 SQL Server 实例名和 WinCC 使用的库。用 SSMS 或命令行连上去列出数据库-- 列出当前实例下的所有数据库找到 WinCC 归档库 SELECT name, database_id, create_date FROM sys.databases ORDER BY create_date DESC;逻辑说明WinCC 归档库通常和工程创建时间接近按创建时间倒序能快速定位。参数说明不需要额外参数直接执行即可。如果权限不足联系 DBA 开只读账号。找到库之后看表。归档表命名有规律常见以归档名或内部编号命名。不要猜直接查-- 切换到目标归档库后列出所有表 USE [你的归档库名]; GO SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE BASE TABLE ORDER BY TABLE_NAME;逻辑说明先看清有哪些表再决定查哪张。参数说明把方括号里的库名替换成实际名称。这一步能避免对着错误表结构写半天 SQL。3. 把归档数据读出来查询、导出与字段对齐的实操3.1 归档表的时间字段和值字段怎么认WinCC 归档表一般有时间戳列和值列。时间戳可能是本地时间也可能是 UTC取决于工程组态。值列的类型和变量类型对应浮点、整型、字符串各有不同。不要假设所有值列都是 float遇到字符串归档直接转数值会报错。常见做法是先取一行样本看数据-- 取前 10 行样本观察时间列和值列的实际内容 SELECT TOP 10 * FROM [你的归档表名] ORDER BY [时间列名] DESC;逻辑说明先看数据长什么样再写精确查询。参数说明把表名和时间列名替换成实际名称。如果表很大加 TOP 避免全表扫描拖慢数据库。3.2 按时间范围导出到 CSV 的完整脚本假设你已经确认表名是 ArchiveTable时间列是 TimeStamp值列是 Value导出某一天的数据-- 导出指定时间范围的归档数据 SELECT TimeStamp, Value FROM ArchiveTable WHERE TimeStamp 2026-01-01 00:00:00 AND TimeStamp 2026-01-02 00:00:00 ORDER BY TimeStamp ASC;逻辑说明用半开区间避免边界重复。参数说明时间格式用 SQL Server 能识别的字符串如果时间列是 UTC查询条件也要用 UTC。导出时在 SSMS 里右键结果选“另存为 CSV”或者用 bcp 命令行。如果数据量大用 bcp 更快# 用 bcp 导出归档数据到 CSV-c 表示字符模式-t 指定分隔符 bcp SELECT TimeStamp, Value FROM 归档库.dbo.ArchiveTable WHERE TimeStamp 2026-01-01 queryout D:\export\archive.csv -c -t, -S 服务器名 -U 用户名 -P 密码逻辑说明bcp 适合百万行级导出比 SSMS 界面导出稳定。参数说明-S 后跟实例名-U/-P 是账号密码生产环境建议用集成认证避免密码明文。3.3 字段对齐变量名和归档列的映射关系WinCC 工程里变量名和归档表列名不是一一对应的。常见做法是查 WinCC 的组态数据库或归档配置表找到变量到归档的映射。如果找不到就按归档顺序和变量类型人工比对。这一步没有捷径血泪经验是先导出少量数据和 WinCC 趋势画面对比确认列对应关系后再批量导。注意不要直接修改归档库里的任何表只读。写入操作可能破坏 WinCC 运行系统的归档完整性。4. 避坑与排查读 WinCC 归档数据时最容易翻车的 5 个点4.1 现象查询超时SSMS 卡死原因归档表数据量巨大没有索引或查询条件没走索引全表扫描。解决先查表索引情况尽量用时间列做范围过滤避免 SELECT *。如果必须全量导出分批按天或按小时查。4.2 现象读出来的值和画面上不一致原因时间戳时区不一致或者读的是快速归档而画面显示的是慢速归档。解决确认时间列是本地还是 UTC确认归档类型。用同一时间段在 WinCC 画面上对比锁定差异来源。4.3 现象连接被拒绝提示登录失败原因WinCC 运行账户和 SQL 登录账户权限不匹配或者 SQL Server 只允许 Windows 认证。解决找 DBA 开只读账号或者用 Windows 认证在相同域环境下连接。不要用 sa 账号做长期采集。4.4 现象导出 CSV 中文乱码原因bcp 默认编码和 Excel 预期不一致。解决导出后用文本编辑器转 UTF-8 with BOM或者用 SSMS 导出时选 Unicode。如果值列里有中文优先用 SSMS 导出。4.5 现象WinCC 运行中数据库文件被占用无法拷贝原因SQL Server 持有文件句柄。解决不要拷贝正在运行的 .mdf/.ldf。用 SQL 查询在线读或者停 WinCC 后再拷贝。停之前确认产线允许。5. 进阶把归档读取做成可复用的采集任务5.1 用 Python 定时拉取增量数据现场不可能每次手动导。常见做法是写一个 Python 脚本按时间窗口增量查询写入本地库或 CSV。核心是记录上次读取的最大时间戳下次从那里继续。import pyodbc import csv from datetime import datetime, timedelta # 连接 WinCC 归档库驱动名以现场安装为准 conn pyodbc.connect( DRIVER{SQL Server}; SERVER你的服务器名; DATABASE你的归档库名; UID只读账号; PWD密码; TrustServerCertificateyes; ) cursor conn.cursor() # 增量窗口从上次时间戳到当前首次运行可指定起始时间 last_ts datetime(2026, 1, 1, 0, 0, 0) now_ts datetime.now() cursor.execute( SELECT TimeStamp, Value FROM ArchiveTable WHERE TimeStamp ? AND TimeStamp ? ORDER BY TimeStamp ASC , last_ts, now_ts) rows cursor.fetchall() with open(archive_increment.csv, a, newline, encodingutf-8-sig) as f: writer csv.writer(f) for row in rows: writer.writerow([row[0], row[1]]) # 更新 last_ts 为本次最大时间戳供下次使用 if rows: last_ts rows[-1][0] print(f本次导出 {len(rows)} 行下次起点 {last_ts})逻辑说明用参数化查询避免 SQL 注入增量窗口避免重复。参数说明last_ts 持久化到文件或数据库不要每次从固定时间开始。驱动名根据现场安装的 ODBC 驱动调整常见是 SQL Server 或 ODBC Driver 17。5.2 验证采集完整性的三个检查点第一行数对比同一时间段Python 导出的行数和 SSMS 直接查的行数一致。第二时间连续性检查时间戳有没有跳变或重复。第三值域抽查随机抽几个时间点和 WinCC 画面比对。这三个检查做完基本能确认采集链路可靠。5.3 我自己的习惯我一般会在采集脚本里加一个日志文件记录每次运行的时间、行数、最大时间戳。出问题时先看日志比翻数据库快。另外只读账号权限只给 SELECT不给任何写权限这是后悔药。希望帮到你。本文还有配套的精品资源点击获取