利用kettle的JS進行ETL數(shù)據(jù)校驗(升級版)

無意中在網(wǎng)上看到一篇文章《利用kettle中的JS來完成ETL數(shù)據(jù)校驗》,挺受啟發(fā)的,覺得用JS來實現(xiàn)ETL的自動化校驗,是個不錯的思路。但是這篇文章里給的JS腳本樣例確實有待改進,一是讓初學(xué)者看著不那么清晰,二是擴展性和維護性都較差。于是我做了二次改造,重新編寫了腳本,如下:

//Script here

var strConn = "TestOrcl";

var check_status=0;//如果檢測到有任何一種校驗錯誤,則check_status=1

var check_table="E_OT_PRMTALT";//校驗有關(guān)的表名字

var check_table_id="LICALTID";//校驗表主鍵

var check_name=LICALTID;//校驗表主鍵值

var check_detail="";//校驗到的錯誤詳細情況

var check_type="";//校驗到的錯誤類型

var check_date=new Date();//校驗時間

var source_table="E_OT_PRMTALT";//數(shù)據(jù)源表名稱,如果數(shù)據(jù)來自多個數(shù)據(jù)表,則需要聲明多個

var source_table_id="LICALTID";//數(shù)據(jù)源表主鍵,如果多個表聯(lián)合主鍵,則需要聲明多個主鍵

/////////////////////////////字段唯一性校驗//////////////////////////////////////////

var isuniqueArray=new Array("LICALTID","LICID");//一維數(shù)組,表的字段名

var isunique_str="";

var isunique_column="";

for(var i=0;i<isuniqueArray.length;i++){

//1:唯一性枚舉值

? isunique_str+="var "+isuniqueArray[i]+"_isunique=0;";

? //唯一性校驗枚舉值賦值

? isunique_str+="var uniquesql_"+isuniqueArray[i]+"=\"SELECT count(1) FROM "+check_table+" where "+isuniqueArray[i]+"='\"+"+isuniqueArray[i]+"+\"' \";";

? isunique_str+="if(fireToDB(strConn,uniquesql_"+isuniqueArray[i]+")[0][0]==1){"+isuniqueArray[i]+"_isunique=1;}";

? //校驗所有表需要校驗的字段,如果有一個校驗失敗,則校驗狀態(tài)為1

? isunique_str+="if(check_status==0){if("+isuniqueArray[i]+"_isunique==0)check_status=1;}";

? //check is unique? return not unique column

? isunique_str+="if("+isuniqueArray[i]+"_isunique==0){if(isunique_column==\"\"){ isunique_column = \""+ isuniqueArray[i] +"\";}else{isunique_column+=\"、\"+\""+isuniqueArray[i]+"\";}}";?

}

//最終輸出的錯誤詳細情況

isunique_str+="if(check_status==1){check_type=\"違反唯一規(guī)則\";check_detail=\"表\"+source_table+\"中,字段\"+isunique_column+\"違反了唯一規(guī)則\";}";

eval(isunique_str);

//////////////////////////////////////////////////////////////////////////////////

/////////////////////////////字段非空校驗//////////////////////////////////////////

var isnullArray=new Array("ALT","ALTBE","ALTAF","ALTDATE");//一維數(shù)組,表的字段名

var isnull_str="";

var isnull_column="";

check_status=0;//校驗狀態(tài)置0

for(var i=0;i<isnullArray.length;i++){

//2:非空枚舉值

isnull_str+="var "+isnullArray[i]+"_isnull=0;";

//非空校驗枚舉值賦值

isnull_str+="if("+isnullArray[i]+"==null||"+isnullArray[i]+"==\"\"){"+isnullArray[i]+"_isnull=1;}";

//校驗所有表需要校驗的字段,如果有一個校驗失敗,則校驗狀態(tài)為1

isnull_str+="if(check_status==0){if("+isnullArray[i]+"_isnull==1)check_status=1;}";

//check is null? return null column

isnull_str += "if("+isnullArray[i]+"_isnull==1){if(isnull_column==\"\"){isnull_column = \""+ isnullArray[i] +"\";}else{isnull_column+=\"、\"+\""+isnullArray[i]+"\";}}";

}

//最終輸出的錯誤詳細情況

isnull_str+="if(check_status==1){if(check_detail==\"\"){check_type=\"違反非空規(guī)則\";check_detail=\"字段\"+ isnull_column +\"違反了非空規(guī)則\";}else{check_type+=\",\"+\"違反非空規(guī)則\";check_detail+=\",字段\"+ isnull_column +\"違反了非空規(guī)則\";}}";

eval(isnull_str);

//////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////標準值校驗//////////////////////////////////////////

var isnormalArray = [["S_EXT_FROMNODE","in ('220000')"],["ALT","in ('許可文件編號','許可文件名稱','許可機關(guān)','許可內(nèi)容')"]];//二維數(shù)組,第一列為字段,第二列為匹配規(guī)則

var isnormal_str="";

var isnormal_column="";

check_status=0;//校驗狀態(tài)置0

for(var i=0;i<isnormalArray.length;i++){

//3:標準化枚舉值

isnormal_str+="var "+isnormalArray[i][0]+"_isnormal=0;";

//標準化校驗枚舉值賦值

isnormal_str+="var normalsql_"+isnormalArray[i][0]+"= \"select? count(1) from "+check_table+" where "+ isnormalArray[i][0] +" "+isnormalArray[i][1]+" and "+check_table_id+"='"+check_name+"'\";";

isnormal_str+="if(fireToDB(strConn, normalsql_"+isnormalArray[i][0]+")[0][0]>0){"+ isnormalArray[i][0] +"_isnormal=1;}";

//校驗所有表需要校驗的字段,如果有一個校驗失敗,則校驗狀態(tài)為1

isnormal_str+="if(check_status==0){if("+isnormalArray[i][0]+"_isnormal==0) check_status=1;}";

//check is normal? return not normal column

isnormal_str+="if("+isnormalArray[i][0]+"_isnormal==0){if(isnormal_column==\"\"){ isnormal_column = \""+ isnormalArray[i][0] +"\";}else{isnormal_column+=\"、\"+\""+isnormalArray[i][0]+"\";}}";

}

//最終輸出的錯誤詳細情況

isnormal_str+="if(check_status==1){if(check_detail==\"\"){check_type=\"違反標準化規(guī)則\";check_detail=\"字段\"+ isnormal_column +\"違反了標準化規(guī)則\";}else{check_type+=\",\"+\"違反標準化規(guī)則\";check_detail+=\",字段\"+ isnormal_column +\"違反了標準化規(guī)則\";}}";

eval(isnormal_str);

//////////////////////////////數(shù)據(jù)類型校驗//////////////////////////////////////////

var datatypeArray = [["ALTDATE","isDate"],["ALTAF","isNum"]];//二維數(shù)組,第一列為要校驗的數(shù)據(jù)字段,第二列為數(shù)據(jù)類型校驗函數(shù)(isDate[日期]、isNum[數(shù)字]、isMailValid[郵箱]、isEmpty[空])

var datatype_str="";

var datatype_column="";

check_status=0;//校驗狀態(tài)置0

for(var i=0;i<datatypeArray.length;i++){

//4:類型校驗枚舉值

datatype_str+="var "+datatypeArray[i][0]+"_datatype=0;";

//數(shù)據(jù)類型校驗枚舉值賦值

datatype_str+="var datatypesql_"+datatypeArray[i][0]+"=\"select "+datatypeArray[i][0]+" from "+ check_table +" where "+check_table_id+"='"+check_name+"'\";";

datatype_str+="if("+datatypeArray[i][1]+"(fireToDB(strConn,datatypesql_"+datatypeArray[i][0]+")[0][0])) "+ datatypeArray[i][0]+"_datatype=1;";

//校驗所有需要校驗的字段,如果有一個校驗失敗,則校驗狀態(tài)為1

datatype_str+="if(check_status==0){if("+datatypeArray[i][0]+"_datatype==0) check_status=1;}";

//check is datatype? return not datatype column

datatype_str+="if("+datatypeArray[i][0]+"_datatype==0){if(datatype_column==\"\"){ datatype_column =\""+datatypeArray[i][0]+"\";}else{datatype_column+=\"、"+datatypeArray[i][0]+"\";}}";

}

//最終輸出的錯誤詳細情況

datatype_str+="if(check_status==1){if(check_detail==\"\"){check_type=\"違反數(shù)據(jù)類型規(guī)則\";check_detail=\"字段\"+datatype_column+\"違反數(shù)據(jù)類型規(guī)則\";}else{check_type+=\",\"+\"違反數(shù)據(jù)類型規(guī)則\";check_detail+=\",字段\"+datatype_column+\"違反數(shù)據(jù)類型規(guī)則\";}}";

eval(datatype_str);

//////////////////////////////////////////////////////////////////////////////////////

if(check_detail!="")

{

check_detail=check_detail+","+source_table_id+"="+check_name;

}

以下是執(zhí)行后的效果:

在此基礎(chǔ)上我們還可以擴展更多的校驗,比如通過正則表達式的方式(利用kettle的isRegExp函數(shù)),如下:

//////////////////////////////正則表達式校驗//////////////////////////////////////////

var dataArray = [["Email","^\\w+@[a-zA-Z_]+?\\.[a-zA-Z]{2,3}$","^[\\w-\.]+@([\\w-]+\\.)+[\\w-]{2,4}$"]];//二維數(shù)組,第一列為要校驗的數(shù)據(jù)字段,第二列為規(guī)則1,第三列為規(guī)則2(可選)

var data_str="";

var data_column="";

check_status=0;//校驗狀態(tài)置0

for(var i=0;i

//4:類型校驗枚舉值

data_str+="var "+dataArray[i][0]+"_data=0;";

//數(shù)據(jù)類型校驗枚舉值賦值

data_str+="var datasql_"+dataArray[i][0]+"=\"select "+dataArray[i][0]+" from "+check_table+" where "+ check_table_id +"='"+check_name+"'\";";

data_str+="if(isRegExp(fireToDB(strConn,datasql_"+dataArray[i][0]+")[0][0],dataArray[i][1],dataArray[i][2] )>-1) "+dataArray[i][0]+"_data=1;";

//校驗所有需要校驗的字段,如果有一個校驗失敗,則校驗狀態(tài)為1

data_str+="if(check_status==0){if("+dataArray[i][0]+"_data==0) check_status=1;}";

//check is data? return not data column

data_str+="if("+dataArray[i][0]+"_data==0){if(data_column==\"\"){data_column=\""+ dataArray[i][0] + "\"; } else {data_column+=\"、"+dataArray[i][0]+"\";}}";

}

//最終輸出的錯誤詳細情況

data_str+="if(check_status==1){if(check_detail==\"\"){check_type=\"違反數(shù)據(jù)類型規(guī)則\";check_detail=\"字段\"+ data_column +\"違反數(shù)據(jù)類型規(guī)則\";}else{check_type+=\",\"+\"違反數(shù)據(jù)類型規(guī)則\";check_detail+=\",字段\"+ data_column + \"違反數(shù)據(jù)類型規(guī)則\";}}";eval(data_str);

以上腳本的好處就是,可以直接通過修改變量,就能對不同輸出表的不同字段進行校驗,基本上不用修改邏輯代碼,如果進一步優(yōu)化一下,就可以寫成函數(shù),直接調(diào)用。可以把檢驗字段和檢驗規(guī)則進一步參數(shù)化,通過調(diào)用參數(shù)表,來執(zhí)行數(shù)據(jù)驅(qū)動的校驗測試(這就是一種自動化測試的思路)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容