Kettle是一款国外开源的ETL工具,纯java编写,可以在Windows、Linux、Unix上运行,数据抽取高效稳定。本人用的版本是6.1。

之前用kettle这个开源的ETL工具是用来做数据抽取的,这次测试有个需求,是做数据库数据的比对。验证源表到目标表的逻辑正确,从而利用源表自己写SQL逻辑,生成的结果和目标表去比对。这次想到了利用kettle的数据比较功能,来做这些数据校验。

这个任务主要是读取输入参数CSV里面的每行数据,填充到SQL的参数里面,然后执行两个SQL的比对,最后统计测试结果。

下面来看每一步的操作:

【清空上次结果】

如图,右键节点可以打开对应的Transformation。

public boolean processRow(StepMetaInterface smi, StepDataInterface sdi) throws KettleException{String resultFoldPath = getParameter("resultPath");process(resultFoldPath);return false;}  public void process(String resultFoldPath) {//清空结果文件File tempFile = new File(resultFoldPath);File[] listFiles = tempFile.listFiles();for(int i=0;i<listFiles.length;i++){listFiles[i].delete();         }}

这是一个“Java代码”组件,主要清空指定目录的所有文件。

【读取数据】

利用“CSV文件输入”组件,读取username和rownum的字段值,可以读取多行。

【初始化变量】

这是任务里面的一个JS组件,用于把上一步骤里面读取到的数据通过previous_result.getRows()取出来,然后放到tables里面。注意这里放到tables里面以后格式变成了[[a1],[b1],[a2],[b2]]。Size是tables的总行数。这里的i是定义的循环行的index,初始值是0。最后我们把第一行的所有字段都取出来,放到同名的变量里面。

var prevRow = previous_result.getRows();if(prevRow == null ||(prevRow.size() == 0)){false;}else{parent_job.setVariable("tables",prevRow);//ArrayList存储表名变量,以数组形式保存入[[table1],[table2]]parent_job.setVariable("size",prevRow.size());//存储执行表的总数量parent_job.setVariable("i",0)//循环控制变量for(k=0;k<prevRow.get(0).size();k++){//获取每列的列名var name = prevRow.get(0).getRowMeta().getFieldNames()[k];//parent_job.setVariable("name",name); name变量可以输出到日志用于调试var value = prevRow.get(0).getString(k,"");//parent_job.setVariable("value",value); value变量可以输出到日志用于调试parent_job.setVariable(name,value);}true;}

网上给的例子一般都是写死的,比如给name变量赋值: parent_job.setVariable(“name”,value),但是本项目的参数是需要经常变化的,为了减少维护量,特意去查询了kettle的源码(源码地址:https://github.com/pentaho/pentaho-kettle,选择6.1版本下载)。这里getRows()返回的结果是org.pentaho.di.core.RowMetaAndData类型的数组,可以调用RowMetaAndData里的方法来取值或进行其他操作,这里仅取了列名和列值。

【循环控制器】

“循环控制器”实际是一个“校验字段值”组件,可以进行循环的条件是i<size,从而保证可以循环执行。

【执行SQL】

这里设置了两组比较。

读取源表数据的操作,这里在SQL里把需要替换的变量用${}加进来,“替换SQL语句里的变量”选项要打勾。同理读取目标表数据。

数据比对用的是“合并记录”的组件,匹配的关键字是指用于定位两个数据源中的同一条记录。数据字段是指对于两个数据源中的同一条记录中,指定需要比较的字段。最后生成的数据将包括旧数据来源和新数据来源里的所有数据,对于变化的数据,使用新数据代替旧数据,同时在结果里用一个标志字段,来指定新旧数据的比较结果。“identical” – 旧数据和新数据一样;“changed” – 数据发生了变化; “new” – 新数据中有而旧数据中没有的记录;“deleted” –旧数据中有而新数据中没有的记录。

同理再建一个反向的数据比对,把旧数据源和新数据源互换下。

最后把结果输出到文本文件,选择扩展名是CSV,输出的文件名中可以添加变量i或者其他的变量,最后的文件名是-{源表名}-{目标表名}-正/反,最后的正反的命名取决于正向比对还是反向比对。

要建正向和反向比对的原因是因为测试人员要求输出的结果必须包含有两张表的数据和结果,如果要重新写个组件花费的时间比较长,最终讨论以后采用折中的策略,通过多加一步比对来实现。

【条件变化】

var prevRow=previous_result.getRows();var list = parent_job.getVariable("tables").replace("[","").replace("]","").split(",");var size = new Number(parent_job.getVariable("size"));var i = new Number(parent_job.getVariable("i"))+1;if(i<size){var length = prevRow.get(0).size();//列宽for(k=0;k<length;k++){var name = prevRow.get(i).getRowMeta().getFieldNames()[k];//parent_job.setVariable("name",name);var value = list[length*i+k].replace(" ","");//parent_job.setVariable("value",value);parent_job.setVariable(name,value);   }}parent_job.setVariable("i",i);true;

这个操作是当一次执行完成后,要跳到下一个执行的操作。索引i要加1。获取下一行的数据,网上很多给的例子都是用prevRow.get(i)来获取下一行,但是在实际用的时候发现每次获取的都是第一行,想了很多办法,最后还是通过处理tables来获取下一行,用parent_job.getVariable("tables").replace("[","").replace("]","").split(",")将其转化成数组,然后通过list[length*i+k].replace(" ","")来获取下一行的每个列值。

【统计测试结果】

统计测试结果也是一个“Java代码”组件,这里吐槽下,直接把代码贴到文本框里面是有问题的,像List、JSON等一些复杂结构是无法支持的,因此在发现IDE里面的可正确运行的代码在kettle报错以后,就采用了Jar插件的方法。把java代码导出为Jar放入到kettle的lib文件夹下,然后重启spoon,这样就可以import外部类了。

最后生成的结果如上图所示。

上图是每个详细结果文件和测试结果汇总文件。

有兴趣的可以下载本人的DEMO,包含ktr、job、jar文件。

利用kettle进行数据库数据比对相关推荐

  1. kettle使用数据库来生成序列_Kettle的安装和使用

    Kettle简介 Kettle是一款国外开源的ETL工具,纯java编写,可以在Window.Linux.Unix上运行,数据抽取高效稳定. Kettle是"Kettle E.T.T.L. ...

  2. 利用kettle获取企业微信打卡数据

    利用kettle创建转换,把转换根据顺序执行,生成作业,通过计划任务定时执行作业,把企业微信的打卡记录插入到本地数据库中. 一.先获取打卡应用和通讯录的access_token,由于access_to ...

  3. 利用SQl对数据库实行数据拆分与组合

    利用SQl对数据库实行数据拆分与组合实现提供以下几种方案: 方法一: WITH CTE AS ( SELECT A.Id,A.[Uid],UserName FROM ( SELECT A.[id], ...

  4. 成功解决:利用编程向数据库插入一条记录,而从数据库中查不到该条记录

    成功解决:利用编程向数据库插入一条记录,而从数据库中查不到该条记录 目录 解决问题 解决方法 1.首先查看是否有conn.commit() 2.继续判断 解决问题 利用编程向数据库插入一条记录,而从数 ...

  5. 安卓案例:利用SQLiteOpenHelper操作数据库及表

    安卓案例:利用SQLiteOpenHelper操作数据库及表 一.运行效果 二.涉及知识点 1.利用SQLiteOpenHelper类创建与升级数据库 这个类是一个抽象类,我们必须继承该类创建一个子类 ...

  6. [原创]利用Powerdesinger同步数据库的方法说明

    本文主要介绍我在工作过程中如果利用PowerDesinger同步数据库设计PDM和物理数据库保持同步.PowerDesinger以下简称PD.我们经常在数据库生成后,在后续的开发中发现数据设计有遗漏, ...

  7. 数据库创建(利用写好的数据库表生成创建表的sql语句+利用生成的数据库创建表加同步数据sql)

    一.利用写好的数据库表生成创建表的sql语句 1.简单创建一个数据库,并建一个表,并编辑数据. a.建库 b.建表 c.编辑表,保存时输入表名 d.刷新一下,出来了 e.转存导出sql文件. 二.利用 ...

  8. 安卓案例:利用SQLiteDatabase操作数据库与表

    安卓案例:利用SQLiteDatabase操作数据库与表 一.SQLite简介 SQLite是D. Richard Hipp用 C语言编写 的开源嵌入式数据库引擎.它支持大多数的SQL92标准,并且可 ...

  9. ogg初始化mysql数据_利用OGG进行数据库表的初始化

    利用OGG进行数据库表的初始化 前提是已经搭建好了OGG的运行环境和OGG程序的安装部署!!! 若不知道如何安装OGG请查阅博客中相关安装部署文档. 1.停止目标端replicat进程re1 2.配置 ...

最新文章

  1. enumeration学习
  2. hdu5489(2015合肥网络赛F题)
  3. mel滤波器组频率响应曲线_非常好的滤波器知识总结,值得一看!
  4. #!/usr/bin/env python与#!/usr/bin/python
  5. 20. 利用Veeam ONE监控vSphere虚拟化平台(Veeam ONE安装及配置)
  6. AC自动机——多个kmp匹配
  7. 求两字符串最长公共连续子串---C++编程
  8. 《Java并发编程的艺术》第3章 Java内存模型
  9. html 显示接口数据格式化,科技常识:html格式化输出JSON示例(测试接口)
  10. # C语言程序设计第二次作业——顺序结构
  11. Visio简单画图使用方法
  12. matlab双闭环绘图,matlab双闭环直流调速系统设计及仿真+电路图
  13. 计算机实验室安全知识心得体会,实验室安全知识宣传
  14. 安卓开发者模式中将最小dp调得太高导致无法开机的解决方法
  15. X1000对于camera控制部分的翻译
  16. 数据分析报告怎么写?这5个步骤你必须了解
  17. 有监督学习-逻辑回归sklearn应用举例
  18. 电脑管家软件搬家没有历史记录
  19. Android 硬件传感器
  20. 精华QT安装:qt-opensource-windows-x86-5.14.1

热门文章

  1. Markdown学习笔记,推荐stackedit编辑器
  2. 为什么服务器选择Linux而不用Windows
  3. Python批量爬取简历模板
  4. js小数 取整 取余
  5. 浓缩就是精华-SIGAI机器学习蓝宝书
  6. centos pureftpd mysql,CentOS 搭建 Pure-FTP
  7. css动画无限循环转圈,css3 – 具有无限循环的链CSS动画
  8. 大数据之Presto
  9. LabVIEW通过MC协议实现与三菱FX 3U系列PLC的通讯(TCP)
  10. 【图像处理】基于贝叶斯的Lucy-Richardson图像复原算法