在Perl DBI模块中获取完整的错误消息

时间:2016-08-18 14:00:30

标签: perl logging error-handling dbi

我有这样的Perl脚本:

use DBI;

eval {
    my $dbh = DBI->connect("dbi:Oracle:<database>", "<user>", "<password>") or die ($DBI::errstr);
    my $sth = $dbh->prepare("INSERT INTO WT_APPCERT_LH (STATUS, APPCERT) VALUES (?,?)");
    $sth->execute( "foo", "bar" ) or die($dbh->errstr);
    $dbh->disconnect;
};

my $err = $@;   
print "\$err => $err\n";

当我运行它时,控制台会产生以下输出:

DBD::Oracle::st execute failed: ORA-01722: invalid number (DBD ERROR: error possibly near <*> indicator at char 53 in 'INSERT INTO WT_APPCERT_LH (STATUS, APPCERT) VALUES (:<*>p1,:p2)') [for Statement "INSERT INTO WT_APPCERT_LH (STATUS, APPCERT) VALUES (?,?)" with ParamValues: :p1='foo', :p2='bar'] at C:\Temp\Perl-1.pl line 6.
$err => ORA-01722: invalid number (DBD ERROR: error possibly near <*> indicator at char 53 in 'INSERT INTO WT_APPCERT_LH (STATUS, APPCERT) VALUES (:<*>p1,:p2)') at C:\Temp\Perl-1.pl line 6.

我想存储完整错误消息,但变量$err仅包含ORA-01722: invalid number (DBD ERROR: error possibly near <*> indicator at char 53 in 'INSERT INTO WT_APPCERT_LH (STATUS, APPCERT) VALUES (:<*>p1,:p2)') at C:\Temp\Perl-1.pl line 6.

但我也希望得到[for Statement "INSERT INTO WT_APPCERT_LH (STATUS, APPCERT) VALUES (?,?)" with ParamValues: :p1='foo', :p2='bar'],这是遗漏的。

知道如何捕捉这些额外信息吗?

2 个答案:

答案 0 :(得分:4)

看看documentation for the PrintError attribute。它默认启用,这是将错误记录到控制台的原因。它也是DBD::Oracle::st execute failed:前缀的来源。

然后看一下ShowErrorStatement attribute。它也默认启用(在DBD :: Oracle但不是所有驱动程序中),并且是[for Statement "..." with ParamValues: :p1='foo', :p2='bar']后缀的来源。

然后看一下RaiseError attribute。如果已设置,则DBI将在发生错误时抛出异常(包含您看到记录到控制台的消息)。您可以捕获该异常并随意处理它。

通常,我强烈建议使用DBI的所有应用程序启用RaiseError。它使您的应用程序更加健壮,让您的生活更轻松

P.S。对于可能想要使用的高级用例,请查看HandleError属性,或者在极少数情况下查看HandleSetError属性。

答案 1 :(得分:0)

根据给出的评论和答案,我找到了这些解决方案:

use DBI;

local $SIG{__WARN__} = sub {
    my $err = shift;
    print "\$err => $err\n";
};

my $dbh = DBI->connect("dbi:Oracle:<database>", "<user>", "<password>", { PrintError => 1, ShowErrorStatement => 1 } );
my $sth = $dbh->prepare("INSERT INTO WT_APPCERT_LH (STATUS, APPCERT) VALUES (?,?)");
$sth->execute( "foo", "bar" );
$dbh->disconnect;

use DBI;

eval {
    my $dbh = DBI->connect("dbi:Oracle:<database>", "<user>", "<password>", { RaiseError => 1} );
    my $sth = $dbh->prepare("INSERT INTO WT_APPCERT_LH (STATUS, APPCERT) VALUES (?,?)");
    $sth->execute( "foo", "bar" );
    $dbh->disconnect;
};
my $err = $@;   
print "\$err =>\n$err\n";