作为一个后端开发者, 需要处理的问题会非常多非常杂,不断的接触各方面的知识,总结心得才能有所提高。
最近我们将甲方的信披系统改造后并入了我们的系统,开发基本完成,接下来数据迁移就是一个大问题了。因为之前其它开发商系统的数据库设计极烂,所以这次数据迁移稍微显得麻烦,而数据迁移最大的要求就是保证数据的正确性。
在此把这次迁移的方式记录下来,也希望以后有所提升之后能有更好的方案。
总体的方案上 是先把原库的表导入到我们库,然后写存储过程,对重构的字段做对应,然后导入到我们的新表之中,最后删除老的表。
原库的表导入我们库 我们在这里用到的是oracle的 exp imp命令
注意exp imp命令直接在dos下运行就行 不需要进入sqlplus
下面是exp命令和imp命令
Exp disinfo2/disinfo2@disinfo2 log=disinfo_emp.log file=C:\Users\hundsun\Desktop\cbs信披改造迁移数据\dmp\disinfo.dmp
tables =(TBL_INFO_DISCLOSUER_APPLY,TBL_DISCLOSUER_APPLY_FILE,TBL_FILE_PATH,TBL_FILE_INFO,TBL_INFO_DISCLOSUER_HANDLE_LOG,TBL_DISCLOSUER_LEAVENET_LOG,TBL_DIRECTIONAL_INVESTORS)
imp cfae_cbs/hundsun@1538CBS log=disinfo_imp.log file=C:\Users\hundsun\Desktop\cbs信披改造迁移数据\dmp\disinfo.dmp
tables =(TBL_INFO_DISCLOSUER_APPLY,TBL_DISCLOSUER_APPLY_FILE,TBL_FILE_PATH,TBL_FILE_INFO,TBL_INFO_DISCLOSUER_HANDLE_LOG,TBL_DISCLOSUER_LEAVENET_LOG,TBL_DIRECTIONAL_INVESTORS)
意思应该都明确易懂, 用户名/密码 连接 日志输出地址 需要导入或导出的表。 文件做成bat或sh直接运行就可以了 非常的方便快捷。
这样所有我需要的表都转移到我们自己的库里面。
下一步就是写存储过程,重构对应字段了。
下面是主表的迁移存储过程 关键的地方我添加了注释解释一下
create or replace procedure sp_disinfo_apply_insert
as
--原信披库申请表中存储了所有历史数据 先改造成之前版本进入历史表 所以进入申请表的数据只为版本号最高的数据
cursor cur_infordis_apply is --此处是游标 批量导入数据基本都需要用到 相当于把数据做成一个list 方便之后foreach的循环导入
select t.* from
( select apply_id,
title,
status,
is_directional,
biz_resource,
publish_method,
is_cron_disclosure,
announcement_type_name,
announcement_type_id,
DISCLOSUER_INSTITUTION,
disclosuer_institution_name,
rp_disclosuer_institution,
rp_disclosuer_institution_name,
publisher_mem_code,
bond_id,
bond_code,
bond_short_name,
bond_full_name,
bond_type,
contact_phone,
contact_user,
area_code,
tel_number,
contact_email,
is_check,
remarks,
create_user_id,
update_user_id,
update_user_name,
oper_user_id,
registrstion_notice_paper_no,
create_time,
update_time,
cron_publish_time,
disclosure_time,
tranfer_times,
--此处这个row_number()over partition by 的用法 用于找到之前版本最高的数据 因为原库中没有设计历史表 所有历史数据全在主表里面靠一个版本字段做区分
--这样做非常不好 数据很乱 所以我们做了改动 这里我们需要拿到最高版本的数据
row_number() over(partition by apply_id order by tranfer_times desc) rn from tbl_info_disclosuer_apply)t
where rn=1;
begin
for apply in cur_infordis_apply
loop
--if apply.title='重复测试-001' then
DBMS_OUTPUT.ENABLE(buffer_size => null);
-- 发布类型映射,例:PDF方式->1
--申明变量
declare
--publish_method
v_old_method varchar2(200);
v_new_method number;
--申请类型
v_old_type varchar2(200);
v_new_type varchar2(2);
--所有时间字段
v_old_create_date date;
v_old_update_date date;
v_old_cron_date date;
v_old_disclosure_date date;
v_new_create_date number(10);
v_new_create_time number(10);
v_new_update_date number(10);
v_new_update_time number(10);
v_new_cron_date number(10);
v_new_cron_time number(10);
v_new_disclosure_date number(10);
v_new_disclosure_time number(10);
--区号
v_old_area varchar2(160);
v_new_area varchar2(6);
--版本号
v_old_trans number(10);
v_new_trans varchar(32);
begin
--publish_method转换
v_old_method := apply.publish_method;
if v_old_method='PDF方式' then
v_new_method := 1;
ELSE v_new_method := 2;
end if;
--所有时间字段
v_old_create_date := apply.create_time;
v_old_update_date := apply.update_time;
v_old_cron_date := apply.cron_publish_time;
v_old_disclosure_date := apply.disclosure_time;
v_new_create_date:= TO_NUMBER(TO_CHAR(v_old_create_date, 'YYYYMMDD')) ;
v_new_create_time:= TO_NUMBER(TO_CHAR(v_old_create_date, 'hh24miss')) ;
v_new_update_date:= TO_NUMBER(TO_CHAR(v_old_update_date, 'YYYYMMDD')) ;
v_new_update_time:= TO_NUMBER(TO_CHAR(v_old_update_date, 'hh24miss')) ;
v_new_cron_date:= TO_NUMBER(TO_CHAR(v_old_cron_date, 'YYYYMMDD')) ;
v_new_cron_time:= TO_NUMBER(TO_CHAR(v_old_cron_date, 'hh24miss')) ;
v_new_disclosure_date:= TO_NUMBER(TO_CHAR(v_old_disclosure_date, 'YYYYMMDD')) ;
v_new_disclosure_time:= TO_NUMBER(TO_CHAR(v_old_disclosure_date, 'hh24miss')) ;
--申请类型转换
v_old_type := apply.announcement_type_name;
CASE v_old_type
WHEN '挂牌文件' THEN v_new_type:='1';
WHEN '其他与挂牌相关的事项' THEN v_new_type:='2';
WHEN '挂牌结果公告' THEN v_new_type:='3';
WHEN '财务报告及摘要' THEN v_new_type:='4';
WHEN '信用评级公告' THEN v_new_type:='5';
WHEN '重大事项公告' THEN v_new_type:='6';
WHEN '持有人会议公告' THEN v_new_type:='7';
WHEN '本息资金划转公告' THEN v_new_type:='8';
WHEN '未按期足额偿付本息公告' THEN v_new_type:='9';
WHEN '其它' THEN v_new_type:='10';
else v_new_type:=null;
END case ;
--区号截取
v_old_area:=apply.area_code;
if lengthb(v_old_area)>6 then
v_new_area:=SUBSTRB(v_old_area,0,6);
elsif v_old_area is null then
v_new_area:='';
else
v_new_area:=v_old_area;
end if;
dbms_output.put_line(apply.title);
dbms_output.put_line(apply.apply_id);
dbms_output.put_line(apply.tranfer_times);
--插入数据
insert into infodis_apply
(apply_id,
title,
disclosure_status,
is_directional,
biz_resource,
is_cron_disclosure,
disclosure_method,
disclosure_type,
disclosure_agency,
disclosure_agency_name,
disclosure_client,
disclosure_client_name,
publisher_mem_code,
bond_id,
bond_code,
bond_short_name,
bond_full_name,
bond_type,
contact_phone,
contact_name,
area_code,
tel_number,
contact_email,
is_check,
remark,
create_user_id,
update_user_id,
update_user_name,
oper_user_id,
reg_notice_number,
create_date,
create_time,
update_date,
update_time,
cron_publish_date,
cron_publish_time,
disclosure_date,
disclosure_time)
values( apply.apply_id,
apply.title,
apply.status,
apply.is_directional,
apply.biz_resource,
apply.is_cron_disclosure,
v_new_method,
v_new_type,
apply.DISCLOSUER_INSTITUTION,
apply.disclosuer_institution_name,
apply.rp_disclosuer_institution,
apply.rp_disclosuer_institution_name,
apply.publisher_mem_code,
apply.bond_id,
apply.bond_code,
apply.bond_short_name,
apply.bond_full_name,
apply.bond_type,
apply.contact_phone,
apply.contact_user,
v_new_area,
apply.tel_number,
apply.contact_email,
apply.is_check,
apply.remarks,
apply.create_user_id,
apply.update_user_id,
apply.update_user_name,
apply.oper_user_id,
apply.registrstion_notice_paper_no,
v_new_create_date,
v_new_create_time,
v_new_update_date,
v_new_update_time,
v_new_cron_date,
v_new_cron_time,
v_new_disclosure_date,
v_new_disclosure_time);
commit;
end;
-- end if;
END loop;
end sp_disinfo_apply_insert;
之后的所有表也都按照此存储过程的模式写好存储过程导入。
这里还有需要优化的地方 不同的字段对应方法可以写成function 可能会出现复用的情况。 可以写一个主过程来调用所有的存储过程一次性导入。
总之可能自己接触的东西有限还有很多复杂得多的数据迁移需要实现,希望在之后不断学习,总结更好的方法。