290 likes | 455 Views
源数据库. 目标数据库. 数据管道. 图 15-1 数据管道的工作过程. 第 15 章 数据管道. 数据管道提供了在数据库内部、数据库之间,甚至不同的数据库管理系统之间快速复制数据的简便途径。 数据管道既可以在开发环境下,通过工具栏的数据库画板完成相应的操作,也可以在程序中通过编写代码使用数据管道,这种方式提供了灵活运用数据管道的手段。. 第 15 章 数据管道. 15.1 创建数据管道 15.2 数据管道对象的属性、事件和函数 15.3 数据管道编程实例. 图 15-2 选择 Data Pipeline 创建数据管道.
E N D
源数据库 目标数据库 数据管道 图15-1数据管道的工作过程 第15章数据管道 数据管道提供了在数据库内部、数据库之间,甚至不同的数据库管理系统之间快速复制数据的简便途径。 数据管道既可以在开发环境下,通过工具栏的数据库画板完成相应的操作,也可以在程序中通过编写代码使用数据管道,这种方式提供了灵活运用数据管道的手段。
第15章数据管道 15.1 创建数据管道 15.2 数据管道对象的属性、事件和函数 15.3 数据管道编程实例
图15-2选择Data Pipeline创建数据管道 15.1.1 在数据库画板中创建数据管道 进入数据库画板,在已连接的数据库中选择要复制的表,点击鼠标右键,出现一个弹出式菜单。
图15-3定义数据管道 15.1.1 在数据库画板中创建数据管道 选择Data Pipeline,开始创建数据管道。
图15-4 Pipeline工具栏 15.1.1 在数据库画板中创建数据管道 在图15-3中,有一个Pipeline工具栏,如图15-4所示。其含义见表15-1。 表15-1工具栏图标
15.1.1 在数据库画板中创建数据管道 查看和更改源数据库与目标数据库,可以通过主菜单File的子菜单SourceConnect和DestinationConnect进行。编辑SQL数据源类似于设计数据窗口对象的Data Source,可以定义检索参数Retrieval Arguments和Where条件等,使得满足条件的数据才被复制。 在图15-3定义数据管道中,各选择项的含义见表15-2。 注意:当源表中已有数据时,更改目标表的列的类型与宽度应小心。宽度变小可能丢失数据,改变列的类型可能导致类型转换错误。
15.1.1 在数据库画板中创建数据管道 表15-2定义数据管道的各选择项的含义
图15-5保存数据管道 15.1.1 在数据库画板中创建数据管道 数据管道定义后,可以立即执行数据管道。选择工具栏图标,将立即执行数据管道操作。还可以保存数据管道,以便再次使用或在编程中使用数据管道。在图15-3中,选择保存,在Data Pipeline中输入数据管道名,然后点击OK按钮。数据管道的命名一般用“p_”作前缀。
图15-6创建数据管道对象 15.1.2 创建数据管道对象 在主窗口的工具栏选择New,点击Database页。
图15-7选择源数据库和目标数据库 15.1.2 创建数据管道对象 选择Data Pipeline,出现标题为New Data Pipeline的窗口,选择数据源DataSource、源数据库和目标数据库。
图15-8选择列 15.1.2 创建数据管道对象 若数据源DataSource选QuickSelect,则源表只能选择一个,选择要复制的列。点OK按钮,出现图15-3。
1.选择目标 4.选择要打开的数据管道 2.选择pbl源文件 3.在ObjectType中选择Pipelines或All Objects 图15-9 打开数据管道 15.1.3 打开和修改数据管道 保存数据管道后,再次打开和修改。在主窗口的工具栏选择Open,在对象类型ObjectType中选择Pipelines,在对象 Object中 选择要打 开的数据 管道。 点击OK按钮,出现前面已讲的界面。
图15-10 删除数据管道 15.1.4 删除数据管道 打开Library库管理器,打开要删除的数据管道所在的PBL,选择要删除的数据管道,右击,出现弹出式菜单,选择Delete将删除所选的数据管道。
15.2.1数据管道属性 数据管道对象的属性共有六个,反映了当前使用的数据管道对象、语法、数据管道运行情况等信息。 其中: lDataObject属性的数据类型为String,用于保存数据管道对象名(在数据库画板中创建的对象),其作用与数据窗口控件的同名属性的作用十分相似,该属性指定与数据管道对象相关联的数据管道对象名,与数据窗口控件不同,数据管道用户对象的DataObject属性只能在代码中设置。 lRowsInError的数据类型为Long,它指示数据管道运行过程中发现的错误个数(比如存在键值重复的行等)。 lRowsRead的数据类型为Long,它指示数据管道运行过程中当前已经读取的行数。 lRowsWritten的数据类型为Long,它指示数据管道运行过程中当前已经写入的行数。 lRowsInError、RowsRead和RowsWritten属性提供数据管道运行过程中的状态信息。这些属性通常显示在应用程序的窗口中,让用户了解数据管道的执行进程。 l Syntax属性的数据类型为String,保存用于创建数据管道对象的语法(在数据管道画板中创建的对象)。利用字符串操作函数(如Mid()、Pos()、Len()),可以动态修改数据管道对象语法。
15.2.2数据管道事件 数据管道有五个预定义事件,在创建数据管道用户对象时,可以根据应用程序的需要定义自己的用户事件。预定义事件的为: lConstructor:在数据管道用户对象创建时触发。 lDestructor:在数据管道用户对象删除时触发。 • lPipeStart:开始执行Start()或Repair()函数时触发。 • lPipeMeter:每次读或写一块数据时触发,设计数据管道对象时定义的Commit参数的大小决定了块的大小。也就是说,数据管道每执行完一个数据库事务时都会触发PipeMeter事件。 • lPipeEnd:Start()或Repair()函数执行结束时触发。
15.2.3数据管道函数 Start()函数执行数据管道对象,将数据从源表按SQL SELECT语句指定的要求复制到目标表中。 格式:pipelineobject.Start ( sourcetrans, desttrans,errordw [, arg1, arg2, ..., argn]) 其中: • l pipelineobject是包含要被执行数据管道对象的数据管道用户对象名称。 • lsourcetrans是连接到源数据库的事务对象名,可以是缺省的事务对象SQLCA、也可以是应用程序创建的事务对象。 • ldesttrans是连接到目标数据库的事务对象名,可以是缺省的事务对象SQLCA、也可以是应用程序自己创建的事务对象。 • lerrordw是个数据窗口控件名,该控件用于显示数据管道运行过程中出现的错误。程序中无需把某个数据窗口对象关联到该控件上,系统会根据出现的数据管道错误自动生成所需的数据窗口对象。如果程序中已经在该控件上关联了某个数据窗口对象,运行时该对象将被数据管道创建的对象取代。 • larg1, arg2,..., argn是可选参数,对应于定义数据管道数据源时SELECT语句所需的检索参数。
15.2.3数据管道函数 Start()函数返回一个Integer值指示数据管道的运行是否成功,返回值的意义为: 1 函数执行成功 -1 打不开数据管道(如数据管道对象不存在) -2 列数太多 -3 要创建的表已经存在 -4 要增加数据的表不存在 -5 未建立与数据库的连接 -6 参数错误 -7 列不匹配 -8 访问源数据库的SQL语句致命错误 -9 访问目标数据库的SQL语句致命错误 -10 已经达到指定的最大错误数 -12 不正确的表语法 -13 需要关键字、但未指定关键字 -15 数据管道已经在运行 -16 源数据库出错 -17 目标数据库出错 -18 目标数据库处于只读状态,不能写入数据
15.2.3数据管道函数 1. Cancel()函数 在数据管道运行过程中,执行Cancel()函数后将终止数据管道的执行。 格式:pipelineobject.Cancel ( ) 该函数执行成功时返回1,失败时返回0。 2. Repair()函数 数据管道运行后,如果某些行不能传送到目标数据库,就产生了错误,出错的行显示在与数据管道对象相关联的数据窗口中,用户在数据窗口中修改了数据后,使用Repair()函数,将修改结果传送到目标数据库。 格式:pipelineobject.Repair ( desttrans ) 其中:pipelineobject是包含要被执行数据管道对象的数据管道用户对象名称。desttrans是连接到目标数据库的事务对象名。
15.2.3数据管道函数 Repair()函数的返回值: 1 函数执行成功 -5 未建立与数据库的连接 -6 参数错误 -9 访问目标数据库的SQL语句致命错误 -10 已经达到指定的最大错误数 -12 不正确的表语法 -15 数据管道已经在运行 -17 目标数据库出错 -18 目标数据库处于只读状态,不能写入数据
15.3数据管道编程实例 在程序中使用数据管道的基本步骤为: • 创建数据管道对象,如果不存在的话 • 定义Pipeline的标准类用户对象(或在代码中定义Pipeline对象实例) • 创建窗口,在窗口上放置一个数据窗口控件 • 编写代码 • 处理行错误 • 结束管道操作
图15-11数据管道应用实例 15.3数据管道编程实例 在该例中,先选择复制方向:是从服务器数据库下载数据到本地库,还是将本地库数据上传到服务器数据库以更新数据;然后选“开始”按钮,执行数据复制操作,在复制的过程中,可以点“取消”按钮,将取消正在进行的复制操作。复制操作的执行状况显示在数据窗口控件中,结果显示在三个静态文本框中。
15.3数据管道编程实例 步骤如下: (1)创建一个mypipe.pbl文件,其ApplicationObject名为pipedb。再创建窗口w_pipe,在w_pipe上,创建一个组框gb_1、两个单选按钮rb_down和rb_up、开始命令按钮cb_ok、取消命令按钮cb_cancel、返回命令按钮cb_return、静态文本框st_read、静态文本框st_written、静态文本框st_error、数据窗口控件dw_1。 (2)创建两个数据管道:p_student_ltos将本地数据库中的表student中的部分数据上传到服务器数据库中的表student以更新数据;p_student_stol将服务器数据库中的表student中的部分数据下载到本地数据库中的表student中。这两个数据管道都定义了string类型的检索参数str,并在编辑SQL数据源中加上条件“where student.class=:str”,表示仅处理指定的班级。 (3) 在窗口w_pipe中定义函数wf_connectlocaldb()表示连接本地数据库、wf_connectserverdb()表示连接服务器数据库、wf_error(integer ret)错误处理、wf_startpipe(Transaction sourcetrans,Transaction desttrans,string p_object)开始管道操作。
(4)编写代码 l在ApplicationObject对象pipedb的open事件中编写以下代码 open(w_pipe) l在窗口w_pipe中,声明以下InstanceVariables对象实例: //定义两个事务处理对象serverdb和localdb //serverdb用来连接服务器数据库 //localdb用来连接本地库 transaction serverdb,localdb //定义数据管道对象u_pipe pipeline u_pipe l在窗口w_pipe的open事件中编写代码: //定义事务处理对象实例变量localdb和serverdb serverdb=create transaction localdb=create transaction //定义数据管道对象实例变量 u_pipe=create pipeline l在窗口w_pipe的close事件中编写代码: //释放数据管道对象 destroy u_pipe; //释放事务处理对象 disconnect using localdb; destroy localdb; disconnect using serverdb; destroy serverdb; 15.3数据管道编程实例
l在“取消”命令按钮的clicked事件中编写代码:l在“取消”命令按钮的clicked事件中编写代码: int ret ret=u_pipe.Cancel() //终止管道运行 if ret=1 then messagebox("取消操作成功 ","终止管道运行") else messagebox("取消操作失败","未能终止管道运行") end if l在“返回”命令按钮cb_return的clicked事件中编写代码: close(parent) //关闭当前窗口 l在连接本地数据库的函数wf_connectlocaldb()中编写代码: //该函数无参数,返回值为sqlcode //连接本地库 localdb.autocommit=true localdb.DBMS = "odbc" localdb.database = "student" localdb.userid = "dba" localdb.dbpass = "sql" localdb.servername = "" localdb.logid="" localdb.logpass="" localdb.dbparm="connectstring= 'dsn=student;uid=dba;pwd=sql'" connect using localdb; return localdb.sqlcode 15.3数据管道编程实例
15.3数据管道编程实例 l在连接服务器数据库的函数wf_connectserverdb()中编写代码: //该函数无参数,返回值为sqlcode //连接服务器数据库 //这里为方便实验,选用了另一个本地库math serverdb.autocommit=true serverdb.DBMS = "odbc" serverdb.database = "math" serverdb.userid = "dba" serverdb.dbpass = "sql" serverdb.servername = "" serverdb.logid="" serverdb.logpass="" serverdb.dbparm = "connectstring='dsn=math;uid=dba;pwd=sql'" connect using serverdb; return serverdb.sqlcode
l在错误处理函数wf_error(integer ret)中编写代码: //该函数的入口参数ret,表示执行数据管道操作返回的错误代码。 //该函数无返回值。 string msg Choose Case ret Case -1 msg = "打不开数据管道" Case -2 msg = "列数太多" Case –3 msg = “要创建的表已经存在” Case -4 msg = "要增加数据的表不存在" Case -5 msg = "未建立与数据库的连接" Case –6 msg = "参数错误" Case –7 msg = "列不匹配" Case -8 msg = "访问源数据库的SQL语句致命错误" Case -9 msg = “访问目标数据库的SQL语 句 致命错误" Case -10 msg = “已经达到指定的最大错误数" Case –12 msg = "不正确的表语法" Case -13 msg = “需要关键字、但未指定关键 字" Case -15 msg = "数据管道已经在运行" Case –16 msg = "源数据库出错" Case –17 msg = "目标数据库出错" Case -18 msg = “目标数据库处于只读状态, 不能写入数据" End Choose MessageBox("数据管道运行出错", msg, StopSign!,ok!) 15.3数据管道编程实例
l在执行管道操作的函数wf_startpipe(Transaction sourcetrans,Transaction desttrans,string p_object)中编写代码: //该函数有三个入口参数sourcetrans、desttrans、p_object //该函数无返回值。 //参数sourcetrans表示源事务处理对象 //参数desttrans表示目标事务处理对象 //参数p_object表示在数据库画板中创建的数据管道对象 int ret //定义数据管道对象实例变量 u_pipe.DataObject = p_object //设置数据管道对象 ret=u_pipe.Start(sourcetrans, desttrans, w_pipe.dw_1,"996905") //这里带了参数"996905",是因为创建数据管道P_object时, //定义了检索参数,表示仅处理996905班级的数据 if ret<> 1 then wf_error(ret) //转错误处理程序 Else MessageBox("数据管道运行成功", "操作成功") end if st_read.text= String(u_pipe.RowsRead) //显示已读数据行数 st_written.text= String(u_pipe.RowsWritten) //显示已写数据行数 st_error.text= String(u_pipe.RowsInError) //显示出错数据行数 15.3数据管道编程实例
15.3数据管道编程实例 l在“开始”命令按钮cb_ok的clicked事件中编写代码: int ret ret=wf_connectserverdb() //连接服务器数据库 if ret<>0 then messagebox(“=====错误信息提示=====”,“不能连接服务器数据 库!~r~n请询问系统管理员",stopsign!) return end if ret=wf_connectlocaldb() //连接本地数据库 if ret<>0 then messagebox("=====错误信息提示=====","不能连接本地数据库!~r~n 请询问系统管理员",stopsign!) return end if if rb_down.checked then //选择从服务器数据库下载数据到本地库 wf_startpipe(serverdb,localdb,"p_student_stol") else //选择将本地库数据上传到服务器数据库以更新数据 wf_startpipe(localdb,serverdb,"p_student_ltos") end if