Remember the entire process of data migration

background

The second phase of development of a large-scale project has been completed and launched online. A large number of data sources need to be initialized, and the data sources provided by the third-party BPM system are not completely in the format and table structure we need, so it is necessary Do a data migration. The database used is SqlServer.This migration idea can be used for any migration where the table structure is inconsistent between databases.

Prerequisites and requirements

  1. Clarify the scope of local data migration
  2. Maintain data consistency during data migration
  3. The business table adds a migration data identifier, and the business table migration data field ISMOVE='Y'

logic

The data source is provided by a third party, which is cleaned, filtered, and written into its own business library and business tables.

 accomplish

1. Create four migration setting tables QY_Tables, Qy_Maping, Qy_FieldDic, and Qy_ErrorMsg

--迁移表设置
CREATE TABLE QY_Tables
(
  ID        INT NOT NULL -- 主键
, Type      VARCHAR (255) NULL  -- 类型【试图、表,一般皆为表】
, Business  VARCHAR (255) NULL -- 业务模块
, TableName VARCHAR (255) NULL -- 表名中文
, TableCode VARCHAR (255) NULL -- 第三方提供的数据表表名【用于存储清洗后的数据】
, BPMTable  VARCHAR (255) NULL -- 从第三方数据库同步过来之后的数据源表名[用于第一次同步第三方数据源到自己的库中]
, BPMVIEW   VARCHAR (255) NULL -- 将第三方数据源表字段更换为中文所用试图,便于查看
, CostTable VARCHAR (255) NULL -- 自己的业务表
, Mark      VARCHAR (255) NULL -- 备注
, Doing     VARCHAR (255) NULL -- 是否同步
)

--迁移字段设置表
--有可能QyTableFieldName字段在QyTableFieldCodeBPM中没有,那么设置QyDefaultValue默认值即可
--这个表,是设置我们所需要的业务字段,用于清洗数据使用
CREATE TABLE Qy_Maping
(
  Id                   INT IDENTITY NOT NULL --主键
, QyTableName          NVARCHAR (50) NULL -- 迁移表名
, QyTableFieldName     NVARCHAR (50) NULL -- 迁移字段中文名称
, QyTableFieldCode     NVARCHAR (50) NULL -- 迁移字段英文
, QyTableFieldCodeBPM  NVARCHAR (50) NULL -- 第三方迁移表字段英文
, QyRemark             NVARCHAR (200) NULL --字段备注
, QyPOPTYPE            NVARCHAR (200) NULL -- 下拉框字典,对应 Qy_FieldDic.POPTYPE
, QyPOPTYPEValueSouce  NVARCHAR (50) NULL --下拉框字段具体值,对应 Qy_FieldDic.TITLEVALUE
, QyDefaultValue       NVARCHAR (50) NULL -- 默认值
, QyRelaceNullValue    NVARCHAR (50) NULL -- 如果第三方字段为空,默认替代值
, QyTableFieldType     NVARCHAR (50) NULL -- 字段类型【'int'、'nvarchar'等】
, QyTableFieldDataType NVARCHAR (50) NULL -- 字段类型,一般如果是枚举值时不为空,其他为空
, QyIsNull             NVARCHAR (50) NULL -- 是否为null
, QyIsNullBPM          NVARCHAR (50) NULL -- 第三方数据源是否为null
, QyDeaultBPMValue     NVARCHAR (50) NULL -- 第三方数据源默认值
)
GO

-- 字段字典枚举值
CREATE TABLE dbo.Qy_FieldDic
(
  ID                INT IDENTITY NOT NULL -- 主键
, POPUPLSTELEMENTID INT NULL -- 对应自己业务系统中已有的字段枚举值表ID,没有填0
, TITLECN           NVARCHAR (50) NULL -- 中文含义
, TITLEVALUE        NVARCHAR (50) NULL -- 编码
, POPTYPE           NVARCHAR (50) NULL -- 枚举类型
, BPMCODE           NVARCHAR (50) NULL -- 第三方数据源值编码
, BPMCLOUMN         NVARCHAR (50) NULL -- 第三方数据源值对应的数据源列
, BPMTABLE          NVARCHAR (50) NULL -- 所在迁移表表名
, CONSTRAINT PK_Qy_FieldDic PRIMARY KEY (ID)
)
GO

--错误日志表,主要用于迁移失败的日志记录,可根据自己的业务自由扩展字段
CREATE TABLE dbo.Qy_ErrorMsg
(
  Id                INT IDENTITY NOT NULL -- 主键
, FromTableName     NVARCHAR (50) NULL -- 来源表
, ToTableName       NVARCHAR (50) NULL -- 业务目标表
, ErrorMsg          NVARCHAR (max) NULL -- 错误信息
, ErrorSqlCmd NVARCHAR (max) NULL -- 执行的sql语句
, CONSTRAINT PK_Qy_ErrorMsg PRIMARY KEY (Id)
)
GO

2.BPM only provides an attempt to provide data sources, and the data sources are still in their system. Due to the large amount of migration, all the data sources they provide are first migrated to the database through database bridging. The intermediate library [intermediate table] of your own database; try to batch generate SQL statements that synchronize data to your own intermediate library through VIEW_SQL_Proc_BPM_IN.You can also further divide the queried SQL into stored procedures Proc_IN_BPM, so It is more convenient to perform synchronization.

create VIEW VIEW_SQL_Proc_BPM_IN AS
SELECT 
'IF OBJECT_ID (''dbo.'+BPMTable+''') IS NOT NULL DROP TABLE dbo.'+BPMTable+';' AS SQL
FROM VIEW_QY_Tables
WHERE BPMTable <> ''
UNION ALL

SELECT 
'SELECT * INTO '+BPMTable+' from openquery(BPM, ''select * from sgbpm_prd.'+BPMTable + ''') TEMP;' AS SQL
FROM VIEW_QY_Tables
WHERE BPMTable <> ''
GO

--中间如果有报错,根据实际情况更改下sql的查询方式即可
CREATE proc [dbo].[Proc_IN_BPM]
as
begin
--DROP TABLE bpm_fkjl_heyue_view;
DROP TABLE 	bpm_QY_BudgetMapKM_view	;
DROP TABLE 	bpm_QY_BudgetMapZT_view	;
DROP TABLE 	bpm_QY_BudgetZT_view	;
DROP TABLE 	bpm_QY_Company_view	;
DROP TABLE 	bpm_QY_ContractAppendices_view	;
DROP TABLE 	bpm_QY_ContractBasic_view	;
DROP TABLE 	bpm_QY_ContractCost_view	;
DROP TABLE 	bpm_QY_ContractMatter_view	;
DROP TABLE 	bpm_QY_ContractParty_view	;
DROP TABLE 	bpm_QY_ContractPayment_view	;
DROP TABLE 	bpm_QY_ContractType_view	;
DROP TABLE 	bpm_QY_Department_view	;
DROP TABLE 	bpm_QY_Legal_view	;
DROP TABLE 	bpm_QY_LX_Basic_view	;
DROP TABLE 	bpm_QY_LX_File_view	;
DROP TABLE 	bpm_QY_LX_Release_view	;
DROP TABLE 	bpm_QY_LX_Subject_view	;
DROP TABLE 	bpm_QY_Person_view	;
DROP TABLE 	bpm_QY_Project_view	;
DROP TABLE 	bpm_QY_Provision_gys_view	;
DROP TABLE 	bpm_QY_Provision_jtmx_view	;
DROP TABLE 	bpm_QY_Provision_view	;
DROP TABLE 	bpm_QY_Subject_view	;
DROP TABLE 	bpm_QY_YS_File_view	;
DROP TABLE 	bpm_QY_YS_PayPlan_view	;
DROP TABLE 	bpm_QY_YS_Settlement_view	;
DROP TABLE 	bpm_QY_YS_Subject_view	;
DROP TABLE 	bpm_QY_YS_view	;

--DROP TABLE 	BPM_JITICHONGXIAO_NEW_VIEW	;
--DROP TABLE 	BPM_JITICHONGXIAOMAIN_NEW_VIEW	;
--DROP TABLE 	bpm_toheyue_htfkjlkemu_view;
--DROP TABLE 	bpm_lxiangyanshoukemu_view;
--DROP TABLE 	bpm_htyufukuankemu_view;

SELECT * INTO bpm_QY_ContractType_view from openquery(BPM, 'select * from sgbpm_prd.bpm_QY_ContractType_view') TEMP;
SELECT * INTO bpm_QY_Legal_view 
from openquery(BPM,'select 
NBFRZTID, GSMC, NSRSBH, FDDLR, GSDZ, YZBM, LXDH, BZ, NBFRBH, KAIHUHANG, KAIHUMINGCHENG, KAIHUZHUANGHAO, CJR, CJSJ,
 XGR, XGSJ, LIANHANCODE, AREACODEINFO, REC_PROVINCE, REC_CITY, USAGE, TYPES ,cast(RecordStatus AS varchar(10))  AS  RecordStatus
from sgbpm_prd.bpm_QY_Legal_view') a;

SELECT * INTO bpm_QY_Subject_view from openquery(BPM, 'select 
YUSUANKEMUID                  ,
YUSUANKEMUMINGCHENG           ,
YUSUANKEMUBIANHAO             ,
FUJIKEMUID                    ,
KEMUJIBIE                     ,
cast(SHIFOUMOJIKEMU AS varchar(10))           AS     SHIFOUMOJIKEMU,
CHANNELTYPE                   ,
ISBAOXIAO                     ,
COSTTYPE                      ,
ISCHECKEXTRACT                ,
ISCHECKPACT                   ,
ISHOUSE                       ,
ISNEGATIVE                    ,
ISKEMUADJUST                  ,
MINLXZHAOBIAOJINE             ,
MAXFEIHETONGLXJINE            ,
MAXLXYANSHOUJINE              ,
YUSUANLEIXING                 ,
PROJECTTYPE                   ,
SUBJECTTYPE                   ,
ASSESSMENT_TYPE               ,
YUSUANKEMUSHUILV              ,
GXMC                          ,
YUSUANKEMUSHUOMING            ,
XIUGAIREN                     ,
XIUGAISHIJIAN                 ,
cast(RECORDSTATUS AS varchar(10))           AS     RECORDSTATUS

 from sgbpm_prd.bpm_QY_Subject_view') TEMP;
SELECT * INTO bpm_QY_BudgetMapKM_view 
 from openquery(BPM,'select 


YUSUANKEMUID       ,
NEWKMMC            ,
NEWKMBH            ,
CHANNELTYPE        ,
COSTTYPE           ,
PROJECTTYPE        ,
SUBJECTTYPE        ,
OLDKMMC            ,
OLDKMBH            ,
CJR                ,
CJSJ               ,
XGR                ,
XGSJ               ,  
cast(RecordStatus AS varchar(10))           AS     RecordStatus


 from sgbpm_prd.bpm_QY_BudgetMapKM_view') a;
SELECT * INTO bpm_QY_Project_view from openquery(BPM, 'select * from sgbpm_prd.bpm_QY_Project_view') TEMP;
SELECT * INTO bpm_QY_BudgetZT_view from openquery(BPM, 'select * from sgbpm_prd.bpm_QY_BudgetZT_view') TEMP;
SELECT * INTO bpm_QY_BudgetMapZT_view from openquery(BPM, 'select 
ID, OLDZTBH, OLDZTMC, NEWZTID, NEWZTBH, NEWZTMC, CJR, CJSJ, XGR, XGSJ, TYPE, STATUS, TYPENAME
,  
cast(RecordStatus AS varchar(10))           AS     RecordStatus
 from sgbpm_prd.bpm_QY_BudgetMapZT_view') TEMP;


SELECT * INTO bpm_QY_ContractBasic_view from openquery(BPM, 'select * from sgbpm_prd.bpm_QY_ContractBasic_view') TEMP;
SELECT * INTO bpm_QY_ContractParty_view from openquery(BPM, 'select * from sgbpm_prd.bpm_QY_ContractParty_view') TEMP;
SELECT * INTO bpm_QY_ContractPayment_view from openquery(BPM, 'select * from sgbpm_prd.bpm_QY_ContractPayment_view') TEMP;
SELECT * INTO bpm_QY_ContractAppendices_view from openquery(BPM, 'select * from sgbpm_prd.bpm_QY_ContractAppendices_view') TEMP;
SELECT * INTO bpm_QY_ContractCost_view from openquery(BPM, 'select * from sgbpm_prd.bpm_QY_ContractCost_view') TEMP;
SELECT * INTO bpm_QY_YS_view from openquery(BPM, 'select * from sgbpm_prd.bpm_QY_YS_view') TEMP;
SELECT * INTO bpm_QY_YS_PayPlan_view from openquery(BPM, 'select * from sgbpm_prd.bpm_QY_YS_PayPlan_view') TEMP;
SELECT * INTO bpm_QY_YS_Subject_view from openquery(BPM, 'select * from sgbpm_prd.bpm_QY_YS_Subject_view') TEMP;
SELECT * INTO bpm_QY_YS_Settlement_view from openquery(BPM, 'select * from sgbpm_prd.bpm_QY_YS_Settlement_view') TEMP;
SELECT * INTO bpm_QY_YS_File_view from openquery(BPM, 'select * from sgbpm_prd.bpm_QY_YS_File_view') TEMP;

--SELECT * INTO bpm_fkjl_heyue_view from openquery(BPM, 'select * from sgbpm_prd.bpm_fkjl_heyue_view') TEMP;

SELECT * INTO bpm_QY_LX_Basic_view from openquery(BPM, 'select * from sgbpm_prd.bpm_QY_LX_Basic_view') TEMP;
SELECT * INTO bpm_QY_LX_Subject_view from openquery(BPM, 'select * from sgbpm_prd.bpm_QY_LX_Subject_view') TEMP;
SELECT * INTO bpm_QY_LX_File_view from openquery(BPM, 'select * from sgbpm_prd.bpm_QY_LX_File_view') TEMP;
SELECT * INTO bpm_QY_LX_Release_view from openquery(BPM, 'select * from sgbpm_prd.bpm_QY_LX_Release_view') TEMP;

SELECT * INTO bpm_QY_ContractMatter_view from openquery(BPM, 'select * from sgbpm_prd.bpm_QY_ContractMatter_view') TEMP;
SELECT * INTO bpm_QY_Provision_gys_view from openquery(BPM, 'select * from sgbpm_prd.bpm_QY_Provision_gys_view') TEMP;
SELECT * INTO bpm_QY_Provision_jtmx_view from openquery(BPM, 'select * from sgbpm_prd.bpm_QY_Provision_jtmx_view') TEMP;
SELECT * INTO bpm_QY_Provision_view from openquery(BPM, 'select * from sgbpm_prd.bpm_QY_Provision_view') TEMP;

SELECT * INTO bpm_QY_Department_view from VIEW_SS_bpm_QY_Department_view TEMP;
SELECT * INTO bpm_QY_Company_view from VIEW_SS_bpm_QY_Company_view TEMP;
SELECT * INTO bpm_QY_Person_view from VIEW_EAS_PERSON TEMP;

--SELECT * INTO BPM_JITICHONGXIAO_NEW_VIEW  from  openquery(BPM,'select * from sgbpm_prd.BPM_JITICHONGXIAO_NEW_VIEW where xmbh
--IN(''HSHS379'',''ZJZJ457'',''XHS288'',''HSHS370'') and ZTLX=''1''') a;
--SELECT * INTO BPM_JITICHONGXIAOMAIN_NEW_VIEW  from  openquery(BPM,'select * from sgbpm_prd.BPM_JITICHONGXIAOMAIN_NEW_VIEW') a;


--SELECT 
--* INTO bpm_toheyue_htfkjlkemu_view 
-- from  openquery(BPM,'select * from sgbpm_prd.bpm_toheyue_htfkjlkemu_view') a;
--SELECT * FROM QY_Project WHERE [项目名称] IN ('成都温江合生汇','北京朝阳合生汇','广州海珠合生广场南区','广州海珠合生广场北区')

--SELECT * INTO bpm_lxiangyanshoukemu_view  from  openquery(BPM,'select * from sgbpm_prd.bpm_lxiangyanshoukemu_view') a;

--SELECT * INTO bpm_htyufukuankemu_view  from  openquery(BPM,'select * from sgbpm_prd.bpm_htyufukuankemu_view') a;

end
GO

3. After executing the above Proc_IN_BPM stored procedure, we will find that there are many more tables under the BPMTable column in the QY_Tables table in our intermediate library. This is the data source table we have synchronized. All subsequent operations are performed on these tables. deal with

4. Cleaning process:

  1.  Write the view VIEW_SQL_Proc_IN to obtain the data source table of the Chinese field of the third-party data source. The main purpose of obtaining the Chinese field is to facilitate data verification.
    create VIEW VIEW_SQL_Proc_IN AS
    SELECT 
    'CREATE proc Proc_IN_'+QyTableName+' AS begin INSERT INTO '+QyTableName+
    ' ('+LEFT(BPMList2,LEN(BPMList2)-1)+') '+
    ' SELECT ' +LEFT(BPMList,LEN(BPMList)-1)
    + ' FROM '+BPMVIEW + ' END GO ' AS SQL2
    FROM (
    	SELECT 
    	QyTableName,BPMTable,BPMVIEW,
    	(
    		SELECT SQL1+',' FROM VIEW_CheckSQL
    		WHERE QyTableName=A.QyTableName
    		FOR XML PATH('')
    	) AS BPMList,
    		(
    		SELECT QyTableFieldName+',' FROM VIEW_CheckSQL
    		WHERE QyTableFieldCodeBPM IS NOT NULL AND QyTableName=A.QyTableName
    		FOR XML PATH('')
    	) AS BPMList2
    	FROM VIEW_CheckSQL A
    	--WHERE QyTableName='QY_ContractType'
    	GROUP BY QyTableName,BPMTable,BPMVIEW
    )TEMP
    WHERE BPMList <> ''
    GO
    
    
    create VIEW VIEW_CheckSQL AS
    	SELECT 
    	T.Business,
    	T.TableName,
    	T.BPMTable,
    	T.BPMVIEW,
    	M.QyTableName,
    	M.QyTableFieldName,
    	M.QyTableFieldCodeBPM,
    	M.QyIsNull,
    	M.QyIsNullBPM,
    	CASE 
    	WHEN M.QyDeaultBPMValue IS NULL THEN M.QyTableFieldCodeBPM+ +' AS ['+M.QyTableFieldName+']'
    	ELSE 
    	'ISNULL('+M.QyTableFieldCodeBPM+','''+M.QyDeaultBPMValue+''')'+' AS ['+M.QyTableFieldName+']'
    	END AS SQL1
    	FROM
    	VIEW_Qy_Maping M
    	LEFT JOIN VIEW_QY_Tables T ON T.TableCode=M.QyTableName
    	WHERE QyTableFieldName IS NOT NULL
    GO
    
    
  2. Querying VIEW_SQL_Proc_IN will get the execution statement of a stored procedure for all tables. After copying the query results, execute them in batches and then encapsulate them into stored procedures.
    CREATE proc [Proc_IN_QY]
    as
    BEGIN
    DELETE FROM 	QY_BudgetMapKM	;
    DELETE FROM 	 QY_BudgetMapZT	;
    DELETE FROM 	 QY_BudgetZT	;
    DELETE FROM 	 QY_ContractAppendices	;
    DELETE FROM 	 QY_ContractBasic	;
    DELETE FROM 	 QY_ContractCost	;
    DELETE FROM 	 QY_ContractParty	;
    DELETE FROM 	 QY_ContractPayment	;
    DELETE FROM 	 QY_ContractType	;
    --DELETE FROM 	 QY_Department	;
    --DELETE FROM 	 QY_Legal	;
    DELETE FROM 	 QY_LX_Basic	;
    DELETE FROM 	 QY_LX_File	;
    DELETE FROM 	 QY_LX_Release	;
    DELETE FROM 	 QY_LX_Subject	;
    DELETE FROM 	 QY_Project	;
    DELETE FROM 	 QY_ProjectLegal	;
    DELETE FROM 	 QY_Subject	;
    DELETE FROM 	 QY_YS	;
    DELETE FROM 	 QY_YS_File	;
    DELETE FROM 	 QY_YS_PayPlan	;
    DELETE FROM 	 QY_YS_Settlement	;
    DELETE FROM 	 QY_YS_Subject	;
    DELETE FROM 	 QY_YS_Pay 	;
    
    DELETE FROM 	 QY_Provision		;
    DELETE FROM 	 QY_Provision_jtmx		;
    DELETE FROM 	 QY_Provision_gys		;
    DELETE FROM 	 QY_ContractMatter		;
    
    DELETE FROM 	 QY_Company 	;
    --DELETE FROM 	 QY_Person 	;
    --DELETE FROM 	 QY_ProjectLegal 	;
    DELETE FROM 	 QY_ProjectMap 	;
    --DELETE FROM 	 QY_JITICHONGXIAOMAIN 	;
    
    exec	Proc_IN_QY_BudgetMapKM	;
    exec	 Proc_IN_QY_BudgetMapZT	;
    exec	 Proc_IN_QY_BudgetZT	;
    exec	 Proc_IN_QY_ContractAppendices	;
    exec	 Proc_IN_QY_ContractBasic	;
    exec	 Proc_IN_QY_ContractCost	;
    exec	 Proc_IN_QY_ContractParty	;
    exec	 Proc_IN_QY_ContractPayment	;
    exec	 Proc_IN_QY_ContractType	;
    --exec	 Proc_IN_QY_Legal	;
    exec	 Proc_IN_QY_LX_Basic	;
    exec	 Proc_IN_QY_LX_File	;
    exec	 Proc_IN_QY_LX_Release	;
    exec	 Proc_IN_QY_LX_Subject	;
    exec	 Proc_IN_QY_Project	;
    exec	 Proc_IN_QY_Subject	;
    exec	 Proc_IN_QY_YS	;
    exec	 Proc_IN_QY_YS_File	;
    exec	 Proc_IN_QY_YS_PayPlan	;
    exec	 Proc_IN_QY_YS_Settlement	;
    exec	 Proc_IN_QY_YS_Subject	;
    exec	 Proc_IN_QY_YS_Pay
    
    exec	 Proc_IN_QY_ContractMatter	;
    exec	 Proc_IN_QY_Provision	;
    exec	 Proc_IN_QY_Provision_jtmx	;
    exec	 Proc_IN_QY_Provision_gys	;
    
    --exec	 Proc_IN_QY_Department	;
    --exec	 Proc_IN_QY_Person	;
    
    exec	 Proc_IN_QY_Company	;
    --exec	 Proc_IN_QY_ProjectLegal	;
    exec	Proc_IN_QY_ProjectMap	;
    --exec	Proc_IN_QY_JITICHONGXIAOMAIN	;
    
    exec	Proc_BPM_Clear	;
    end
    GO
    
    
  3. After executing the Proc_IN_QY stored procedure, we will get the Chinese data source tables of all migrated data sources. The main purpose is to facilitate viewing of the data sources.

  4. Next, write the view VIEW_SQL_Proc_OUT. We write the data source of the current intermediate library to the target library.

    CREATE VIEW VIEW_SQL_Proc_OUT AS
    
    SELECT 
    'if OBJECT_ID(''dbo.PROC_OUT_'+TableCode+''',''procedure'') is not null BEGIN DROP PROC dbo.PROC_OUT_' + TableCode + '  END GO'  AS SQL1
    FROM VIEW_QY_Tables
    WHERE BPMTable <> ''
    UNION
    SELECT 
    'CREATE proc Proc_OUT_'+TableCode+' AS begin INSERT INTO [HY].[HopsonCost].[dbo].'+TableCode+
    ' SELECT * FROM '+TableCode + ' END GO ' AS SQL1
    FROM VIEW_QY_Tables
    WHERE BPMTable <> ''
    GO
    
  5. Executing VIEW_SQL_Proc_OUT will get all the written stored procedure codes, paste and copy them, and execute them.

  6. Similarly, package the above stored procedure into Proc_OUT_QY for easy execution

    CREATE proc [dbo].[Proc_OUT_QY]
    as
    begin
    
    DELETE FROM [HY].[HopsonCost].[dbo].QY_BudgetMapKM;
    DELETE FROM [HY].[HopsonCost].[dbo].QY_BudgetMapZT;
    DELETE FROM [HY].[HopsonCost].[dbo].QY_BudgetZT;
    DELETE FROM [HY].[HopsonCost].[dbo].QY_ContractAppendices;
    DELETE FROM [HY].[HopsonCost].[dbo].QY_ContractBasic;
    DELETE FROM [HY].[HopsonCost].[dbo].QY_ContractCost;
    DELETE FROM [HY].[HopsonCost].[dbo].QY_ContractParty;
    DELETE FROM [HY].[HopsonCost].[dbo].QY_ContractPayment;
    DELETE FROM [HY].[HopsonCost].[dbo].QY_ContractType;
    --DELETE FROM [HY].[HopsonCost].[dbo].QY_Department;
    --DELETE FROM [HY].[HopsonCost].[dbo].QY_Legal;
    DELETE FROM [HY].[HopsonCost].[dbo].QY_LX_Basic;
    DELETE FROM [HY].[HopsonCost].[dbo].QY_LX_File;
    DELETE FROM [HY].[HopsonCost].[dbo].QY_LX_Release;
    DELETE FROM [HY].[HopsonCost].[dbo].QY_LX_Subject;
    DELETE FROM [HY].[HopsonCost].[dbo].QY_Project;
    --DELETE FROM [HY].[HopsonCost].[dbo].QY_ProjectLegal;
    DELETE FROM [HY].[HopsonCost].[dbo].QY_Subject;
    DELETE FROM [HY].[HopsonCost].[dbo].QY_YS;
    DELETE FROM [HY].[HopsonCost].[dbo].QY_YS_File;
    DELETE FROM [HY].[HopsonCost].[dbo].QY_YS_PayPlan;
    DELETE FROM [HY].[HopsonCost].[dbo].QY_YS_Settlement;
    DELETE FROM [HY].[HopsonCost].[dbo].QY_YS_Subject;
    DELETE FROM [HY].[HopsonCost].[dbo].QY_YS_Pay;
    DELETE FROM [HY].[HopsonCost].[dbo].QY_Company;
    --DELETE FROM [HY].[HopsonCost].[dbo].QY_Person;
    --DELETE FROM [HY].[HopsonCost].[dbo].QY_ProjectLegal;
    DELETE FROM [HY].[HopsonCost].[dbo].QY_ProjectMap;
    DELETE FROM [HY].[HopsonCost].[dbo].QY_ContractMatter;
    DELETE FROM [HY].[HopsonCost].[dbo].QY_Provision;
    DELETE FROM [HY].[HopsonCost].[dbo].QY_Provision_jtmx;
    DELETE FROM [HY].[HopsonCost].[dbo].QY_Provision_gys;
    --DELETE FROM [HY].[HopsonCost].[dbo].QY_JITICHONGXIAOMAIN 	;
    
    
    
    exec	Proc_OUT_QY_BudgetMapKM	;
    exec	 Proc_OUT_QY_BudgetMapZT	;
    exec	 Proc_OUT_QY_BudgetZT	;
    exec	 Proc_OUT_QY_ContractAppendices	;
    exec	 Proc_OUT_QY_ContractBasic	;
    exec	 Proc_OUT_QY_ContractCost	;
    exec	 Proc_OUT_QY_ContractParty	;
    exec	 Proc_OUT_QY_ContractPayment	;
    exec	 Proc_OUT_QY_ContractType	;
    --exec	 Proc_OUT_QY_Legal	;
    exec	 Proc_OUT_QY_Project	;
    exec	 Proc_OUT_QY_Subject	;
    exec	 Proc_OUT_QY_YS	;
    exec	 Proc_OUT_QY_YS_File	;
    exec	 Proc_OUT_QY_YS_PayPlan	;
    exec	 Proc_OUT_QY_YS_Settlement	;
    exec	 Proc_OUT_QY_YS_Subject	;
    exec	 Proc_OUT_QY_YS_Pay;
    exec	 Proc_OUT_QY_LX_Basic	;
    exec	 Proc_OUT_QY_LX_Subject	;
    exec	 Proc_OUT_QY_LX_File	;
    exec	 Proc_OUT_QY_LX_Release	;
    --exec	 Proc_OUT_QY_Department	;
    --exec	 Proc_OUT_QY_ProjectLegal	;
    exec	Proc_OUT_QY_Company	;
    --exec	Proc_OUT_QY_Person	;
    exec	Proc_OUT_QY_ProjectMap	;
    exec	 Proc_OUT_QY_ContractMatter	;
    exec	Proc_OUT_QY_Provision	;
    exec	Proc_OUT_QY_Provision_gys	;
    exec	Proc_OUT_QY_Provision_jtmx	;
    --exec	Proc_OUT_QY_JITICHONGXIAOMAIN	;
    
    --DROP TABLE [HY].[HopsonCost].[dbo].bpm_fkjl_heyue_view;
    --DROP TABLE [HY].[HopsonCost].[dbo].bpm_toheyue_htfkjlkemu_view;
    
    --SELECT * INTO [HY].[HopsonCost].[dbo].bpm_fkjl_heyue_view FROM bpm_fkjl_heyue_view;
    --SELECT * INTO [HY].[HopsonCost].[dbo].bpm_toheyue_htfkjlkemu_view FROM bpm_toheyue_htfkjlkemu_view;
    
    --DROP TABLE [HY].[HopsonCost].[dbo].bpm_htyufukuankemu_view;
    --DROP TABLE [HY].[HopsonCost].[dbo].bpm_lxiangyanshoukemu_view;
    
    --SELECT * INTO [HY].[HopsonCost].[dbo].bpm_htyufukuankemu_view FROM bpm_htyufukuankemu_view;
    --SELECT * INTO [HY].[HopsonCost].[dbo].bpm_lxiangyanshoukemu_view FROM bpm_lxiangyanshoukemu_view;
    
    end
    GO
    
    
  7. After executing the above stored procedure, we will find that the data source table of our Chinese field is generated in our target library

5. Data writing

        ​ ​ 1. Based on the obtained data source table, code can be coded, and Qy_FieldDic and Qy_ErrorMsg can be used to convert related field dictionaries and log records.

        2. Introduction to the code of a certain business

/// <summary>
/// 付款申请数据迁移
/// 1.1 主表记录
/// </summary>
/// <returns></returns>
public virtual HttpResponseMessage UpPaymentRequest()
{
    try
    {
        int totalCount = 0, successCount = 0, errorCout = 0;
        string fromTableName = "QY_PaymentRequest";
        string toTableName = "FM_PaymentRequest";
        string qyBUSSID = "PaymentRequestBussID";
        string qyCreateUserID = "CreateUserID";
        string qyModifyUserID = "ModifyUserID";
        string qyProjectID = "ProjectID";
        string qyContractID = "ContractID";
        string qyProAppID = "ProAppID";
        string qyImprestID = "ImprestID";
        using (var context = new MasterDbContext())
        {
            List<Qy_Maping> mapings = context.Qy_Maping.Where(ss => ss.QyTableName == fromTableName).ToList();
            List<Qy_FieldDic> fieldDics = context.Qy_FieldDic.Where(x=>x.BPMTABLE == fromTableName).ToList();
            var BUSSID = mapings.FirstOrDefault(ss => ss.QyTableFieldCode == qyBUSSID);
            if (BUSSID == null)
            {
                return WebApiHelper.GetErrorHttpResponseMessage(new { Messsage = "不存在业务ID" });
            }

            DataTable dataTable = context.ExecuteDataTable("select * from " + fromTableName);
            
            totalCount = dataTable.Rows.Count;
            LogTxtInfo("需要迁移" + totalCount + "条");

            var CreateUserID = mapings.FirstOrDefault(ss => ss.QyTableFieldCode == qyCreateUserID);
            var ModifyUserID = mapings.FirstOrDefault(ss => ss.QyTableFieldCode == qyModifyUserID);
            var ProjectID = mapings.FirstOrDefault(ss => ss.QyTableFieldCode == qyProjectID);
            var ProAppID = mapings.FirstOrDefault(ss => ss.QyTableFieldCode == qyProAppID);
            var ContractID = mapings.FirstOrDefault(ss => ss.QyTableFieldCode == qyContractID);
            var ImprestID = mapings.FirstOrDefault(ss => ss.QyTableFieldCode == qyImprestID);
            for (int i = 0; i < dataTable.Rows.Count; i++)
            {
                DataRow row = dataTable.Rows[i];
                object obj = row[BUSSID.QyTableFieldName];
                if (obj == null)
                {
                    //记录日志
                    errorCout++;
                    WriteLog(context, fromTableName, toTableName, "业务ID为空");
                    continue;
                }
                object objCreateUserID = row[CreateUserID.QyTableFieldName];
                object objModifyUserID = row[ModifyUserID.QyTableFieldName];
                object objProjectID = row[ProjectID.QyTableFieldName];
                object objProAppID = row[ProAppID.QyTableFieldName];
                string objContractID = row[ContractID.QyTableFieldName].ToStr();
                string objImprestID = row[ImprestID.QyTableFieldName].ToStr();
                int ProBUSSID = 0;
                if (objProjectID != null)
                {
                    ProBUSSID = context.Database.SqlQuery<int>("SELECT ProjectID FROM dbo.CMN_Project WHERE ProBUSSID = '" + objProjectID.ToString() + "'").FirstOrDefault();
                    ProjectID.QyDefaultValue = ProBUSSID.ToStr();
                }
                int Plixiangid = 0;
                if(ProAppID != null){
                    Plixiangid = context.Database.SqlQuery<int>("SELECT ProAppID FROM CMN_SyncProjectApproval WHERE ProAppBUSSID =  '" + objProAppID + "'").FirstOrDefault();
                    ProAppID.QyDefaultValue = Plixiangid.ToString();
                }
                int CUserID = 0;
                if (objCreateUserID != null)
                {
                    CUserID = context.Database.SqlQuery<int>("SELECT USERID FROM dbo.CF_USER WHERE USERNO = '" + objCreateUserID + "'").FirstOrDefault();
                    CreateUserID.QyDefaultValue = CUserID.ToString();
                }
                int MUserID = 0;
                if (objCreateUserID != null)
                {
                    MUserID = context.Database.SqlQuery<int>("SELECT USERID FROM dbo.CF_USER WHERE USERNO = '" + objModifyUserID + "'").FirstOrDefault();
                    ModifyUserID.QyDefaultValue = MUserID.ToString();
                }
                if (objContractID != "") {
                    var tempContract = context.CON_Contract.FirstOrDefault(x => x.ContractIDBUSSID == objContractID);
                    if (tempContract != null)
                    {
                        ContractID.QyDefaultValue = tempContract.ContractID.ToStr();
                    }
                    else {
                        LogTxtInfo("迁移失败: 未找到合同信息:objContractID=" + objContractID);
                        //记录日志
                        errorCout++;
                        WriteLog(context, fromTableName, toTableName, "迁移失败: 未找到合同信息:objContractID=" + objContractID);
                        continue;
                    }
                }
                if (objImprestID != "") {
                    var tempImprest = context.FM_Imprest.FirstOrDefault(x => x.BPMmainId == objImprestID);
                    if (tempImprest != null)
                    {
                        ImprestID.QyDefaultValue = tempImprest.ImprestID.ToStr();
                    }
                    else
                    {
                        LogTxtInfo("迁移失败: 未找到备用金信息:objImprestID=" + objImprestID);
                        //记录日志
                        errorCout++;
                        WriteLog(context, fromTableName, toTableName, "迁移失败: 未找到备用金信息:objImprestID=" + objImprestID);
                        continue;
                    }
                }
                string updateWhere = string.Empty;
                if (obj.ToString() == "NULL")
                {
                    updateWhere = " WHERE 1=2";
                }
                else
                {
                    updateWhere = " WHERE " + qyBUSSID + "='" + obj.ToString() + "'";
                }
                string sqlCmdInsert = string.Empty;
                string sqlCmdUpdate = string.Empty;
                try
                {
                    using (var dbContextTransaction = context.Database.BeginTransaction())
                    {
                        sqlCmdInsert = CreateInsertSqlCmd(row, toTableName, mapings, fieldDics);
                        sqlCmdUpdate = CreateUpdateSqlCmd(row, toTableName, mapings, fieldDics) + updateWhere;
                        List<SqlParameter> paramArray = new List<SqlParameter>();
                        paramArray.Add(new SqlParameter("@bussid", obj.ToString()));
                        paramArray.Add(new SqlParameter("@insertCmd", sqlCmdInsert));
                        paramArray.Add(new SqlParameter("@updateCmd", sqlCmdUpdate));
                        paramArray.Add(new SqlParameter("@tableName", toTableName));
                        context.Database.ExecuteSqlCommand("[dbo].[Qy_InsertOrUpdateAndInsertPrimarykeyRelation] @bussid , @insertCmd , @updateCmd , @tableName  ", paramArray.ToArray());
                        dbContextTransaction.Commit();
                        successCount++;
                    }
                }
                catch (Exception ex)
                {
                    //记录日志
                    errorCout++;
                    WriteLog(context, fromTableName, toTableName, ex.ToString(), sqlCmdInsert, sqlCmdUpdate);
                    continue;
                }
            }
        }
        LogTxtInfo("迁移完毕,总计:" + totalCount + "条,成功:" + successCount + "条,失败:" + errorCout + "条");
        return WebApiHelper.GetOkHttpResponseMessage(new { Messsage = "迁移完毕,总计:" + totalCount + "条,成功:" + successCount + "条,失败:" + errorCout + "条" });
    }
    catch (Exception ex)
    {
        LogTxtInfo("迁移异常:" + ex.Message.ToString());
        return WebApiHelper.GetErrorHttpResponseMessage(new { Messsage = ex.Message.ToString() });
    }
}
/// <summary>
/// 创建插入数据SQL
/// </summary>
/// <param name="dataRow"></param>
/// <param name="tableName"></param>
/// <param name="mapings"></param>
/// <param name="fieldDics"></param>
/// <returns></returns>
private string CreateInsertSqlCmd(DataRow dataRow, string tableName, List<Qy_Maping> mapings, List<Qy_FieldDic> fieldDics)
{
    mapings = mapings.Where(ss => ss.QyTableFieldCode != null).ToList();
    StringBuilder sqlAppend = new StringBuilder();
    sqlAppend.Append("INSERT INTO " + tableName + "");
    sqlAppend.Append("( ");
    List<string> fields = new List<string>();
    foreach (var item in mapings)
    {
        fields.Add(item.QyTableFieldCode);
    }
    sqlAppend.Append(string.Join(",", fields));
    sqlAppend.Append(")");
    sqlAppend.Append("VALUES ");
    sqlAppend.Append("( ");
    List<string> values = new List<string>();
    for (int k = 0; k < mapings.Count; k++)
    {
        Qy_Maping maping = mapings[k];
        try
        {
            string QyTableFieldName = maping.QyTableFieldName;
            if (string.IsNullOrEmpty(QyTableFieldName))
            {
                if (string.IsNullOrEmpty(maping.QyDefaultValue))
                {
                    values.Add("NULL");
                }
                else
                {
                    //values.Add("'" + mapings[k].QyDefaultValue + "'");
                    values.Add(GetFieldTypeForValue(maping.QyTableFieldType, maping.QyDefaultValue));
                }
            }
            else
            {
                //如果设置默认值,则强制覆盖
                if (!string.IsNullOrEmpty(maping.QyDefaultValue))
                {
                    //values.Add("'" + mapings[k].QyDefaultValue + "'");
                    values.Add(GetFieldTypeForValue(maping.QyTableFieldType, maping.QyDefaultValue));
                }
                else
                {
                    object obj = dataRow[QyTableFieldName];
                    if (obj != null && !string.IsNullOrEmpty(obj.ToString()))
                    {
                        string value = GetValue(obj, maping.QyPOPTYPE, maping.QyPOPTYPEValueSouce, fieldDics);
                        if (value == "NULL")
                            values.Add(value);
                        else
                            //values.Add(value);
                            values.Add(GetFieldTypeForValue(maping.QyTableFieldType, value));
                    }
                    else
                    {
                        if (!string.IsNullOrEmpty(maping.QyRelaceNullValue))
                        {
                            values.Add(GetFieldTypeForValue(maping.QyTableFieldType, maping.QyRelaceNullValue));
                        }
                        else
                            values.Add(" NULL ");
                    }
                }
            }
        }
        catch (Exception ex)
        {
            throw new Exception("错误字段:" + maping.QyTableFieldName + ",错误消息:" + ex.Message);
        }
    }
    sqlAppend.Append(string.Join(",", values));
    sqlAppend.Append(")");
    return sqlAppend.ToString();
}


/// <summary>
/// 创建更新数据SQL
/// </summary>
/// <param name="dataRow"></param>
/// <param name="tableName"></param>
/// <param name="mapings"></param>
/// <param name="fieldDics"></param>
/// <returns></returns>
private string CreateUpdateSqlCmd(DataRow dataRow, string tableName, List<Qy_Maping> mapings, List<Qy_FieldDic> fieldDics)
{
    mapings = mapings.Where(ss => ss.QyTableFieldCode != null).ToList();
    List<string> sqlCmdUpdateTabel = new List<string>();
    StringBuilder sqlAppend = new StringBuilder();
    sqlAppend.Append("UPDATE " + tableName + " SET ");
    List<string> values = new List<string>();
    for (int k = 0; k < mapings.Count; k++)
    {
        Qy_Maping maping = mapings[k];
        try
        {
            string QyTableFieldName = maping.QyTableFieldName;
            if (string.IsNullOrEmpty(QyTableFieldName))
            {
                if (string.IsNullOrEmpty(maping.QyDefaultValue))
                {
                    values.Add(maping.QyTableFieldCode + "= NULL ");
                }
                else
                {
                    values.Add(mapings[k].QyTableFieldCode + " = " + GetFieldTypeForValue(maping.QyTableFieldType, maping.QyDefaultValue));
                }
            }
            else
            {
                //如果设置默认值,则强制覆盖
                if (!string.IsNullOrEmpty(maping.QyDefaultValue))
                {
                    values.Add(maping.QyTableFieldCode + "= " + GetFieldTypeForValue(maping.QyTableFieldType, maping.QyDefaultValue));
                }
                else
                {
                    object obj = dataRow[QyTableFieldName];
                    if (obj != null && !string.IsNullOrEmpty(obj.ToString()))
                    {
                        string value = GetValue(obj, maping.QyPOPTYPE, maping.QyPOPTYPEValueSouce, fieldDics);
                        if (value == "NULL")
                            values.Add(maping.QyTableFieldCode + "= NULL ");
                        else
                            values.Add(maping.QyTableFieldCode + " = " + GetFieldTypeForValue(maping.QyTableFieldType, value));
                    }
                    else
                    {
                        if (!string.IsNullOrEmpty(maping.QyRelaceNullValue))
                        {
                            values.Add(maping.QyTableFieldCode + " = " + GetFieldTypeForValue(maping.QyTableFieldType, maping.QyRelaceNullValue));
                        }
                        else
                            values.Add(maping.QyTableFieldCode + "= NULL ");
                    }
                }
            }
        }
        catch (Exception ex)
        {
            throw new Exception("错误字段:" + maping.QyTableFieldName + ",错误消息:" + ex.Message);
        }
    }
    sqlAppend.Append(string.Join(",", values));
    return sqlAppend.ToString();
}

/// <summary>
/// 根据字段类型创建SQL语句的Values
/// </summary>
/// <param name="QyTableFieldType"></param>
/// <param name="Value"></param>
/// <returns></returns>
private string GetFieldTypeForValue(string QyTableFieldType, string Value)
{
    try
    {
        if (string.IsNullOrEmpty(QyTableFieldType))
            return "'" + Value + "'";
        string fieldValue = string.Empty;
        switch (QyTableFieldType)
        {
            case "char": fieldValue = "'" + Value + "'"; break;
            case "date": fieldValue = "'" + Value + "'"; break;
            case "datetime": fieldValue = "'" + Convert.ToDateTime(Value).ToString("yyyy-MM-dd HH:mm:ss") + "'"; break;
            case "int": fieldValue = Convert.ToInt32(Value).ToString(); break;
            case "decimal": fieldValue = Convert.ToDecimal(Value).ToString(); break;
            case "nvarchar": fieldValue = "'" + Value.Replace("'", "’") + "'"; break;
            case "VARCHAR2": fieldValue = "'" + Value.Replace("'", "’") + "'"; break;
            case "NUMBER": fieldValue = Convert.ToInt32(Value).ToString(); break;
            case "NUMBER(20,4)": fieldValue = Convert.ToDecimal(Value).ToString(); break;
            case "TIMESTAMP": fieldValue = "to_timestamp('" + Convert.ToDateTime(Value).ToString() + "','YYYY-MM-DDHH24:MI:SS')"; break;
            case "DATE": fieldValue = "to_date('" + Convert.ToDateTime(Value).ToString() + "','YYYY-MM-DDHH24:MI:SS')"; break;
            default: fieldValue = "'" + Value + "'"; break;
        }
        return fieldValue;
    }
    catch (Exception ex)
    {
        throw new Exception(ex.Message);
    }
}

/// <summary>
/// 记录错误日志
/// </summary>
/// <param name="context"></param>
/// <param name="fromTable"></param>
/// <param name="toTable"></param>
/// <param name="errorMsg"></param>
/// <param name="sqlCmdInsert"></param>
/// <param name="sqlCmdUpdate"></param>
private void WriteLog(MasterDbContext context, string fromTable, string toTable, string errorMsg, string sqlCmdInsert = "", string sqlCmdUpdate = "")
{
    string sqlCmdLog = "INSERT INTO[dbo].[Qy_ErrorMsg]([FromTableName],[ToTableName],[ErrorMsg],[ErrorInsertSqlCmd],[ErrorUpdateSqlCmd]) VALUES(@FromTableName,@ToTableName,@ErrorMsg,@ErrorInsertSqlCmd,@ErrorUpdateSqlCmd)";
    List<SqlParameter> paramArray = new List<SqlParameter>();
    paramArray.Add(new SqlParameter("@FromTableName", fromTable));
    paramArray.Add(new SqlParameter("@ToTableName", toTable));
    paramArray.Add(new SqlParameter("@ErrorMsg", errorMsg));
    paramArray.Add(new SqlParameter("@ErrorInsertSqlCmd", sqlCmdInsert));
    paramArray.Add(new SqlParameter("@ErrorUpdateSqlCmd", sqlCmdUpdate));
    context.Database.ExecuteSqlCommand(sqlCmdLog, paramArray.ToArray());
}

Summarize

        At this point, the overall migration is completed. In the migration process, there are actually not many difficulties, it just requires more patienceandcare< a i=4>. Similarly, the above migration ideas can also be simplified. However, I personally think that this is safer and easier to verify later data. Of course, there are many other solutions, welcome to discuss~~~

Guess you like

Origin blog.csdn.net/qq_18316109/article/details/125685517