C#上位机的数据库设计,昆山产线项目里的经验就一句话:表结构先于代码定型,四张核心表(标签点表、事件流水、配方表、生产工单)把设备、过程、工艺、生产四类数据一次装下,之后所有业务都在它们之上长。这篇把每张表的字段设计、主外键关系、历史归档和读写隔离的落地做法摊开讲,附可以直接抄的建表SQL。
上位机数据到底分几类?四张表怎么各司其职?
先想清楚一个车间的数据本质。设备在动(电压电流温度)、过程在发生(报警、启停、配方切换)、工艺在变(配比、参数、物料)、生产在记账(工单、产量、良率)。对应到数据库就是老话常说的四类:设备标签是"点",事件流水是"迹",配方是"标准",生产工单是"账"。昆山的教训主要是顺序问题——很多项目一上来就堆几十张业务表,设备点还没管清楚,后面全乱。我的建议是先把这四张表钉住,跑通了再往上加。
四张表的关系,用一句话能串起来:某张生产工单在若干台设备上执行,每台设备用某套配方干活,设备上的标签值(标签点表)和发生的报警记录(事件流水)滚动记录整个过程。下面把实体关系画成一张图,字段细节一张张过。
先钉标签点表和事件流水——设备侧的"点"与"迹"
标签点表是上位机的骨架。它把PLC里一串软元件地址翻译成有名字的业务点:D100=料温,D104=转速,M20=门联锁。这样业务代码只认TagKey,不碰裸地址。字段别省,点名、类型、单位、上下限、所属设备、读写权限都值得存下来,后面做画面、做报表、做权限全靠它。
| 字段 | 类型 | 说明 |
|---|---|---|
| TagKey | varchar(50) PK | 唯一业务名,如 Temp.Oven1.D201 |
| DeviceId | int FK → Device | 归属设备 |
| Address | varchar(30) | 软元件地址 D500 / D104 / M20 |
| DataType | tinyint | 0=开关量 1=16位整 2=32位浮点 3=字符串 |
| Unit / RangeLo / RangeHi | varchar / float | 单位与合法区间,供过滤与minmap用 |
| AccessRight | tinyint | 1=只读 2=操作员可写 3=工程师可写 |
| CreateTime | datetime2 | 建点时间 |
事件流水表管"迹",不带业务状态、只记发生了啥。关键在于列应有尽有:发生时间、事件类型(报警/配方切换/启停/人员操作)、关联点、事件代码、描述、操作人、处置状态。查询永远是"这张表按时间段+类型"出报表,所以CreateTime 一定要建索引,事务级实时产生的记录,顺序存、按需查,别在流水表上做复杂更新。
配方表和生产工单表——工艺的"标准"与生产的"账"
配方表常被做成"一表一行配方"的坑。标准做法是拆成两表:配方主表(RecipeHeader,配方号、名称、版本、状态)加配方项表(RecipeItem,配方号FK、参数项、目标值、上下限)。这样换配方版本只是加一条带新版本号的头记录,旧版本留着好追溯,报工出错时能查"当时用的是哪版参数"。
生产工单表是业务账本:工单号、产品号、数量计划、设备、起始时间、合格数、不良数、良率。它和标签/流水是弱关联——工单本身不存每条采集数据,只通过时间范围加设备号把过程数据圈出来。这个设计很关键:报表要"这块这个工单的曲线",就是按 WorkOrder 的 Start/End + DeviceId 过滤标签历史,不用在工单表里塞大字段。
▲ 工单关联历史数据的标准写法:时间范围 + 设备号,而非全表扫
历史数据怎么存、怎么归档才不拖垮主库?
标签的当前值放主表,历史值得跟主表分开。常用做法是TagHistory 按天分表或按月分表,主键用 (TagKey, SampleTime),只插不更新。上位机 C# 侧用批量插入(SqlBulkCopy),几千点在线的车间,一秒写进库也不卡。归档:老数据按月移到归档库或直接分区后drop,主库永远只留三个月内的热数据,报表从历史库跨区查。采集写库和业务读库物理分开(两个库或两个连接串),写库不能被打断,读库可以稍微排队。
字段命名和权限,两条能少加班的铁律
命名上统一三条:主键统一叫 Id(bigint),业务唯一键叫 xxxNo(OrderNo/RecipeNo),时间统一叫 xxxTime(datetime2)。别一会儿 User_Id 一会儿 userID 一会儿 user_id,C# 团队一散人就乱套。时间戳一定要用 datetime2,SQL Server 默认的 datetime 精度到 3ms,毫秒级采集装了也无福消受。
权限不用复杂到角色表,先用 AccessRight 一个字段三层(只读/操作员/工程师)管住标签点的写权限,登录后鉴权就在写之前拦一道。对了,操作要留痕——C# 里所有写配方、改参数、切工单的入口,统一收口到一个带审计的 Service 方法,别让 UI 直接握 SqlConnection,不然查"谁改的"会查得想哭。
新项目建库,第一步该做什么?
行动建议:动手写代码前,先花半天把四张核心表建出来、灌几条假数据、把那个按工单圈曲线的 SQL 跑通。这个 SQL 能跑顺,说明表关系是对的,后面所有报表都是它的变形。数据库设计这事,晚一天定型,后面就要拿加班的倍数来还。