利用动态数据管道技术迁移不同版本或者不同类型数据库数据

本场景案例是Informix数据库从7.3版本往11.0版本迁移数据,由于版本跨度过大,数据库文件系统结构不同,导致无法通过服务器打包数据方式来迁移数据,因此用到动态数据管道来实现数据迁移

global type f_pipeline_full from function_object
end type

forward prototypes
global function string f_pipeline_full (transaction atrans_source, transaction atrans_destination, string as_tablename, integer ai_pipe_type)
end prototypes

global function string f_pipeline_full (transaction atrans_source, transaction atrans_destination, string as_tablename, integer ai_pipe_type);//====================================================================
// 事件: .f_pipeline_full()
//--------------------------------------------------------------------
// 描述:用于Informix数据库版本跨度过大,无法通过服务器打包恢复数据,故通过构造动态数据管道来迁移数据
//			该函数目前待完善处:1.无法获取column的null属性,暂时把管道中该属性全部填充nulls_allowed=yes,以免空字段传输异常
//--------------------------------------------------------------------
// 参数:
// 	value	transaction	atrans_source     	
// 	value	transaction	atrans_destination	
// 	value	string     	as_tablename      	
// 	value	integer    	ai_pipe_type      	
//--------------------------------------------------------------------
// 返回:  string
//--------------------------------------------------------------------
// 作者:	JGM		日期: 2018年03月10日
//--------------------------------------------------------------------
//	Copyright (c) 2017 JGM (TM), All rights reserved.
//--------------------------------------------------------------------
// 修改历史:
//
//====================================================================

Int i ,li_columncount , li_return
String ls_pipeline1,ls_pipeline2,ls_pipeline3,ls_pipeline4,ls_pipesyn

//定义数据管道操作方式
String ls_pipetype[5] = {"create" , "replace" ,"refresh" , "append" , "update" }

String ls_sourcetype,ls_destype,ls_colname,ls_sourcedbtype,ls_desdbtype,ls_inital,ls_sourcetype_temp,ls_source_key
String ls_insertcol,ls_sel,errors
pipeline pipe_sourcetodes
datastore lds_source

ls_sel = "SELECT * FROM " + as_tablename
lds_source = Create datastore

//动态创建datastore,用以获取字段名及数据类型
lds_source.Create(atrans_source.SyntaxFromSQL ( ls_sel ,"style(type=grid)",errors))

If Len(errors) > 0 Then Return '动态数据存储创建失败'

li_columncount = Integer(lds_source.Object.DataWindow.Column.Count)

pipe_sourcetodes = Create pipeline

If ai_pipe_type <= 2 Then
	ls_pipeline1 = 'PIPELINE(source_connect=lybh,destination_connect=jdbh,type='+ls_pipetype[ai_pipe_type]+',commit=100,errors=100,keyname="' + as_tablename + '_x")'
Else
	Return '数据管道传输方式暂未写'
End If

ls_pipeline2 = 'SOURCE(name="' + as_tablename + '",'

ls_pipeline3 = "RETRIEVE(statement=~"PBSELECT(VERSION(400)TABLE ( NAME = ~~~""+as_tablename + "~~~")"

//"~""双引号中"字符串需转义~",等同于'"',两者并无区别,就像单纯引用字符串用单引号'',和双引号"",并无区别

ls_pipeline4 = "DESTINATION(name=~""+as_tablename+"~","

//循环获取字段名及数据类型,构造动态数据管道语法
For i = 1 To li_columncount
	ls_colname = String(lds_source.Describe("#"+String(i)+".dbname"))
	ls_sourcetype_temp = String(lds_source.Describe("#"+String(i)+".coltype"))
	ls_source_key = String(lds_source.Describe("#"+String(i)+".key"))
	
	//判断字段数据类型,根据数据类型构造动态数据管道语法	
	Choose Case Upper(Left(ls_sourcetype_temp,3))
	
		Case "CHA"
			ls_sourcetype = "char"
			ls_sourcedbtype = "~"CHAR"+Right(ls_sourcetype_temp,Len(ls_sourcetype_temp)-Pos(ls_sourcetype_temp,"(")+1)+"~""
			ls_destype = "char"
			ls_desdbtype = "~"CHAR"+Right(ls_sourcetype_temp,Len(ls_sourcetype_temp)-Pos(ls_sourcetype_temp,"(")+1)+"~""
			ls_inital = "~"spaces~""
		Case "DEC"
			ls_sourcetype = "decimal"
			ls_sourcedbtype = "~"DECIMAL"+"(20,"+Right(ls_sourcetype_temp,Len(ls_sourcetype_temp)-Pos(ls_sourcetype_temp,"("))+"~""
			ls_destype = "decimal"
			ls_desdbtype = "~"DECIMAL"+"(20,"+Right(ls_sourcetype_temp,Len(ls_sourcetype_temp)-Pos(ls_sourcetype_temp,"("))+"~""
			ls_inital = "~"0~""
		Case "DAT"
			If Upper(ls_sourcetype_temp) = "DATE" Then
				ls_sourcetype = "date"
				ls_sourcedbtype = '"DATE"'
				ls_destype = "date"
				ls_desdbtype = '"DATE"'
			ElseIf Upper(ls_sourcetype_temp) = "DATETIME" Then
				ls_sourcetype = "datetime"
				ls_sourcedbtype = '"DATETIME"'
				ls_destype = "datetime"
				ls_desdbtype = '"DATETIME"'
			End If
			ls_inital = "~"today~""
		Case "INT"
			ls_sourcetype = "int"
			ls_sourcedbtype = '"SMALLINT"'
			ls_destype = "int"
			ls_desdbtype = '"SMALLINT"'
			ls_inital = "~"0~""
		Case "LON"
			ls_sourcetype = "long"
			ls_sourcedbtype = '"INTEGER"'
			ls_destype = "long"
			ls_desdbtype = '"INTEGER"'
			ls_inital = "~"0~""
		Case "DOU"
			ls_sourcetype = "double"
			ls_sourcedbtype = '"FLOAT"'
			ls_destype = "double"
			ls_desdbtype = '"FLOAT"'
			ls_inital = "~"0~""
		Case "TIM"
			ls_sourcetype = "time"
			ls_sourcedbtype = '"TIME"'
			ls_destype = "time"
			ls_desdbtype = '"TIME"'
			ls_inital = "~"0~""
	End Choose
	
	ls_pipeline3+= "COLUMN(NAME=~~~""+as_tablename+"."+ls_colname+"~~~")"
	//判断主键标识
	If Upper(Trim(ls_source_key)) = "YES" Then
		ls_pipeline2+= "COLUMN(type="+ls_sourcetype+",name=~""+ls_colname+"~",dbtype="+ls_sourcedbtype+",key=yes,nulls_allowed=yes)"+"~r~n"
		ls_pipeline4+= "COLUMN(type="+ls_destype+",name=~""+ls_colname+"~",dbtype="+ls_desdbtype+",key=yes,nulls_allowed=yes,initial_value="+ls_inital+")"+"~r~n"
	Else
		ls_pipeline2+= "COLUMN(type="+ls_sourcetype+",name=~""+ls_colname+"~",dbtype="+ls_sourcedbtype+",nulls_allowed=yes)"+"~r~n"
		ls_pipeline4+= "COLUMN(type="+ls_destype+",name=~""+ls_colname+"~",dbtype="+ls_desdbtype+",nulls_allowed=yes,initial_value="+ls_inital+")"+"~r~n"
	End If
Next

ls_pipeline2+= +")"
ls_pipeline3+= ")~")"
ls_pipeline4+= +")"

ls_pipesyn = ls_pipeline1+"~r~n"+ls_pipeline2+"~r~n"+ls_pipeline3+"~r~n"+ls_pipeline4


MessageBox("",ls_pipesyn)


pipe_sourcetodes.Syntax = ls_pipesyn //将数据管道语法字符串赋值给Syntax属性
li_return = pipe_sourcetodes.Start(atrans_source,atrans_destination,lds_source) //启动数据管道

Destroy lds_source
Destroy pipe_sourcetodes

Choose Case li_return //返回数据管道执行成功标志或错误代码
	Case 1
		Return "传输成功"
	Case -1
		Return("管道不能打开")
	Case -3
		Return("目标表在目标数据库中已存在。")
	Case -4
		Return("源数据库中不存在选定表。")
	Case -2
		Return("列太多。")
	Case -5
		Return("联结错误。")
	Case -6
		Return("检索变量错误。")
	Case -7
		Return("列不匹配。")
	Case -8
		Return("源中有致命的SQL错误。")
	Case -9
		Return("目标中有致命的SQL错误。")
	Case -10
		Return("超出了最大的错误数。")
	Case -12
		Return("表语法错误。")
	Case -13
		Return("没有提供必须的主键。")
	Case -15
		Return("管道操作已经进行。")
	Case -16
		Return("源数据库中有错误。")
	Case -17
		Return("目标数据库中有错误。")
	Case -18
		Return("目标数据库是只读的。")
	Case Else
		Return("未知错误")
End Choose




end function

核心思路就是通过datastore动态获取表结构,然后动态生成数据管道的syntax,其中有一个问题由于才疏学浅暂未找到办法,就是如何获取column的null属性,暂时处理方案是在数据管道拼接syntax是把nulls_allowed属性全设为yes了,以免空字段无法插入问题

后续再补充完善,记录一下,以备后用!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值