简介《天健医院信息系统数据结构手册》是一份面向HIS系统开发、实施及运维工程师的数据库表结构说明文档。内容围绕天健医疗HIS系统展开按公共字典、人员属性、国家地区单位、科室字典等模块梳理数据表包含性别、婚姻、民族、血型、职业、身份、费别、病人来源、军种、勤务等常用字典以及工作人员、技术职务、社会关系、合同单位、临床科室配置、科室与病房对照、营养室、大单位等核心表便于快速定位业务字段与跨表关联关系。手册还附有版本更新记录和分模块目录并用红、蓝、黑三色标识表及字段的在用、新增与未使用状态便于按图索骥。资源共1个文件为doc格式文档压缩包大小约7.19MB属于较完整的单册技术手册。已有850人学习下载适合需要了解天健HIS底层数据结构、进行二次开发或数据查询分析的中高级工程师参考。1. 天健医院信息系统数据结构手册是做什么的不是从头读的是拿来对着查的一份天健医院信息系统数据结构手册.doc 摆到桌面上通常不是让你从头读到尾的。它出现在两种场景要么你刚接手一套跑了好多年的 HIS要做接口对接、DRG 上报、数据迁移或报表开发厂商丢给你这份文档当“产品说明书”要么你在做系统选型或验收想搞清楚这套系统底层到底存了什么。它要回答的核心问题就三个业务数据落在哪张表、字段叫什么、字典值是什么意思。注意标题里的“数据结构”跟算法课上的链表队列没关系这里指的是 HIS 里库表的组织方式每张业务表、每个字段、每本字典代码。HIS 项目里最常见的困境是系统本身像个黑匣子按钮能点但拿不到干净的数据。你需要的不是一份科普而是一条从文档走到可执行 SQL 的路径。下面这套读法按“扒结构 → 落 SQL → 对现网”推进每一步都能直接复用尤其适合已经拿到数据库账号、正准备写第一条取数 SQL 的开发和实施同学。2. 从 .doc 到可查的表清单先按“模块→物理表→字段”三层扒结构拿到这种 .doc 手册我一般不去啃正文先干三件事翻目录、找表清单、看字典。老一代国内 HIS 的数据结构手册写法通常很统一先讲总体架构再讲编码规范然后按业务模块列一堆表每张表占一节最后附代码字典。麻烦的是 .doc 是二进制格式Word 里翻着费劲想用脚本批量提取更是无从下手。所以第一步永远是把它转成能程序化处理的东西。2.1 快速扫一遍 doc从目录页和章节标题锁定模块边界先把 .doc 统一转成 .docx再用 python-docx 读章节标题这样整个文档的骨架能被一次性拉出来。转换用 LibreOffice 的 headless 模式最省事不需要装完整办公套件soffice --headless --convert-to docx \ 天健医院信息系统数据结构手册.doc \ --outdir ./converted这条命令里--headless表示不弹界面纯命令行跑--convert-to docx指定输出格式--outdir指定输出目录。转出来的 docx 和原文件同一目录名后缀变了。如果输出文件名带乱码说明原 doc 的编码本身有问题后面处理 CSV 时也要留意全角字符。转完后读标题层级from docx import Document doc Document(converted/天健医院信息系统数据结构手册.docx) for p in doc.paragraphs: style p.style.name if style.startswith(Heading) or style.startswith(标题): level style.replace(Heading, ).replace(标题, ).strip() if level : level 1 print(f{level}|{p.text.strip()})这段脚本会把所有标题按层级打出来比如1|门诊模块、2|门诊挂号表、3|字段说明。看到这份清单你就能立刻判断出文档覆盖了哪些模块、每张表大概哪几页。中文版 Word 文档里的样式名通常是“标题 1”而不是“Heading 1”所以判断条件里两个都查。这里要提醒一句有些手册是实施顾问手工整理的标题样式根本没套规范段落全是正文样式那这一招会失灵只能退回去人工翻目录页。2.2 提取表名和字段清单把 Word 表格批量导出 CSV模块边界清楚了下一步就是把正文里的表格导出来。绝大多数数据结构手册里一张业务表的字段定义就是一个 Word 表格表头是“字段名 / 类型 / 长度 / 必填 / 说明”下面每行一个字段。用 python-docx 遍历所有表格逐张落成 CSVfrom docx import Document import csv, re, os, unicodedata SRC converted/天健医院信息系统数据结构手册.docx OUT tables os.makedirs(OUT, exist_okTrue) def clean(s: str) - str: s s.replace(\n, ).replace(\r, ).strip() return unicodedata.normalize(NFKC, s) # 全角转半角 doc Document(SRC) for idx, t in enumerate(doc.tables): rows [] for row in t.rows: cells [clean(c.text) for c in row.cells] # python-docx 中合并单元格会在同一行重复出现这里去重 cells list(dict.fromkeys(cells)) if len(set(cells)) 1 and cells[0] : continue # 跳过整行空白 rows.append(cells) if not rows: continue first _.join(rows[0])[:50] first re.sub(r[\\/:*?|], _, first) path os.path.join(OUT, ft{idx:03d}_{first}.csv) with open(path, w, newline, encodingutf-8-sig) as f: csv.writer(f).writerows(rows) print(f{path}: {len(rows)} rows)逻辑上有几个关键点。dict.fromkeys(cells)是把列表转成去重后的新列表因为单元格合并后 python-docx 会在同一行的多个位置返回同一个文本不去重会让字段清单凭空多出几列。unicodedata.normalize(NFKC, ...)把全角字母、全角空格归一到半角老文档从 WPS 链转过来经常带这类隐藏字符后面做 JOIN 或比对外键时最容易翻车。编码用utf-8-sig而不是utf-8是为了让 Excel 双击打开不乱码。文件名用首行前 50 个字符拼出来既保留可读性又避免超长路径导致导出报错t{idx:03d}保留表格在文档里的原始顺序方便回查。导完后你会得到几十个 CSV命名大致长这样t012_字段名_类型_长度_必填_说明.csv。这时候用任何一款表格工具把所有 CSV 合并成一个总清单再加两列“来源表名”和“来源表格序号”后续查字段就快了。2.3 字段后面的“字典值”是最值钱的部分别只抄数据类型很多人在导字段时只关心类型和长度把“说明”那一列当成描述性文字一扫而过这是最亏的。HIS 表里大量字段是CHAR(1)或VARCHAR2(2)的状态位比如支付方式、费别、性别、挂号状态。手册里经常不单独给注释而是把值域写在字段说明里或者藏在文末的“代码表”章节。我的习惯是把这类枚举单独收进一个 YAML作为后续所有 SQL 的解释层# dict_ref.yaml pay_type: table: t_dic_pay_type desc: 支付方式 values: 1: 现金 2: 医保 3: 银行卡 9: 其他 sex: table: t_dic_sex desc: 性别 values: 1: 男 2: 女 9: 未知为什么用 YAML 而不是继续堆 Excel因为后面写 SQL 时我可以直接用这段 YAML 生成 CASE WHEN 语句也能在字段口径有争议时快速翻查。注意values里的 key 必须写成字符串HIS 很多状态值在库里是VARCHAR2存的数字可能带前导空格直接拿整数去匹配会查不到。另外凡是类型是CHAR(1)的字段几乎都可以认定是枚举优先级最高的反查对象就是它如果 YAML 里查不到可选值别猜跳到第 4 章的排查方法。3. 让手册变成能跑的 SQL按业务键建表写出第一张门诊费用对账单手册拆成 CSV 和字典之后就进入真正出活的阶段让文档回答业务问题。很多人的习惯是拿到手册先照着画 ER 图画完发现连不上现网库白费半天。我的做法完全反过来先不碰 ER 图从“业务键”入手。HIS 里所有模块都围着“一次就诊”转你只要能找到挂号、收费、医嘱这几张核心表之间共用的键报表已经能写出一半。3.1 先读 ER 和主键别对着文档画图直接找“业务键”国内 HIS 的物理表命名习惯多是拼音缩写门诊模块的表名常带MZ住院带ZY收费带SF医嘱带YZ。具体到你手里的天健手册表名前缀是什么、哪张表是核心以文档为准但找表的方法是一致的先找带“序号”“流水号”“编码”字样的字段这些就是键。比如挂号主表的挂号序号、收费明细表的收费明细序号、医嘱表的医嘱序号这就是连接事实表和维度表的锚点。-- 先确认手册里的表在现网库真实存在Oracle 视角 SELECT table_name, num_rows, last_analyzed FROM all_tables WHERE owner HIS_APP -- 改成你实际的 schema 名 AND table_name IN (MZ_GHXX, MZ_SFMX, ZY_YZ) ORDER BY table_name;all_tables是 Oracle 的元数据视图能查当前 schema 下所有表num_rows是上一次收集统计信息时的行数只能当量级参考不能当准确行数last_analyzed告诉你这个数字是什么时候的。如果手册里的表名在现网查不到要么是文档版本太老要么是表名被实施期改过这就是第 4 章要处理的问题。SQL Server 环境下把all_tables换成sys.tables就行MySQL 则查information_schema.tables。3.2 把手册字段落成建表 DDL类型、长度和注释怎么定你大概率不需要真的建一张一模一样的表但把手册字段落成 DDL 是检验“手册读懂没有”最直接的方式。这一步会把三类问题全暴露出来字段类型缺失、长度对不上、必填约束没写。下面这张门诊收费明细表是行业常见结构表名和字段名按你手册里的实际名称替换-- 落地示例门诊收费明细 CREATE TABLE t_mz_sfmx ( sfxh NUMBER(18) NOT NULL, -- 收费流水号 ghxh NUMBER(18) NOT NULL, -- 挂号序号关联挂号主表 xm_code VARCHAR2(32), -- 收费项目编码 item_name VARCHAR2(128), -- 收费项目名称冗余字段 je NUMBER(12,2) NOT NULL, -- 金额单位元 zfrq DATE, -- 支付日期 zffs VARCHAR2(2), -- 支付方式见 dict_ref his_remark VARCHAR2(512) -- 备注 );NOT NULL 的取舍要克制主键和业务必需字段加上其余不要随便加约束因为现网老数据经常有空值你约束加得越狠数据同步和迁移时翻车概率越大。类型选择上NUMBER(18)对应“流水号”这类可能超过 Java int 范围的大整数金额用NUMBER(12,2)精度到分上限 99 亿医院单日流水完全够用zffs故意用VARCHAR2(2)而不是CHAR(1)因为有些字典值后续可能扩成两位编码。item_name这种冗余字段在 HIS 手册里很常见建表时保留它报表可以少 JOIN 一张字典表但你要清楚它是冗余字段不是主数据。3.3 写第一笔跨表查询挂号、收费明细的关联口径新接手一个 HIS我建议第一张报表就做门诊收费对账因为它同时覆盖了挂号主表和收费明细表能把两张核心表的关系捋顺。核心口径是一张挂号单可以对多条收费明细一条收费明细必须属于一张挂号单所以按挂号序号关联是安全的SELECT d.dept_name AS 科室, COUNT(DISTINCT g.ghxh) AS 就诊人次, SUM(m.je) AS 实收金额 FROM t_mz_ghxx g JOIN t_mz_sfmx m ON m.ghxh g.ghxh LEFT JOIN t_dim_dept d ON d.dept_code g.dept_code WHERE g.gzrq DATE 2024-01-01 AND g.gzrq DATE 2025-01-01 GROUP BY d.dept_name ORDER BY 实收金额 DESC;COUNT(DISTINCT g.ghxh)是为了防止一张挂号单关联了多条明细时人次被重复计数这是对账报表最常见的低级错误。LEFT JOIN保留没有科室信息的挂号记录避免 LEFT 侧数据被 JOIN 过滤掉。日期过滤用左闭右开 和 而不是BETWEEN因为BETWEEN会把 2024-12-31 00:00:00 之前一整天都包含进去。如果手册里gzrq字段是字符型而不是 DATE就需要包一层TO_DATE这也是我前面强调先看手册字段类型的原因。4. 结合现网对不上的 5 个坑现象、原因和处理办法手册是纸面的现网是活的两者对不上才是常态。下面 5 条按踩坑频率排每条都是“现象 → 原因 → 解决”的结构直接对照自己遇到的情况即可对号入座。4.1 手册里的字段现网库里根本没有现象按手册写 SQLOracle 直接报ORA-00904: invalid identifier字段名拼写也没错就是查不到。原因文档比库老新版本加了字段没回写文档或者实施时按客户需求裁剪掉了该字段。解决 别急着改 SQL 硬猜先用元数据视图核对现网全量列-- 查出现网表实际拥有的列再和手册做差集 SELECT column_name, data_type, data_length FROM all_tab_columns WHERE owner HIS_APP AND table_name T_MZ_SFMX ORDER BY column_id;把查出来的列粘贴到 Excel和手册字段清单做一次 VLOOKUP缺失和多余的字段立刻现形。如果只是个别字段缺失直接去掉如果缺失了一整类字段说明手册版本和现网差了一个大版本后面的 SQL 都要以现网为准。4.2 字典表里查不到的状态值现象按字典 YAML 写了 CASE WHEN跑出来发现大量 NULL 落到 ELSE 分支或者出现一个文档里根本没写的值。原因字典代码表只覆盖了当前接口字典早期实施导入的历史数据用的是旧字典有些字段干脆是自由文本根本不对应任何代码。解决不要猜先看真实分布-- 查支付方式字段的值分布 SELECT zffs, COUNT(*) AS cnt FROM t_mz_sfmx GROUP BY zffs ORDER BY cnt DESC;值分布查出来后对照 YAML 看哪些值没被覆盖再决定补字典还是保留为“未知”。这一步必须做否则后续所有统计口径都会带着一个说不清的“其他”。4.3 中文乱码不是编码问题是客户端 NLS 没设对现象PL/SQL Developer 里中文显示成“???”导出 CSV 用 Excel 打开也是乱码但数据库本身用命令行查是好的。原因客户端字符集和服务端字符集不一致。常见组合是服务端AL32UTF8、客户端ZHS16GBK或者反过来。解决连库前先设置环境变量export NLS_LANGAMERICAN_AMERICA.ZHS16GBK sqlplus his/his//10.0.0.11:1521/hisdb report.sqlNLS_LANG的格式是“语言_地区.字符集”关键在字符集部分必须和服务端一致。不确定服务端字符集时先执行SELECT USERENV(language) FROM dual;查看。注意这只是客户端显示问题数据本身没有坏乱码导出的 CSV 不要直接进报表重导一遍更省事。4.4 “日期”和“时间”分开存跨天退费最容易翻车现象做日结对账每天凌晨总有几笔账对不上仔细一看是前一天的日志被算进今天。原因HIS 里常见“业务日期”和“业务时间”分开两个字段手册字段名叫zfrq的其实只存日期具体时刻在另一个时间字段里。还有人直接拿日期字段做BETWEEN把当天 00:00 到 23:59:59 之外的数据都算错边界。解决凡是跨天统计先确认手册里有没有独立的时间字段有就日期字段和时间字段拼成完整时间戳再过滤。如果手册里只能找到单一日期字段那说明这个字段在设计上就只精确到天用它做小时级统计本身就是错的口径。4.5 同一个字段名两种含义现象sfxm在费用明细表里是收费项目编码换到另一张表里变成了收费项目名称。原因HIS 是多模块多年叠加的系统不同模块由不同实施顾问维护一套文档里口径没统一。解决写 SQL 时所有字段必须带表别名不裸写字段名遇到同名不同义的情况记到字典 YAML 的备注里作为团队口径基线。这条处理不好后面写任何跨模块 JOIN 都会带着隐患而且很难排查。5. 手册之外的三条补全路径和一个最值得先做的验证动作手册只覆盖产品标准结构而现网库通常比手册多出实施期扩展表和归档表。如果你最终要做迁移或上报我一般按这个顺序补全先问厂商 DBA 要一份现网的数据字典导出这通常比手册新鲜拿到手先做一次全量字段对比再直接从库的元数据视图生成全量表列清单最后抽核心表的数据看样例值是否和手册描述一致。样例数据是最诚实的文档可能过期数据不会骗你。补完之后建议做一个“手册 vs 元数据 vs 真实数据”的三栏验证动作抽三张核心表逐字段对比判定标准是手册有、元数据有、数据有才算这条字段可用。下面是一张可复制的对比表手册字段元数据实际类型样例数据判定ZFFSVARCHAR2(2)“1”一致可用ZFRQDATE2024-01-01一致可用BZ元数据不存在无手册过期废弃这套验证做完手册里的字段哪些可信、哪些要丢一清二楚。我踩过最深的一个坑就是拿到手册当宝直接据此写接口结果和现网对不上反复调试了两周才发现文档版本比库旧了三个迭代。现在我把“先信元数据再信数据本身最后才信文档”当铁律省掉了大量返工。希望这次的结构化读法能帮你把那份 .doc 变成第一版可用的取数口径希望帮到你。本文还有配套的精品资源点击获取