☰
卫宁电子病历表结构解析:从800张表中定位医嘱、诊断与收费核心链路
2026/10/11 16:11:24 网站建设 项目流程

简介:卫宁电子病历表结构文档面向医院信息管理者、IT技术人员及医疗信息化研究人员,系统梳理了卫宁EMR 5.0的数据库设计框架,帮助读者理解临床信息系统的底层数据模型与标准化规范。资源包内含1个doc文件,大小约13.92MB,以数据库结构设计说明书形式呈现,涵盖系统框架、财务收费、医疗信息等模块的字段定义与值域说明。文档详细列出800多张数据表,包括职工代码库、医疗项目库、药品分类库、科室与病区代码库、凭证类型库、收费大项目库、医保分类库、诊断代码库等,每张表均标注字段类型、长度、备注及取值范围,便于数据交换与互操作。目前已有1543人学习下载,适合用于优化系统结构、排查数据问题及开展医疗大数据分析,是掌握卫宁EMR数据结构与业务建模的实用参考资料。

1. 卫宁电子病历表结构到底存了什么:从 800 张表里挑出能用的那几张

接手一家二级医院的 HIS 数据对接时,对方丢过来一个压缩包,里面就一份《卫宁电子病历表结构.doc》。翻了两页我就明白,这不是一份能直接跑的代码,而是一份数据库字典——临床信息系统 5.0 版本,上海金仕达卫宁那套 EMR 的底层表结构说明。它把系统框架、医生工作站两大模块下 800 多张表的表名、字段、类型、长度、备注和值域全列了出来,从职工代码库 SYS_ZGDMK 到新生儿首页库 CPOE_BABYSYK,一张不落。

这份东西解决的不是"怎么写代码",而是"数据到底落在哪张表、哪个字段、什么含义"。做接口对接、做数据抽取、做报表二次开发的人最怕字段名靠猜,有了它就能少走一大截弯路。适合医院信息科、做医疗数据集成的乙方、以及要基于卫宁 EMR 做数据仓库的工程师。下面按我实际拆库的顺序讲,先立住表结构这套体系怎么读,再落到具体怎么查、怎么用、哪里会翻车。

2. 读懂卫宁表结构:命名前缀、代码库与业务库的分层逻辑

拿到一份几百张表的字典,第一件事不是逐张看,而是先摸清它的命名规律和分层。卫宁这套结构其实分得很清楚,前缀就是分类标签,看表名基本能猜出它属于哪一层、干什么用。搞懂这层逻辑,后面查表效率能翻好几倍。

2.1 三类前缀:SYS、PUB、CPOE 各管什么

从目录能明显看出三组前缀。SYS_ 开头的是系统级基础库,比如 SYS_ZGDMK 职工代码库、SYS_KSDMK 科室代码库、SYS_BQDMK 病区代码库,这些是全系统共用的主数据,改动影响面最大。PUB_ 开头的是公共代码库和对应关系库,像 PUB_YLXMK 医疗项目库、PUB_YPFLK 药品分类库、PUB_ICD10 诊断代码,还有一堆"对应库"如 PUB_KSYFDYK 科室药房对应、PUB_JXYFDYK 剂型用法对应,这类表专门存多对多的映射关系。CPOE_ 开头的是医生工作站业务库,是真正产生临床数据的地方,医嘱、申请单、手术记录、输血、小处方全在这一层。

这个分层不是随便起的。SYS 和 PUB 属于"字典/主数据",相对静态,一个季度可能都不动一次;CPOE 属于"业务流水",每天都在涨。做数据同步时,字典表可以全量拉、低频同步,业务表必须走增量。我一般会先把所有 SYS_ 和 PUB_ 表拉一份全量做本地字典,CPOE_ 表按时间字段做增量。

2.2 代码库与对应库:值域从哪来

字典里每张表都标了字段的值域,这是它比一般逆向出来的表结构值钱的地方。比如 PUB_YBFLK 医保分类库,字段值域直接告诉你医保类别怎么编码;PUB_SSDJDMK 手术等级代码库,手术分级的标准值就在里面。这些值域是业务规则的固化,比你自己去猜"这个 1 代表什么、2 代表什么"靠谱得多。

对应库更关键。像 PUB_KSYFDYK 科室药房对应、PUB_MZSFZXKSK 门诊收费执行科室对应、CPOE_YPYFDYK 药品用法对应,这些表本身不存业务数据,存的是"谁和谁有关系"。做数据关联查询时,如果不认识这些对应库,很容易写出笛卡尔积或者漏关联。我的习惯是先把所有带"对应"二字的表单独列一张清单,标注它连接的是哪两张主表,画成一张关系草图。

2.3 用 SQL 把表清单和字段结构导出来

光看 doc 效率低,实际干活时我会先把字典里的表名批量转成可查询的元数据。如果目标库是 SQL Server(卫宁老版本常见),可以直接查系统视图把表结构拉出来,和 doc 对照:

-- 拉取所有表名及字段结构,用于和 doc 字典对照 SELECT t.name AS 表名, c.name AS 字段名, ty.name AS 字段类型, c.max_length AS 长度, c.is_nullable AS 允许空, ep.value AS 字段备注 -- 扩展属性里通常存了中文备注 FROM sys.tables t JOIN sys.columns c ON t.object_id = c.object_id JOIN sys.types ty ON c.user_type_id = ty.user_type_id LEFT JOIN sys.extended_properties ep ON ep.major_id = c.object_id AND ep.minor_id = c.column_id AND ep.name = 'MS_Description' WHERE t.name LIKE 'CPOE[_]%' -- 只看医生工作站业务表 ORDER BY t.name, c.column_id;

这段查询的逻辑是:sys.tables拿表,sys.columns拿字段,sys.types拿类型,sys.extended_properties里MS_Description这个扩展属性通常存了字段的中文备注——卫宁建库时一般会把 doc 里的备注写进去。LIKE 'CPOE[_]%'里的下划线是通配符,用[_]转义成字面量下划线,否则会把CPOE后面任意一个字符都匹配上。跑完这份结果,你手里就有一份和 doc 能对上的活字典,比翻 Word 快得多。

提示:不同医院部署时字段备注可能被清空或改写,如果MS_Description查出来是空的,就以 doc 里的备注为准,别硬信数据库。

3. 从字典到可用数据:定位医嘱、诊断、收费三张核心链路

表结构读懂了,接下来是真正落地——把临床业务里最常用的三条数据链路摸出来。医嘱、诊断、收费是 EMR 数据抽取绕不开的三块,也是接口对接时问得最多的。这一章按链路讲,每条链路给出关键表和关联字段。

3.1 医嘱链路:CPOE_YZ 系列怎么串

医嘱相关的表在目录里是一大簇,全以 CPOE_YZ 开头。核心是 CPOE_YZDJK 医嘱单据、CPOE_YZLXK 医嘱类型库、CPOE_YZYPPCK 医嘱药品频次库、CPOE_YZYPYFK 医嘱药品用法库,还有 CPOE_YZPCYFDYK 医嘱频次用法对应库、CPOE_YZSXTJDYK 医嘱时限条件对应库、CPOE_YZYLKZXXK 医嘱用量扩展信息库。

一条医嘱从开出到执行,数据是分散在多张表里的:主记录在医嘱单据表,频次和用法通过对应库关联到字典,用量扩展信息单独一张表。做抽取时最容易犯的错是只拉主表,结果频次、用法全是编码,没法读。正确做法是把对应库一起 join 进来翻译成中文。

-- 抽取医嘱主记录并翻译频次、用法编码 SELECT yz.医嘱ID, yz.病人ID, yz.医嘱内容, yz.开始时间, pc.频次名称, -- 来自 CPOE_YZYPPCK yf.用法名称 -- 来自 CPOE_YZYPYFK FROM CPOE_YZDJK yz LEFT JOIN CPOE_YZYPPCK pc ON yz.频次编码 = pc.频次编码 LEFT JOIN CPOE_YZYPYFK yf ON yz.用法编码 = yf.用法编码 WHERE yz.开始时间 >= '2024-01-01' AND yz.开始时间 < '2024-02-01';

这里字段名是示意,实际以 doc 里每张表的字段定义为准——doc 里 CPOE_YZDJK 和 CPOE_YZYPPCK 的字段名、类型、长度都列了,照着填就行。LEFT JOIN而不是INNER JOIN是有意的:医嘱的频次或用法编码偶尔会有字典里查不到的历史值,用内连接会直接丢记录,做数据核对时这种丢失最难查。参数上,时间范围一定要卡在业务表的时间字段上,别用自增 ID 做增量,卫宁老库的 ID 生成规则不一定单调。

3.2 诊断链路:ICD10 与诊断分类明细

诊断这块,字典层是 PUB_ICD10 ICD10 诊断代码和 PUB_ICD9 ICD9 诊断代码,业务层是 CPOE_ZDFLK 诊断分类库、CPOE_ZDFLMXK 诊断分类明细库、CPOE_ZDXGZ 诊断相关组。ICD10 表是标准编码,诊断分类明细是医院自己维护的分类树。

做病种统计时,常见做法是先用 ICD10 编码定位到标准诊断,再通过诊断分类明细映射到医院内部的大类。这里有个坑:ICD10 编码在不同版本间有细微差异,doc 里标的是 5.0 版本对应的编码集,如果医院后来升级过编码库,doc 和实际库会对不上。核对方法是拿几个高频诊断编码去 PUB_ICD10 里查,看是否存在、名称是否一致。

3.3 收费链路:从收费大项目到临床收费项目

收费链路横跨字典层和业务层。字典层有 PUB_SFDXMK 收费大项目库、PUB_SFXMLBK 收费项目类别库、PUB_SFXXMK 导入收费小项目库、PUB_LCSFXMK 临床收费项目库,业务层有 CPOE_SFXMJLPCDYK 收费项目剂量频次对应库、CPOE_YBXMDYK 医保项目对应库、CPOE_YBYPBXBLDYK 医保药品报销比例对应库。

这条链路的价值在于:临床开单时用的是临床收费项目,财务结算时用的是收费大项目,医保报销又走医保项目对应。三套编码之间靠对应库打通。做费用分析时,如果只取一套编码,口径一定对不上。我一般会先把 PUB_LCSFXMK、PUB_SFDXMK、CPOE_YBXMDYK 三张表的对应关系拉出来,做成一张宽表,后续所有费用统计都基于这张宽表,避免每次查询都重新 join。

注意:医保报销比例对应库 CPOE_YBYPBXBLDYK 里的比例是政策值,会随政策调整,做历史数据分析时不能拿当前比例去算历史费用,必须按费用发生时间取当时生效的比例。

4. 避坑与排查:拆卫宁表结构时最容易翻车的五件事

这份 doc 是 2014 年 5.0 版本的,实际医院部署的版本、补丁、二次开发程度都不一样。下面五条是我和同行踩过的真实坑,按"现象 → 原因 → 解决"写,照着排查能省不少时间。

4.1 表名对得上但字段对不上

现象:doc 里 CPOE_YZDJK 有某个字段,实际库里查不到,或者类型不一样。原因:医院做过版本升级或二次开发,加了自定义字段、改了字段长度,doc 没同步更新。解决:以实际库的sys.columns查询结果为准,把 doc 当参考而不是圣旨;对关键表做一次字段差异比对,把差异记录下来维护成自己的补丁字典。

4.2 中文备注全是乱码或空

现象:查MS_Description出来是问号、乱码或者 NULL。原因:建库时字符集不一致,或者备注根本没写进扩展属性。解决:优先信 doc 里的备注;如果 doc 也没有,就结合字段名拼音缩写和值域反推,比如SFXM大概率是"收费项目"。别在乱码上浪费时间,直接换数据源。

4.3 对应库关联后数据翻倍

现象:join 了对应库之后记录数暴涨。原因:对应库是多对多关系,一张主表记录可能对应多条映射。解决:先单独查对应库,确认是一对一还是一对多;一对多时要么用聚合,要么明确业务上取哪一条(比如取最新生效的那条)。做数据核对时,join 前后都 count 一下,数字对不上立刻停下来查。

4.4 增量抽取用错时间字段

现象:增量同步漏数据或重复。原因:用了自增 ID 或创建时间做增量,但业务表存在补录、修改,创建时间不更新。解决:找业务上的"最后修改时间"字段,没有的话就用变更日志表;实在没有,只能全量比对。卫宁老库不一定有标准的更新时间字段,这点要提前和医院信息科确认。

4.5 值域理解偏差导致统计口径错

现象:统计出来的数字和医院报表对不上。原因:doc 里字段值域标了 1/2/3,但没写清楚每个值的确切含义,自己猜错了。解决:拿实际数据去反查,比如某个状态字段,把每个值对应的记录抽样出来看业务含义;或者直接问医院信息科要一份值域对照表。别自己猜,猜错的口径后面全盘皆输。

5. 把表结构变成可维护的资产:元数据比对与版本管理

拆完一遍之后,真正让这份 doc 长期有用的,不是把它背下来,而是把它变成一份可维护、可比对的元数据资产。我现在的习惯是:每接手一个卫宁 EMR 库,先跑一遍元数据导出,和 doc 做差异比对,把结果存成版本化的文件,下次升级或换医院时直接 diff。

具体做法是写一个导出脚本,把表名、字段名、类型、长度、备注全导成结构化格式(CSV 或 JSON),然后和上一版做对比。下面是一个导出并比对的最小示例:

import csv import subprocess # 假设用 sqlcmd 或类似工具把元数据查出来存成 CSV # 这里演示比对逻辑:找出新增、删除、类型变化的字段 def load_meta(path): meta = {} with open(path, encoding='utf-8') as f: for row in csv.DictReader(f): key = f"{row['表名']}.{row['字段名']}" meta[key] = (row['字段类型'], row['长度']) return meta old = load_meta('meta_v1.csv') new = load_meta('meta_v2.csv') added = [k for k in new if k not in old] removed = [k for k in old if k not in new] changed = [k for k in new if k in old and new[k] != old[k]] print(f"新增字段 {len(added)} 个") print(f"删除字段 {len(removed)} 个") print(f"类型/长度变化 {len(changed)} 个") for k in changed: print(f" {k}: {old[k]} -> {new[k]}")

这段脚本的核心是load_meta把元数据读成字典,key 用"表名.字段名"保证唯一,value 存类型和长度。比对时三个集合分别对应新增、删除、变更。changed那行是关键——类型或长度变化往往意味着业务规则调整,比如某个金额字段从decimal(10,2)变成decimal(12,2),可能是业务量涨了,也可能是精度要求变了,值得单独看一眼。

参数上,meta_v1.csv和meta_v2.csv分别对应两个时间点或两家医院的导出结果。实际用的时候,我会把每次导出的文件按"医院代号_日期"命名,存进 Git,这样任何一次结构变更都有记录,出问题能回溯到是哪次改动引入的。

提示:比对结果里"删除字段"要特别小心,很多医院不会真删字段,而是停用,直接按删除处理可能误判。最好结合数据是否还有值来判断。

从那以后我每次接手新的卫宁 EMR 库,都强制先跑一遍元数据导出和 doc 比对,把差异记下来再动手写任何查询。这份 5.0 的表结构 doc 不是终点,而是一张起点地图——它告诉你路大概怎么走,但每条路实际通不通、有没有改道,得自己走一遍才知道。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询