简体   繁体   中英

Get full error message in Perl DBI module

I have a Perl script like this:

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

When I run it the console produce following output:

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.

I would like to store the full error message, but variable $err contains only 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.

But I would like to get also [for Statement "INSERT INTO WT_APPCERT_LH (STATUS, APPCERT) VALUES (?,?)" with ParamValues: :p1='foo', :p2='bar'] which is missing.

Any idea how to catch this additional information?

Take a look at the documentation for the PrintError attribute . It's enabled by default and is why the error is being logged to the console. It's also the source of the DBD::Oracle::st execute failed: prefix.

Then take a look at the ShowErrorStatement attribute . It's also enabled by default (in DBD::Oracle but not all drivers) and is the source of the [for Statement "..." with ParamValues: :p1='foo', :p2='bar'] suffix.

Then take a look at the RaiseError attribute . If that was set then the DBI would throw an exception (containing the message you saw logged to the console) when the error occurs. You could catch that exception and handle it however you want.

In general, I strongly recommend that all applications using the DBI enable RaiseError. It makes your applications more robust and you life much easier.

ps For advanced use-cases you might want to use look into the HandleError attribute, or in very rare cases, the HandleSetError attribute.

Based on given comments and answer I found these solutions:

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;

and

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM