某专科医院老数据库迁移实战记录
一次与 Oracle 10g/11g 和 SQL Server 2008/2012 的"考古"式交手
一、背景
最近接手了一个有点"考古"意味的项目------某专科医院的老数据库迁移。环境是这样的:
- Oracle:3个库,版本分别是 10g 和 11g
- SQL Server:2个库,版本是 2008 和 2012
数据量其实不大,真正的挑战在于:年代久远,密码早就丢了。HIS 厂商换了好几拨,文档基本等于没有。好在技术层面,这事有门。
二、第一步:无密码登录------操作系统认证救场
2.1 Oracle:sqlplus / as sysdba
一开始最担心的是 Oracle 密码问题。结果试了一下:
powershell
PS C:\Users\Administrator> sqlplus / as sysdba
SQL*Plus: Release 11.2.0.4.0 Production on 星期五 7月 24 10:15:16 2026
Copyright (c) 1982, 2013, Oracle. All rights reserved.
连接到: Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
直接进去了。
原理 :Oracle 支持操作系统认证(OS Authentication) 。安装 Oracle 时,系统会创建 OSDBA 和 OSOPER 组,只要当前 Windows 用户属于这些组,执行 sqlplus / as sysdba 就可以绕过密码直接登录。这本质上是把数据库的认证信任交给了操作系统。
控制这个行为的参数在 sqlnet.ora 文件中:
SQLNET.AUTHENTICATION_SERVICES = (NTS)------ 允许 Windows 操作系统认证SQLNET.AUTHENTICATION_SERVICES = (NONE)------ 关闭 OS 认证,必须用密码
既然能登录,说明这个参数是开放的。登录后可以用 ALTER USER 重置任何用户的密码:
sql
-- 查看所有用户
SELECT username FROM dba_users;
-- 重置密码
ALTER USER hisuser IDENTIFIED BY newpassword;
几个 Oracle 库都如法炮制,全部连上了。
2.2 SQL Server:Windows 身份验证
SQL Server 的情况类似。SQL Server 的 Windows 身份验证模式 使用 Windows 操作系统的安全凭据来验证用户连接,SQL Server 本身不存储或管理密码。
操作很简单:
- 用 Administrator 账户登录 Windows
- 打开 SQL Server Management Studio(SSMS)
- 选择 Windows 身份验证 连接
- 连上之后,可以在"安全性 → 登录名"中重置
sa密码,并把身份验证模式改为"SQL Server 和 Windows 身份验证模式"
连接字符串(供后续工具使用):
Server=服务器IP;Database=库名;Trusted_Connection=True;
两个 SQL Server 库也顺利拿下。
三、第二步:数据迁移------Kettle 上场
3.1 为什么选 Kettle
跨库迁移的方案不少:可以写 Python/Pandas 脚本,也可以用数据库自带的工具(如 Oracle SQL*Loader)。但面对 5 个库、几十上百张表,Kettle(Pentaho Data Integration) 是最省力的选择------它提供可视化的 ETL 操作,尤其是批量迁移功能。
3.2 环境准备
- 下载 Kettle(开源版即可),解压后运行
spoon.bat - 把数据库驱动放到
data-integration/lib目录:- Oracle:
ojdbc8-19.3.0.0.jar(或对应版本的驱动) - SQL Server:
jtds-1.3.1.jar或微软官方驱动
- Oracle:
3.3 单表迁移
新建一个转换(右键"转换" → 新建):
- 拖入 表输入(源)→ 配置 Oracle 连接 → 点击"获取 SQL 查询语句"选表
- 拖入 表输出(目标)→ 配置 SQL Server 连接 → 指定目标表
- 用 Shift+连线 连接两个步骤
- 点击运行
3.4 批量迁移:复制多表向导
手动一张张表做太慢。Kettle 提供了 "复制多表向导" 功能:
操作路径:工具 → 向导 → 复制多表向导
然后按向导提示:
- 选择源数据库连接(Oracle)
- 选择目标数据库连接(SQL Server)
- 勾选需要迁移的表
- Kettle 自动生成迁移作业
注意:复制多表向导适合"目标表不存在、需自动建表并全量复制"的场景。如果目标表已存在且需要复杂的字段映射或值转换,则需要手动组合"表输入→表输出"链路并使用"值映射""字段选择"等组件。
3.5 数据类型转换的坑(重点!)
跨库迁移最大的坑不在连接,在数据类型。
| Oracle 类型 | SQL Server 类型 | 注意事项 |
|---|---|---|
| NUMBER | numeric(38,0) / decimal | 默认的 Oracle NUMBER 和 SQL Server numeric(38,0) 可能不匹配,需指定精度 |
| VARCHAR2 | varchar / nvarchar | 注意字符集,SQL Server 的 nvarchar 最多 4000 字符,对应 Oracle 的 nvarchar2 只有 2000 |
| DATE | datetime / datetime2 | 精度有差异,Kettle 对日期类型的隐式转换缺乏控制,需统一使用 Timestamp 元数据 |
| CLOB | nvarchar(max) | 大字段需特殊处理 |
| 无布尔型 | bit | Oracle 没有布尔型,需映射为 number(1) 或 varchar |
空字符串和 NULL 也是大坑:Kettle 迁移时,源库的空字符串在插入目标库时可能被转为 NULL,触发非空校验失败。
实践建议:
- 迁移前先在目标库建好表结构,手动确认字段类型映射
- 先用一两张测试表跑通,验证类型转换没问题再批量执行
- 目标表在加载数据前禁用所有主键、外键约束和索引,加载完成后再重建
四、第三步:数据结构梳理 + 查询入口
数据迁移完了,但问题才到一半------这些表是干什么的?字段是什么意思?
HIS 厂商不配合是常态。数据字典一旦透明,他们的"独家解释权"就没了。十年间系统经过无数次升级、补丁,文档要么过期要么不存在。
4.1 破局思路:用工具生成"60分字典"
不需要 100% 准确的数据字典,只需要一份能用的"底稿":
- 用 SQL 扫描元数据:从系统表中读取所有表名、字段名、字段类型
- 抽样分析数据 :看字段里的实际值分布(如
STATUS字段里有哪些值) - 结合业务上下文推断 :比如
PATIENT_NAME、DIAGNOSIS_CODE这种命名,含义基本能猜
4.2 技术实现方案
方案一:Streamlit + Python(快速原型)
Streamlit 适合快速搭建数据查询工具:
python
import streamlit as st
import cx_Oracle
import pymssql
import pandas as pd
# 配置多数据源连接
oracle_conn = st.connection("oracle", type=SQLConnection)
sqlserver_conn = st.connection("sqlserver", type=SQLConnection)
# 查询并展示
df = oracle_conn.query("SELECT table_name, column_name FROM all_tab_columns WHERE owner='HIS'")
st.dataframe(df)
方案二:Java + Vue(正式系统)
如果要做成生产级工具:
- 后端:Spring Boot + MyBatis,支持多数据源动态切换
- 前端:Vue + Element UI
- 功能:数据源管理、表结构浏览、SQL 查询面板、数据字典导出
4.3 倒逼厂商配合的策略
拿着"60分字典"去和 HIS 厂商谈,效果完全不同:
- 用具体问题代替笼统需求 :不说"我们要患者数据",而是问"
ZY_PATIENT表的STATUS字段值为 2 时对应什么业务逻辑?" - 让对方知道你已掌握一定信息:对话性质从"单方面需求提报"变成"双方对等的技术讨论"
- 利用合同条款:检查原始合同中是否有数据字典、接口文档的交付条款
五、踩坑总结
坑1:Oracle 监听配置
老 Oracle 的 listener.ora 和 tnsnames.ora 配置可能有问题。如果远程连接不上,检查监听状态:
bash
lsnrctl status
lsnrctl reload
坑2:SQL Server 2008 的兼容性
SQL Server 2008 比较老,某些新版驱动可能不兼容。建议使用 jtds 驱动,或者 SQL Server 2008 对应的旧版微软驱动。
坑3:字符集
Oracle 和 SQL Server 的字符集可能不一致。迁移后出现乱码,需要在 Kettle 的数据库连接配置中指定字符集参数。
坑4:Kettle 版本
Kettle 高版本可能对老数据库驱动支持不好。如果遇到连接问题,可以尝试低版本(如 5.2)。
六、时间线参考
| 阶段 | 工作内容 | 预估时间 |
|---|---|---|
| 第 1 周 | 用 OS 认证连上所有库,确认数据可达 | 2-3 天 |
| 第 2 周 | Kettle 环境搭建 + 单表迁移验证 | 3-5 天 |
| 第 3 周 | 批量迁移所有表 | 2-3 天 |
| 第 4 周 | SQL 扫描生成初步数据字典 | 3-5 天 |
| 第 5 周+ | 拿着字典与 HIS 厂商谈判/核对 | 持续 |
| 第 6 周+ | 查询工具开发 | 2-4 周 |
七、总结
老数据库迁移这件事,技术层面其实不难:
- Oracle 无密码 :
sqlplus / as sysdba搞定 - SQL Server 无密码:Windows 身份验证搞定
- 数据迁移:Kettle 的复制多表向导一键搞定
真正的难点在业务层面------弄清楚这些表是干什么的。但借助 SQL 元数据扫描 + 数据内容分析,至少可以生成一份"60 分字典",把谈判主动权拿回来。
技术不是瓶颈,信息差才是。