数据库perl脚本实战:创建各表,并导入数据
#!/usr/bin/perl
#/*****************************************************************************************
#/*****************************************************************************************
use strict; # Declare using Perl strict syntax
use warnings;
默认脚本解释器位置:/usr/bin/perl
检查系统环境变量
# ------------ Variable Section ------------
my ${AUTO_HOME} = $ENV{"AUTO_HOME"};
my ${DBSERVER} = $ENV{"SDB_SERVICE_NAME"};
if ( !defined(${DBSERVER}) ) {
print "DBSERVER is not defined";
exit(1);
}
my ${USER} = $ENV{"SDB_USER"};
if ( !defined(${USER}) ) {
print "USER is not defined";
exit(1);
}
my ${PASSWD} = $ENV{"SDB_PASSWD"};
if ( !defined(${PASSWD}) ) {
print "PASSWD is not defined";
exit(1);
}
定义各变量并引用环境变量,defined判断变量是否为空,如果!defined成立说明变量为空,然后打印错误信息并退出,错误代码1.非正常退出。
my ${CONTROL_NAME} = substr($ARGV[0],-12);
my ${DATE} = substr(${CONTROL_NAME},0,8);
#源系统、源表名,用于拼接构目标表名及控制文件名
my $Org_System = "aw";
my $Org_Table = "S_INFO";
my $Table_Date = substr(${DATE},4,4);
my $TABLE_NAME_MMDD = $Org_Table."_".$Table_Date;
if ( !defined(${AUTO_HOME}) ) {
${AUTO_HOME} = "/home/oracle/std";
}
my ${SDB} = $ENV{"AUTO_SDB"};
if ( !defined(${SDB}) ) {
${SDB} = "SDB";
}
my ${ODB} = $ENV{"AUTO_ODB"};
if ( !defined(${ODB}) ) {
${ODB} = "ODB";
}
my ${CDB} = $ENV{"AUTO_CDB"};
if ( !defined(${CDB}) ) {
${CDB} = "CDB";
}
my ${MDB} = $ENV{"AUTO_MDB"};
if ( !defined(${MDB}) ) {
${MDB} = "MDB";
}
my ${SDBDDL} = $ENV{"AUTO_SDBDDL"};
if ( !defined(${SDBDDL}) ) {
${SDBDDL} = "SDDL";
}
my ${ILL_DATE} = "0001-01-02";
my ${NULL_DATE} = "0001-01-01";
my ${MAX_DATE} = "3000-12-31";
my ${LOGON_FILE} = "${AUTO_HOME}/etc/LOGON_LOAD";
my ${LOGON_STR};
my ${CONTROL_FILE};
my ${TX_DATE};
my ${TX_DATE_YYYYMMDD};
my ${TX_MON_DAY_MMDD};
$ARGV里面存放的是从外部传进来的参数,substr($ARGV[0],-12):取外部传参后12位字符定义control_name变量,再在control_name中取前8位定义为date变量;取自定义变量与date变量后4位拼接合并为月日表名变量。
定义AUTO_HOME,SDB,ODB,CDB,SDB,SDBDDL等引用环境变量,如变量为空则重新定义。
变量设置完成 ,开始编写SQLPLUS子程序块的脚本内容
# ------------ sqlplus function ------------
sub run_sqlplus_command
{
my $rc = open(sqlplus, "| sqlplus /nolog"); #进入sqlplus环境,nolog参数表示不登录
#————————————————————————————————————————————————————————————————————————————————
#用open函数也可像命令行一样,打开和使用管道.
# 语法为:
# open(MYVAR, "mode");
# mode有如下两种模式:
# "|command" 表示对MYVAR的输出相当于对command的输入.
# 如果以管道符号开头,”open” 启动一个新的命令,打开一个可写文件句柄通向
# 这个命令。你可以向这个句柄中写入内容,而你所写的将出现在这个命令的标准
# 输出里。
# "command|" 表示command的输出作为对MYVAR的输入.
# 如果末尾的字符是一个管道时,你启动一个新的命令,打开一个通向这个命令的
# 可读文件句柄。这使得这个命令写入标准输出的内容可以在你的句柄中读到的。
#————————————————————————————————————————————————————————————————————————————————
unless ($rc) {
print "Could not invoke sqlplus command\n";
return -1;
}
#my $rc = open(sqlplus, "| sqlplus /nolog")||die "Could not invoke sqlplus command\n";
# ------ sqlplus scripts ----------
print sqlplus <<ENDOFINPUT;
conn $USER/$PASSWD\@${DBSERVER}; #连接数据库,用户/密码@数据库名
set echo on #设置运行命令是是否显示语句
set timing on #设置显示“已用时间:XXXX”
alter session force parallel query parallel 8;
alter session force parallel dml parallel 8;
alter session force parallel ddl parallel 8;
#设置oracle查询、DML、DDL语句并行度为8;
--建表SDB技术缓冲层
WHENEVER SQLERROR CONTINUE;
DROP TABLE SDB.S01_LSB_$Table_Date;
commit;
WHENEVER SQLERROR EXIT SQL.SQLCODE;
CREATE TABLE SDB.S01_LSB_$Table_Date (
ACTNO NUMBER(4)
,OPNAME VARCHAR(10)
,PASSWD VARCHAR(6)
,CASH NUMBER(10,2)
,OPDATE DATE
,OPADDR VARCHAR(30)
)
TABLESPACE tbs_SDB COMPRESS
STORAGE(FLASH_CACHE DEFAULT)
NOLOGGING;
commit;
#建表SDB技术缓冲层
WHENEVER SQLERROR EXIT SQL.SQLCODE;
GRANT SELECT ON ${SDB}.S01_LSB_$Table_Date TO ODB;
commit;
GRANT SELECT ON ${SDB}.S01_LSB_$Table_Date TO CDB;
commit;
GRANT SELECT ON ${SDB}.S01_LSB_$Table_Date TO MDB;
commit;
#给数据贴源层、共性加工层、应用集市层用户提供SDB表的查询权限!
ENDOFINPUT
#向SQLPLUS句柄输入内容完成
close(sqlplus);
#关闭sqlplus句柄
my $RET_CODE = $? >> 8;
#$?为上次执行命令:成功=0失败=1;定义变量$RET_CODE为上次命令执行结果检测值;
if ( $RET_CODE == 0 ) {
return 0;
}
else {
return 1;
}
#执行成功返回0,失败返回1.
}
print sqlplus <<ENDOFINPUT;
ENDOFINPUT ——从print语句到ENDOFINPUT之间的文本输出到SQLPLUS句柄,即向句柄SQLPLUS写入 ENDOFINPUT括起来的字符串作为命令行输出;
【引用】WHENEVER语句是SQL预编译程序的指示语句,而不是可执行语句。它通知预编译程序在每条可执行嵌入式SQL语句之后自动生成错误处理程序,并指定了错误处理操作。
①:WHENEVER SQLERROR action:表示一旦sql语句执行时遇到错误信息,则执行action,action中包含了处理错误的代码(SQLCODE<0)。
②:WHENEVER SQLWARNING action:表示一旦sql语句执行时遇到警告信息,则执行aciton,即action中包含了处理警报的代码(SQLCODE=1)。
③:WHENEVER NOT FOUND action:表示一旦sql语句执行时没有找到相应的元组,则执行action,即 action包含了处理没有查到内容的代码(SQLCODE=100)。
针对上述三种异常处理,用户可以指定预编译程序采取以下三种行为(action):
Ⅰ:WHENEVER …GOTO:通知预编译程序产生一条转移语句。
Ⅱ:WHENEVER…CONTINUE/EXIT:通知预编译程序让程序的控制流转入到下一个主语言语句或退出。
Ⅲ:WHENEVER…CALL:通知预编译程序调用函数。
其完整语法如下:WHENEVER {SQLWARNING | SQLERROR | NOT FOUND} {CONTINUE | GOTO stmt_label | CALL function()}
主程序块:
# ------------ main function ------------
sub main
{
my $ret;
my $localtm=localtime(time());
print "\nbatch exec STARTTIME:$localtm\n\n";#批处理执行开始时间
# Call sqlplus command to load data
$ret = run_sqlplus_command();
my $localtm=localtime(time());
print "\nbatch exec ENDTIME:$localtm\n\n";#批处理执行结束 时间
my $sqlldr_ret = EDW::run_sqlldr_command($Org_System,$Org_Table,$DATE,"1");
print "run_sqlplus_command() = $ret\n\n";
print "run_sqlldr_command() = $sqlldr_ret\n\n";
if ( $ret == 0 && $sqlldr_ret == 0 ) {
return 0;
}
else {
return 1;
}
}
调用子程序run_sqlplus_command建表
调用包模块的run_sqlldr_command方法并带入参数Org_System,Org_Table,DATE,“1”,执行sqlldr批量导入!
打印执行结果,如果建表和导入同时成功则返回0,否则返回1.
程序块
# ------------ program section ------------
if ( $#ARGV < 0 ) {
print "Usage: [perl program Control_File] (Control_File format: dir.jobnameYYYYMMDD or sysname_jobname_YYYYMMDD.dir) \n";
print "\n";
exit(1);
}
#判断无输入参数报错退出
# Get the first argument
${CONTROL_FILE} = ${DATE};
if (${CONTROL_FILE} =~/[0-9]{8}($|\.)/) {
${TX_DATE_YYYYMMDD} = substr($&,0,8);#在模式匹配后调用重用部分的结果可用变量$n,全部的结果用变量$&
}
else{
print "Usage: [perl program Control_File] (Control_File format: dir.jobnameYYYYMMDD or sysname_jobname_YYYYMMDD.dir) \n";
print "\n";
exit(1);
}
#CONTROL_FILE引用之前的DATE进行匹配 ,如参数输入格式不对,正则匹配不成功报错退出。匹配成功后的8位日期截取出来作为TX_DATE_YYYYMMDD的内容。
${TX_MON_DAY_MMDD} = substr(${TX_DATE_YYYYMMDD}, length(${TX_DATE_YYYYMMDD})-4,4);
${TX_DATE} = substr(${TX_DATE_YYYYMMDD}, 0, 4)."-".substr(${TX_DATE_YYYYMMDD}, 4, 2)."-".substr(${TX_DATE_YYYYMMDD}, 6, 2);
open(STDERR, ">&STDOUT");
#输出错误信息
my $ret = main();
exit($ret);
运行主程序main;
退出。