2012-07-31 136 views
1

所以我开始熟悉Perl并编写了我的第一个Db脚本。perl将日志db查询错误写入日志文件

现在我试图从很大的atable中选择数据,并尝试根据某些条件插入到汇总表中。

现在有机会,选择查询可能失败或插入查询可能由于超出我的控制超时或其他数据库问题而失败。

最终我的脚本将是cron脚本。

我可以只记录我遇到的连接错误,插入并选择到脚本中生成的文件中吗?

$logfile = $path.'logs/$currdate.log'; 

这里是我的代码:

my $SQL_handled="SELECT division_id,region_id, NVL(COUNT(*),0) FROM super_tab GROUP BY division_id,region_id;"; 
my $result_handled = $dbh->prepare($SQL_handled); 
$result_handled->execute(); 
while (my ($division_id,$region_id,$count) = $result_handled->fetchrow_array()){ 
    my $InsertHandled="INSERT INTO summary_tab (date_hour, division_id, region_id,volume) VALUES ('$current',$division_id,$region_id,$market_id,'$service_type','$handled',$count);"; 
    my $result_insert_handled = $dbh->prepare($InsertHandled); 

    $result_insert_handled->execute(); 

} 

如果(DBI查询失败){// 记录错误到上面的日志路径 }

回答

2

其通常是这样做的

my $SQL_handled="SELECT division_id,region_id, NVL(COUNT(*),0) FROM super_tab GROUP BY division_id,region_id;"; 
my $result_handled = $dbh->prepare($SQL_handled); 
my $retval = $result_handled->execute(); 
if(!$retval){ 
    #open a log file and write errors 
    writelog(); 
    die "Error executing SQL SELECT - $dbh->errstr"; 
} 
while(my ($division_id,$region_id,$count) = $result_handled->fetchrow_array()){.... 
} 

--------------------------------- 

sub writelog{ 
    my $path = "/path/to/logfile"; 
    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); 
    $year += 1900; 
    $mon++; 
    my $currdate = "$mon$mday$year"; 

    $logfile = $path . "/$currdate.log"; 
    open (OUT, ">>$logfile"); 
    print OUT "There was an error encountered while executing SQL- $dbh->errstr \n"; 
    close(OUT); 
} 

您也可以使用$dbh->err;,它返回本机Oracle错误代码以捕获错误并相应地退出。

上面的脚本中的每个​​方法调用都可以执行基本的异常处理。请记住,默认情况下,DBIAutoCommit设置为1(启用),除非明确禁用。因此,您的交易将为每次插入自动提交,为了处理整个交易的ATOMICITY,您可以禁用自动提交,并使用$dbh->commit$dbh->rollback来处理您想要提交的内容,或者可能使用一些自定义的commit point(适用于更大的数据)。

或低于可同时连接到数据库

$dbh = DBI->connect("dbi:Oracle:abcdef", "username", "password" , { 
    PrintError => 0, ### Don't report errors via warn() 
    RaiseError => 1 ### Do report errors via die() 
}); 

这将通过die自动报告所有的错误使用。默认情况下,RaiseError通常处于关闭状态。

另外,如果我正确地理解你,那么通过cron你的意思是你会从一个shell cron作业调用它。在这种情况下,打电话给你的perl脚本由cron的本身可以被重定向到日志文件类似下面

perl your_perl.pl >> out.log 2>> err.log 

out.log将包含常规日志和err.log将包含错误(由DBI专门抛出prepare() or execute()方法太)。在这种情况下,您还需要确保在printdie中使用适当的措辞,以便日志看起来有意义。

1

首先,记住,如果你在你的crontab的上面放一个电子邮件地址,文件从cron作业的任何输出熊将通过电子邮件发送给您:

[email protected] 

第二,如果你设置DBI的RaiseError到1当你连接你不需要检查每一个电话时,DBI会在发生错误时提出错误。

三,DBI有一个错误handler callback。您注册了一个处理程序,并且在错误和错误文本等句柄发生错误时调用它。如果您从错误处理程序返回false,则DBI将像没有处理程序那样工作,并继续死亡或警告。因此,比Annjawn建议的更容易设置RaiseError并创建错误处理程序。

最后,如果你不想自己做这个,你可以使用像DBIx::Log4perl这样的东西,只是要求它记录错误而不是其他东西。任何错误将被写入您的Log4perl文件,并且它们包括正在执行的SQL,参数等。