最近做了一个项目,是一个关于省集中的项目。所谓省集中就是将各个地市的业务统一迁移到省中心,一个项目由多个点变成了一个点,数据库迁移势在必行了。之前这个系统用的数据库是sybase,省集中后,局方要求使用oralcle的数据库,于是面前一个棘手的工作就出现了——sybase数据库迁移到oracle。
一、oracle脚本的生成
我们公司开发系统有一个很好的习惯,每一个系统都有几近完美的脚本保存。包括Powerdesigner的PDM文件、安装脚本.sql、更新脚本YYYYDD.sql。其中Powerdesigner是一个强大的工具,支持sybase、oracle、sql
server,能够进行数据库建模,生成sql脚本,同时,也能逆向将sql脚本生成数据库模型。这个系统完好的保存有PDM文件,所以oracle建库脚本的生成就亦如反掌了,直接设置数据库类型为oracle,然后就可以生成需要的oracle建库脚本了。
有一点特别郁闷的是oracle的时间函数和sybase的时间函数不同,所以必须特别注意的是在sybase中,表字段默认值是是getdate(),在oracle中就得把它改成sysdate了。
另外,oracle的自增字段和sybase实现方式也是不同的,sybase通过identity来实现,oracle则没有。要实现oracle中字段的自增,有两种方式,一是放弃自增字段,在系统代码中的insert处将字段的max+1来作为字段的值。则中方式的弊端是代码修改量很大,而且容易漏掉。另一种办法则是应用oracle的sequence+trigger。在Oracle数据库中,sequence等同于序列号,每次取的时候sequence会自动增加。建立一个名字为S_PA_KEY_TIME,那么可以通过建立before
insert触发器,将sequence.NEXTVAL赋值给需要自增的字段即可。这样就轻松搞定sybase的identity字段了。
如:select S_PA_KEY_TIME.NEXTVAL INTO :new.CN_ID from
dual;
还有一点必须引起注意的是,sybase的字符连接符号是“+”而oracle的连接符号则是“||”。
建库脚本容易生成,面对存储过程和触发器,powerdesigner也无能为力。所以存储过程和触发器需要手动改写,这个工作量可不小哦。
二、oracle脚本的生成
终于进入正题,数据库迁移。数据库迁移可以分3个阶段,数据处理、数据导出、数据导入。
1、数据处理
数据处理主要处理主键冲突,原来各个地市的主键大多由identity字段产生的,那么如果不加处理的话,即时能够顺利导入第一个地市的数据,导第二个地市的数据肯定会有冲突。
解决办法是在地市的数据库建视图,有主键冲突的表都要建视图来代替。在创建视图时的select语句里,使之间的数据由PK变成‘区号’+PK,如:
CREATE VIEW TABLENAME_VIEW AS SELECT
'020'+convert(varchar(15),PK_NAME) as
PKNAME,ZIDUAN1,ZIDUAN2,ZIDUAN3 FROM TABLENAME。
当然,由于主键都被加长了2-4位,所以需要修改建库脚本,加长主键4-5位。
2、数据导出
sybase导出数据最好的办法是bcp。通过写bcp语句,在命令行里执行。如:bcp
dbname..viename out
E:xiancp数据\tablename.txt
-Sservername -Uusername -Ppwd-c -t
@_@ -r
$_$。值得注意的是,这条语句中的@_@是字段分割符,$_$是数据记录分割符。一般而已,用回车作为记录分割符比比较好接受,但是我在导库的过程中发现一个问题:有些字段数据是有回车符存在的,尤其是text字段,那么通过sqlldr导入oracle数据库的时候,就会出错,导不进去。
3、数据导入
oracle数据导库的方式是sqlldr。首先需要生成控制文件,如:
OPTIONS(BINDSIZE=8388608,READSIZE=8388608,ERRORS=-1,ROWS=50000)
LOAD DATA
INFILE 'E: empcp资阳\数据库迁移数据\FJ_AREA_INFO.txt' "STR
X'245f24'"
append INTO TABLE FJ_AREA_INFO
FIELDS TERMINATED BY X'405f40' TRAILING NULLCOLS
(
CN_AREACODE CHAR(4),
CN_AREANAME CHAR(20),
CN_AREA_ID CHAR(4)
)
其中FJ_AREA_INFO.txt是从sybase数据库中bcp出来的数据,"STR
X'245f24'"
中的245f24表明数据行分割符“$_$”,这个编码可以通过在oracle客户端执行“select utl_raw.cast_to_raw('$_$') from dual”来得到。
接着就是导入脚本了,也是在命令行里执行即可,如:“sqlldr
control=E: empcp资阳\数据库迁移控制文件\PA_ACCOUNT_sqlldr.ctl
log=PA_ACCOUNT_sqlldr.log”。
4、总结
我上面所描述的只是导库的一个过程,在具体的实施中会遇到相当多的问题的。要证明数据库迁移完成,至少得迁移4个以上的地市来做测试,然后对系统做一个全面细致的测试,通过反复的修改,才会日趋完善。
参考资料:
Oracle中sequence的使用方法
oracle sqlldr控制文件模板