1. 程式人生 > >一次較為完整的oracle資料庫資料遷移過程

一次較為完整的oracle資料庫資料遷移過程

作為一個後端開發者, 需要處理的問題會非常多非常雜,不斷的接觸各方面的知識,總結心得才能有所提高。

最近我們將甲方的信披系統改造後併入了我們的系統,開發基本完成,接下來資料遷移就是一個大問題了。因為之前其它開發商系統的資料庫設計極爛,所以這次資料遷移稍微顯得麻煩,而資料遷移最大的要求就是保證資料的正確性。

在此把這次遷移的方式記錄下來,也希望以後有所提升之後能有更好的方案。

總體的方案上  是先把原庫的表匯入到我們庫,然後寫儲存過程,對重構的欄位做對應,然後匯入到我們的新表之中,最後刪除老的表。

原庫的表匯入我們庫  我們在這裡用到的是oracle的 exp imp命令

注意exp imp命令直接在dos下執行就行  不需要進入sqlplus

下面是exp命令和imp命令

Exp disinfo2/[email protected] 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/[email protected] 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 可能會出現複用的情況。 可以寫一個主過程來呼叫所有的儲存過程一次性匯入。

總之可能自己接觸的東西有限還有很多複雜得多的資料遷移需要實現,希望在之後不斷學習,總結更好的方法。