#!/usr/bin/perl
###############################################################################
# 规则检查主要包括以下步骤:
#1.查询出所有的规则组,进行第一次循环
# 2.查询当前规则组下的所有规则(一般都是针对同一个字段),循环每一个规则,从中提取规则sql
# 3.一组规则的每个规则都会在前一个规则的执行基础之上计算通过率,
# 有效检查记录总数,计算的粒度细分到机构,规则编号
#说明:
#调用形式 :
#perl ruleCheck-concurrent.pl DQC_BHYWXXB#BHQSRQ_20160601.dir(单个字段)
#perl ruleCheck-concurrent.pl DQC_BHYWXXB#XDHTH-CJRQ_20160601.dir(多个字段)
#执行数据库环境:DB210.5 DPF
# Writer : zengst
# Version : 2.0
###############################################################################
use strict;#对语法做严格限制,如变量必须先用my声明
use DBI;
use Time::Local;
my $dbh;#与数据库的连接
my $AUTO_HOME = $ENV{"AUTO_HOME"};
#通过ETL的加密方式得到登录信息
my $LOGON_DB2_FILE=$ENV{"LOAD_LOGON_DB2_FILE"};
my $DB2LOGON_FILE = "${AUTO_HOME}/etc/${LOGON_DB2_FILE}";
my $ODBCDriver = "AHNXODS64";
my $LOGONSTR;
my $DB2user;
my $DB2pwd;
my $RUN_DATE;#质量检测日期
my $Topic_Area;#检查的专题
my $Sys_Id;#检查的系统id
my $Map_Id;#规则组id
my $table_Name;#检查的表名
my $Check_Column_Name;#检查的字段名称,一个规则组,检测一个字段
my $PK_Column_Name;#检查的表的主键字段
my $Org_Column_Name;#机构字段名称,注意不是值,因为检查的业务系统的机构字段可能不一致
my $Rule_Name;#规则说明,即检查的是什么
my $checkID; #检查编号
my $SQLClause;#当前规则检查的sql
my $Rule_Info;#规则信息
my $Rule_Group;#规则组信息
my $whereClause;
my $modifydate;
my $CheckDimension;#规则维度
my $CheckSegmentation;
my $logFile;
my $RuleTable='EASTDQM.Rule';#规则信息表
my $RuleGroupTable='EASTDQM.RuleGroup';#规则组信息表
my $check_Result = 'EASTDQM.Check_Result';#轻度结果汇总表
my $check_detail='EASTDQM.Check_Result_Detail';#检查结果明细表
my $check_detail_sample = 'EASTDQM.check_detail_sample';
#日志文件目录
#一个大于号,表示覆盖原有文件的内容
#两个大于号表示在原有文件内容之后添加
#@日志文件因为并发,可能发生读写冲突,最好加上表名和字段名的区分,即规则组的粒度
# 判断是否有信号文件信息
if ( $#ARGV < 0 ) {
print "\n";
print "Usage: ****.pl CONTROL_FILE \n";
print "Usage: Use parameters \n";
print "CONTROL_FILE -- SYS_JOBNAME_YYYYMMDD.dir \n";
exit(1);
}
my $job_params = $ARGV[0]; #传入的参数
my $tableName="";#参数中的表名
my $column="";#参数中的字段名
my $TX_DATE=substr($job_params,length($job_params)-12,8);#业务数据日期
my $_date = substr($TX_DATE,0,4)."-".substr($TX_DATE,4,2)."-".substr($TX_DATE,6,2);
#my $TX_DATE="20160621";#数据日期
my $jobName = substr($job_params,4,length($job_params)-17);
sub getTableAndColumn{
if($jobName =~ /#/){
my @job_split = split("#",$jobName);
$tableName = @job_split[0];
#可能有多个列,列之间通过中杠分割
$column = @job_split[1];
if(split("-",$column)){
my @columnArr = split("-",$column);
my $columnLength = $#columnArr;
foreach my $k(0..$columnLength){
if($k eq 0){
$column = @columnArr[$k];
}else{
$column = $column.','.@columnArr[$k];
}
}
}
}
else{
print "The para format is wrong\n";
return 0;
}
}
sub getDB2LogonStr{
#定义文件的句柄
my $LOGONFILEREF;
#打开文件
open($LOGONFILEREF, "${DB2LOGON_FILE}");
my $LOGONSTR = <$LOGONFILEREF>;
close(LOGONFILEREF);
$LOGONSTR = `${AUTO_HOME}/bin/IceCode.exe "$LOGONSTR"`;
my ($UserID, $UserPwd) = split(' ',$LOGONSTR);
chop($UserPwd);
($DB2user,$DB2pwd) = split(',' , $UserPwd);
}
#初始化数据库的连接信息
sub DBconnect{
getDB2LogonStr();
$dbh = DBI->connect("dbi:ODBC:${ODBCDriver}","$DB2user","$DB2pwd",{RaiseError => 1, AutoCommit => 0 })
|| die "Couldn't connect to database: ".DBI->errstr;
print (GetNowTime()." get DB2 connection success! \n ");
return $dbh;
}
#得到规则组信息。因为每一个规则组里面的规则需要进行单独的
#权重评分,一次性搜索全部的规则时处理逻辑会相当复杂
sub getRuleGroupInfo{
#得到所有正在运行的规则组
getTableAndColumn();
my $runFreq =isRunCondition();
#根据表名+字段名的粒度筛选规则组,并发时并发度做到一定程度的最大化
my $groupInfoSQL = "select Map_Id,Topic_Area from ${RuleGroupTable} where Status= 1 and freq_flag in($runFreq) and table_name='$tableName' and check_column_name='$column' order by Map_Id";
#my $groupInfoSQL = "select Map_Id,Topic_Area from ${RuleGroupTable} where Status= 1 and freq_flag in('01') and table_name='dacorpinfo' and check_column_name='basicbankname' order by Map_Id";
#my $groupInfoSQL = "select Map_Id,Topic_Area from ${RuleGroupTable} where Status= 1 and table_name not in('CZXX','GRDQCKFHZ','GRHQCKFHZMXJL','GRJCXX','JJKXX','JYLS','NBFHZMXJL') AND MAP_ID NOT IN(SELECT MAP_ID FROM $check_Result group by map_id) order by Map_Id";
my $sth = $dbh->prepare($groupInfoSQL) or return -1;
my $ret = $sth->execute() or return -1;
${Rule_Group} = $sth->fetchall_arrayref();
$sth->finish();
return ${Rule_Group};
}
#得到数据库配置表的信息
sub getRuleInfo{
my ($groupId)=@_;#参数传入规则组Map_id
#一个规则组下有多个规则,rule_prior小的先执行
my $ruleConfigSql =
"select check_id,Topic_Area,r.sys_id,r.table_Name,r.Check_Column_Name,".
"r.PK_Column_Name,r.Org_Column_Name,rule_name,modifydate,r.SQLClause,map_id,WhereClause,CHECKDIMENSION ".
"from ${RuleTable} r".
" where r.status='1' and map_id=$groupId ".
" order by Rule_Prior asc";
my $sth = $dbh->prepare($ruleConfigSql) or return -1;
my $ret = $sth->execute() or return -1;
${Rule_Info} = $sth->fetchall_arrayref();
$sth->finish();
return 0;
}
#执行规则SQL
sub exeRuleSql{
#存储已经排好序的待执行的规则sql
my @exeCheckSql=();
for my $i(0..$#${Rule_Info}){
$checkID=${Rule_Info}->[$i]->[0]; #检查编号
print (GetNowTime()." Begin To Run Rule[$i]:$checkID \n");
$Topic_Area = ${Rule_Info}->[$i]->[1];#Rule_Info是一个二维数组,${Rule_Info}->[$i]表示是第i行
$Sys_Id=${Rule_Info}->[$i]->[2];
$table_Name=${Rule_Info}->[$i]->[3];
$Check_Column_Name=${Rule_Info}->[$i]->[4];
$PK_Column_Name=${Rule_Info}->[$i]->[5];
$Org_Column_Name=${Rule_Info}->[$i]->[6];
$Rule_Name=${Rule_Info}->[$i]->[7];
$modifydate=${Rule_Info}->[$i]->[8];
$SQLClause=${Rule_Info}->[$i]->[9];
$SQLClause =~ s/(\$[\w_]+)/eval $1/ge;
$SQLClause =~ s/(\$\{[^\}]+\})/eval $1/ge;
$Map_Id=${Rule_Info}->[$i]->[10];
$whereClause = ${Rule_Info}->[$i]->[11];
$CheckDimension = ${Rule_Info}->[$i]->[12];
push(@exeCheckSql,$SQLClause);
#为了防止多次执行,需要删除轻度汇总表和和检查明细表
#运行时要删除全部的机构数据
print (GetNowTime() . " **************************Clear The Result Table:**************************\n");
my $DelSql = "Delete From ${check_Result} Where Check_ID = ${checkID} and rundate='${_date}'";
my $sth = $dbh->prepare($DelSql) or return -1;
#返回影响的行数,select也可以影响行数
my $ret = $sth->execute() or return -1;
$sth->finish();
print (GetNowTime() . " **************************Clear The Result Table:Succeed[Rows:$ret] **************************\n");
print (GetNowTime() . " **************************Clear The Detail Table:**************************\n");
my $DelSql = "Delete From ${check_detail} Where Check_ID = ${checkID} and RUNDATE='${_date}'";
$sth = $dbh->prepare($DelSql) or return -1;
#返回影响的行数,也包括select语句
$ret = $sth->execute() or return -1;
$sth->finish();#释放结果集
print (GetNowTime() . " **************************Clear The Detail Table:Succeed[Rows:$ret]**************************\n");
#字符串的相等是eq,第一次执行的规则的记录总数是待检测表的记录总数
if($i==0){
my $fromposi = index($SQLClause,'FROM');
my $fromclause = substr($SQLClause,$fromposi+4);
#主键字段是多列,这里将它拼成一列
my $pkselect = '';
my @PKcon = split(",",$PK_Column_Name);
my $PKlen = $#PKcon;#获得数组的下标,数组为空时,返回-1
if($PKlen eq 0){
$pkselect = $PK_Column_Name;
}else{
foreach my $k(0..$PKlen){
if($k eq 0){
$pkselect = @PKcon[$k];
}else{
$pkselect = $pkselect.'||'.'\'#\''.'||'.(@PKcon[$k]);
}
}
}
#对检查的字段是多列情况的处理,将多列的数据拼接成一列
my $ckselect= '';
my @CKcon = split(",",$Check_Column_Name);
my $CKlen = $#CKcon;
if($CKlen eq 0){
$ckselect = $Check_Column_Name;
}else{
foreach my $k(0..$CKlen){
if($k eq 0){
$ckselect = @CKcon[$k];
}else{
$ckselect = $ckselect.'||'.'\'#\''.'||'.(@CKcon[$k]);
}
}
}
my $now1 = time;
print (GetNowTime() ." ************************** insert into detail begin **************************\n");
#将规则sql的检查结果插入detail表,因为最终需要进行轻度汇总
my $detailinsertSql = "Insert Into ${check_detail}" .
" select ${checkID},'${_date}', ${Map_Id}," .
" '${Topic_Area}','${Sys_Id}','${table_Name}','${Check_Column_Name}','${CheckDimension}','${CheckSegmentation}',".
" ${pkselect},${Org_Column_Name},${ckselect} from ".$fromclause;
my $detailsth = $dbh->prepare($detailinsertSql) or return -1;
$detailsth->execute() or return -1;
$detailsth->finish();
print (GetNowTime() ." ************************** insert into detail end **************************\n");
print (GetNowTime() ." ************************** insert into sample data begin **************************\n");
#从全量表按照规则、机构和运行日期的维度取得样本数据,插入到样例表
#partition by 可以是多个字段
my $sampInsert = "insert into ${check_detail_sample}".
" select ${checkID},'${_date}',${Map_Id},'${Topic_Area}','${Sys_Id}','${table_Name}','${Check_Column_Name}',".
"'${CheckDimension}','${CheckSegmentation}',pk_column_value,org_id,check_column_value from ".
"(select crt.*,ROW_NUMBER() over( partition by org_id,check_id) as seq from ${check_detail} crt where rundate='${_date}') detailtmp ".
" where detailtmp.seq<6";
my $inssth = $dbh->prepare($sampInsert) or return -1;
$inssth->execute() or return -1;
$inssth->finish();
#将日志信息打印到文件当中
print (GetNowTime() ." ************************** insert into sample data end **************************\n");
print (GetNowTime() ." ************************** begin insert check_result**************************\n");
#将detail数据进行汇总插入到result表,直接通过sql进行数据的循环插入,方式insert into table select ******
my $InsSql = " Insert Into ${check_Result}".
" select ${checkID},'${_date}', '${Rule_Name}',${Map_Id},'${Topic_Area}','${Sys_Id}','${table_Name}','${Check_Column_Name}','${CheckDimension}','${CheckSegmentation}',".
" mainorg ,effectCount,effectCount-decode(FailCount,null,0,FailCount), decode(FailCount,null,0,FailCount),".
" cast(decode(FailCount,null,0,FailCount) as double)/effectCount,cast((effectCount-decode(FailCount,null,0,FailCount)) as double)/effectCount from ".
"(select count(*) as effectCount, $Org_Column_Name as mainorg from ${Sys_Id}.${table_Name} group by ${Org_Column_Name}) tmain ".
" left join ".
"(select count(*) as FailCount, org_id,check_id from ${check_detail} detail where detail.rundate = '${_date}'and check_id=${checkID} group by org_id,check_id) tdetail".
" on tmain.mainorg = tdetail.org_id";
my $collsth = $dbh->prepare($InsSql) or return -1;
$collsth->execute() or return -1;
$collsth->finish();
print (GetNowTime() ." ************************** end insert check_result**************************\n");
my $now2 = time;
my $diff = $now2 - $now1;
if($diff > 1800){#大于30分钟
print ("execute time is : $diff second,checkId is :【$checkID】 ! \n");
}
$dbh->commit();
#没有commit时,就不会插入到数据库
}else{
#上一次执行的sql,一个规则组下的第n个规则执行时,检查的有效记录数=全表-前面n-1次检查出的记录数
my $preWhereCluse = '';
my $arrIndex = $#exeCheckSql;
#当前是第i个规则sql,那么需要得到前面i-1个规则sql检测的sql
for(my $j=0;$j<=($arrIndex-1);$j++){
#这里要求规则sql都是有where条件的,截取的都是where之后的内容
#这里要求执行的规则sql只有where子句
my $whereposi = index(@exeCheckSql[$j],'WHERE');
my $whereclause = substr(@exeCheckSql[$j],$whereposi+5);
if($j eq 0){
$preWhereCluse = ' and not('.$whereclause.')';
}else{
$preWhereCluse = $preWhereCluse.' and not('.$whereclause.')';
}
}
#本次检查在上一次检查的基础上,排除上次规则检查有问题的记录
my $currSqlCluse = $SQLClause.$preWhereCluse;
my $fromposi = index($currSqlCluse,'FROM');
my $fromclause = substr($currSqlCluse,$fromposi+4);
my $pkselect = '';
my @PKcon = split(",",$PK_Column_Name);
my $PKlen = $#PKcon;#获得数组的下标,从0开始,数组为空时,返回-1
if($PKlen eq 0){
$pkselect = $PK_Column_Name;
}else{
foreach my $k(0..$PKlen){
if($k eq 0){
$pkselect = @PKcon[$k];
}else{
$pkselect = $pkselect.'||'.'\'#\''.'||'.(@PKcon[$k]);
}
}
}
my $ckselect= '';
my @CKcon = split(",",$Check_Column_Name);
my $CKlen = $#CKcon;
if($CKlen eq 0){
$ckselect = $Check_Column_Name;
}else{
foreach my $k(0..$CKlen){
if($k eq 0){
$ckselect = @CKcon[$k];
}else{
$ckselect = $ckselect.'||'.'\'#\''.'||'.(@CKcon[$k]);
}
}
}
my $now1 = time;
print (GetNowTime() ." ************************** insert into detail begin **************************\n");
#将规则sql的检查结果插入明细表
my $detailInsertSql = "Insert Into ${check_detail}" .
" select ${checkID},'${_date}', ${Map_Id}," .
" '${Topic_Area}','${Sys_Id}','${table_Name}','${Check_Column_Name}','${CheckDimension}','${CheckSegmentation}',".
" ${pkselect},${Org_Column_Name},${ckselect} from ".$fromclause;
my $detailsth = $dbh->prepare($detailInsertSql) or return -1;
$detailsth->execute() or return -1;
$detailsth->finish();
print (GetNowTime() ." ************************** insert into detail end **************************\n");
print (GetNowTime() ." ************************** insert into sample data begin **************************\n");
#从临时表按照规则、机构和运行日期的维度取得样本数据,插入明细表
#partition by 可以是多个字段
my $sampInsert = "insert into ${check_detail_sample}".
" select ${checkID},'${_date}',${Map_Id},'${Topic_Area}','${Sys_Id}','${table_Name}','${Check_Column_Name}',".
"'${CheckDimension}','${CheckSegmentation}',pk_column_value,org_id,check_column_value from ".
"(select crt.*,ROW_NUMBER() over( partition by org_id,check_id) as seq from ${check_detail} crt where rundate='${_date}') detailtmp ".
" where detailtmp.seq<6";
my $inssth = $dbh->prepare($sampInsert) or return -1;
$inssth->execute() or return -1;
$inssth->finish();
print (GetNowTime() ." ************************** insert into sample data end **************************\n");
print (GetNowTime() ." ************************** begin insert check_result**************************\n");
#将detail数据插入到result表,直接通过sql进行数据的循环插入,方式insert into table select ******
my $InsSql = " Insert Into ${check_Result}".
" select ${checkID},'${_date}', '${Rule_Name}',${Map_Id},'${Topic_Area}','${Sys_Id}','${table_Name}','${Check_Column_Name}','${CheckDimension}','${CheckSegmentation}',".
" mainorg ,effectCount,effectCount-decode(FailCount,null,0,FailCount), decode(FailCount,null,0,FailCount),".
" cast(decode(FailCount,null,0,FailCount) as double)/effectCount,cast((effectCount-decode(FailCount,null,0,FailCount)) as double)/effectCount from ".
"(select count(*) as effectCount, $Org_Column_Name as mainorg from ${Sys_Id}.${table_Name} where 1=1".$preWhereCluse." group by ${Org_Column_Name}) tmain ".
" left join ".
"(select count(*) as FailCount, org_id,check_id from ${check_detail} detail where detail.rundate = '${_date}'and check_id=${checkID} group by org_id,check_id) tdetail".
" on tmain.mainorg = tdetail.org_id";
my $collsth = $dbh->prepare($InsSql) or return -1;
$collsth->execute() or return -1;
$collsth->finish();
print (GetNowTime() ." ************************** end insert check_result**************************\n");
my $now2 = time;
my $diff = $now2 - $now1;
if($diff > 1800){#大于30分钟
print ("execute time is : $diff second,checkId is :【$checkID】 ! \n");
}
$dbh->commit();
}#else block
}#rule_info for block
return 0;
}
sub main{
print "main begin \n";
#得到数据库连接
$dbh = DBconnect();
#初始化规则组信息
print (GetNowTime() . " *********************init ruleGroup info ! ***************************\n");
getRuleGroupInfo();
#如果查询没有数据,返回接收的数组取值后,下标的最大值就是-1
my $ruleGrouplength = $#${Rule_Group}+1;
print (GetNowTime() . " *********************ruleGroup length: $ruleGrouplength ***************************\n");
#判断执行结果
if ($ruleGrouplength = 0 ){
print (GetNowTime() . " *********************No Rule_Group Info !*********************\n");
} else {
print (GetNowTime() . " *********************Get Rule_Group:Succeed !********************* \n");
}
#循环规则组,根据每一个规则组,找到该规则组下的规则(注意规则状态必须是1,即是可运行的)
my $groupTemp = '';
for my $ii(0..$#${Rule_Group}){
$groupTemp = ${Rule_Group}->[$ii]->[0];
print (GetNowTime() . "********************* Begin To Run Rule_Group[$ii+1],groupId:${groupTemp}********************* \n");
#传入了规则组参数Mapid
print (GetNowTime() . " *********************Begin To get Rule Info! ***************************\n");
getRuleInfo($groupTemp);
print (GetNowTime() . " *********************end To get Rule Info! ***************************\n");
print (GetNowTime() . " *********************Begin To execute Rule check ! ***************************\n");
exeRuleSql();
#将错误明细表的记录导出成txt文件,这里是规则组的粒度
#导出明细后,删除明细数据,防止数据量膨胀
print (GetNowTime() . " *********************end To execute Rule check ! ***************************\n");
}
print (GetNowTime() . " ********************* end ***************************\n");
return 0;
}
sub GetNowTimeNospechar{
my ($sec, $min, $hour, $day, $mon, $year, $wday, $yday, $isdst) = localtime();
$hour = sprintf("%02d", $hour);
$min = sprintf("%02d", $min);
$sec = sprintf("%02d", $sec);
my $stime = GetNowDate().$hour.$min.$sec;
return $stime;
}
sub GetNowTime{
my ($sec, $min, $hour, $day, $mon, $year, $wday, $yday, $isdst) = localtime();
$hour = sprintf("%02d", $hour);
$min = sprintf("%02d", $min);
$sec = sprintf("%02d", $sec);
my $stime = GetNowDate()." ".$hour.":".$min.":".$sec;
return $stime;
}
#找到当前的日期,月份要加1,年份是从1900开始算的
sub GetNowDate{
my ($sec, $min, $hour, $day, $mon, $year, $wday, $yday, $isdst) = localtime();
$mon = sprintf("%02d", $mon+1);
$day = sprintf("%02d", $day);
my $stime = ($year+1900)."-".$mon."-".$day;
return $stime;
}
sub GetNowDate8{
my ($sec, $min, $hour, $day, $mon, $year, $wday, $yday, $isdst) = localtime();
$mon = sprintf("%02d", $mon+1);
$day = sprintf("%02d", $day);
my $stime = ($year+1900).$mon.$day;
return $stime;
}
#判断当前日期所属的频率(每天,每星期,每半月,每月,每季度,每年)
sub isRunCondition{
my $FLAG ="'01'";
my $year = substr($TX_DATE,0,4);
my $month = substr($TX_DATE,4,2);
my $day = substr($TX_DATE,6,2);
#判断是否闰年
my $isRunYear;
if(($year%4==0 && $year%100!=0) || $year%400==0){
$isRunYear = 1;
} else {
$isRunYear = 0;
}
#判断TX_DATE所在周的周末
my $timenum = Time::Local::timelocal(0, 0, 0, $day, $month-1, $year);
my @timestr = localtime($timenum);
my $wday = $timestr[6];
if ($wday==6){
$FLAG=$FLAG.",'02'";
}
#判断TX_DATE所在月的月末
my $Month_End;
if($month eq "01" || $month eq "03" || $month eq "05" || $month eq "07" || $month eq "08" || $month eq "10" || $month eq "12"){
$Month_End = "31";
} elsif($month eq "04" || $month eq "06" || $month eq "09" || $month eq "11"){
$Month_End = "30";
} elsif($month eq "02" && $isRunYear==1) {
$Month_End = "29";
} else {
$Month_End = "28";
}
if($Month_End eq $day){
$FLAG=$FLAG.",'03'";
}
#判断TX_DATE所在季的季末
my $Quarter_Month;
my $Quarter_End;
if($month eq "01" or $month eq "02" or $month eq "03") {
$Quarter_Month="03";
}elsif($month eq "04" or $month eq "05" or $month eq "06") {
$Quarter_Month="06";
}elsif($month eq "07" or $month eq "08" or $month eq "09") {
$Quarter_Month="09";
}elsif($month eq "10" or $month eq "11" or $month eq "12") {
$Quarter_Month="12";
}
if($Quarter_Month eq "03" || $Quarter_Month eq "12" ){
$Quarter_End ="31";
} elsif($Quarter_Month eq "09" || $Quarter_Month eq "06" ){
$Quarter_End ="30";
}
if($Quarter_Month.$Quarter_End eq $month.$day){
$FLAG=$FLAG.",'04'";
}
#判断TX_DATE所在半年末
my $Half_Month;
my $Half_End;
if($month eq "01" or $month eq "02" or $month eq "03" or $month eq "04" or $month eq "05" or $month eq "06") {
$Half_Month="06";
}elsif($month eq "07" or $month eq "08" or $month eq "09" or $month eq "10" or $month eq "11" or $month eq "12") {
$Half_Month="12";
}
if($Half_Month eq "12" ){
$Half_End ="31";
} elsif($Half_Month eq "06" ){
$Half_End ="30";
}
if($Half_Month.$Half_End eq $month.$day){
$FLAG=$FLAG.",'05'";
}
#年末
my $Year_End="1231";
if($Year_End eq $month.$day){
$FLAG=$FLAG.",'06'";
}
return $FLAG;
}
#方法调用,程序入口
my $rc = main();#函数的入口
exit($rc);#这里的exit内容可以被ETL接收到
相关推荐
Jupyter-Notebook
Jupyter-Notebook
高效甘特图模板下载-精心整理.zip
lstm Summary Framework: z = U>x, x u Uz Criteria for choosing U: • PCA: maximize projected variance • CCA: maximize projected correlation • FDA: maximize projected intraclass variance
OpenGL调试工具,适合图形开发者,包括视频开发,播放器开始以及游戏开发者。
全国行政区划shp最新图.zip
全国研究生招生与在校数据+国家线-最新.zip
Jupyter-Notebook
直播电商交流平台 SSM毕业设计 附带论文 启动教程:https://www.bilibili.com/video/BV1GK1iYyE2B
《林黛玉进贾府》课本剧剧本
2000-2020年沪深A股上市公司融资约束程度SA指数-最新数据发布.zip
PPT模版资料,PPT模版资料
CPA注会考试最新教材资料-最新发布.zip
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
内容概要:本文提供了一个完整的职工管理系统的C++源代码。通过面向对象的编程方法,实现了包括创建新职工、查询、增加、修改、删除、排序、统计以及存储和恢复职工数据在内的多个基本操作功能。该系统支持不同的用户角色(如管理员与老板),并通过菜单驱动方式让用户方便地进行相关操作。此外,还包括了错误检测机制,确保操作过程中的异常得到及时处理。 适合人群:有一定C++语言基础,特别是面向对象编程经验的程序员;企业管理人员和技术开发人员。 使用场景及目标:适用于中小型企业内部的人力资源管理部门或IT部门,用于维护员工基本信息数据库,提高工作效率。通过本项目的学习可以加深对链表、类和对象的理解。 阅读建议:建议先熟悉C++的基本语法和面向对象概念,再深入学习代码的具体实现细节。对于关键函数,比如exchange、creatilist等,应当重点关注并动手实践以加强理解。
Jupyter-Notebook
考研公共课历年真题集-最新发布.zip
Huawei-HKUST Joint Workshop on Theory for Future Wireless 15-16 September 2022 华为-香港科技大学未来无线理论联合研讨会 Speaker:Jingwen Tong
演出人员与观众疫情信息管理系统 SSM毕业设计 附带论文 启动教程:https://www.bilibili.com/video/BV1GK1iYyE2B
《林黛玉进贾府》课本剧剧本.pdf