Обсуждение: Catching errors with Perl DBI
How can I catch the errors generated whne I call an INSERT that violates a
constraint? I have coded like this:
my $sth = $dbh->prepare($stmt);
my $rv = $sth->execute() or die $DBI::errstr;
if ( $rv < 0 ) {
print $DBI::errstr;
}
But, if the INSERT violates a constraint, it never gets the the evaluation
of the $rv
Is this a setting for the DBI?
--
"They that would give up essential liberty for temporary safety deserve
neither liberty nor safety."
-- Benjamin Franklin
On Thu, 2 Jul 2020 11:03:37 -0400
stan <stanb@panix.com> wrote:
> my $sth = $dbh->prepare($stmt);
> my $rv = $sth->execute() or die $DBI::errstr;
that ``or die`` means: if the result of the ``execute`` is false
(which only happens on error), throw an exception (which, as you
noticed, terminates the process unless caught with an ``eval {}`` or
similar construct)
> if ( $rv < 0 ) { print $DBI::errstr; }
Notice that ``$rv`` would never be less than 0: for an ``INSERT``,
it's the number of rows inserted (or a special "0 but true" value in
case no rows were inserted).
So, you can do two things:
* keeping the same style::
my $rv = $sth->execute(@bind_values);
if (!$rv) {
print $sth->errstr;
# and probably do something useful here ☺
}
* switching to exceptions everywhere
Tell DBI you want exceptions::
my $dbh = DBI->connect(
$dsn,$user,$password,
{
PrintError => 0,
RaiseErorr => 1,
PrintWarn => 0,
RaiseWarn => 1,
}
);
then run statements like this::
eval { $dbh->prepare($stmt)->execute(@bind_values) }
or do {
print $@; # the exception is store in this variable
};
--
Dakkar - <Mobilis in mobile>
GPG public key fingerprint = A071 E618 DD2C 5901 9574
6FE2 40EA 9883 7519 3F88
key id = 0x75193F88
Stan:
On Thu, Jul 2, 2020 at 5:03 PM stan <stanb@panix.com> wrote:
> How can I catch the errors generated whne I call an INSERT that violates a
> constraint? I have coded like this:
>
> my $sth = $dbh->prepare($stmt);
> my $rv = $sth->execute() or die $DBI::errstr;
> if ( $rv < 0 ) {
> print $DBI::errstr;
> }
>
> But, if the INSERT violates a constraint, it never gets the the evaluation
> of the $rv
I assume you mean the if($rv<0) is what it is not executed.
In perl this happens because something died. I assume it is not the
one you coded. This means some of your handles have the RaiseError
attribute, lookit up in the perldoc.
> Is this a setting for the DBI?
I do not remember if it has a global setting, but it sure has a
database handle setting ( which percolates down ). I use it routinely
for easier error handling.
I'm not sure if you know how to from your message, but if something is
dying you can use the block eval construct:
eval {
# potentially dying code...
my $sth = $dbh->prepare($stmt);
my $rv = $sth->execute() or die $DBI::errstr;
if ( $rv < 0 ) {
print $DBI::errstr;
}
1; # This forces the eval to return true if execution gets here.
} or do {
# Whatever you want, $@ has the codes.
}
to trap it in perl.
About RaiseError, it is common to set it to true in the handle, put
all your code in a sub() and catch it, in programs where you donot
have easy recovery of errors, and use local eval if needed to catch
this kind of prim. key violation things.
Francisco Olarte.