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

Get full error message in Perl DBI module

我有一个这样的 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'],但它丢失了。

知道如何获取这些附加信息吗?

看看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 attribute, or in very rare cases, the HandleSetError 属性。

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

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";