简体   繁体   中英

Perl DBI Statement Handles and Error Handling

Let's say I have a subroutine that connects to a DB. Then I want to make a query and receive the output and do something with it, of course, but what if the query is invalid?

So let's assume I have something like:

$dbh = DBI->connect(<db>, <user>, <pass>);
$query = 'select a, b, c from table';
$sth = $dbh->prepare($query);
$sth->execute();

I realise I could also use a "do", but this will be easier for me to understand. So in a scenario where "table" doesn't have a column "c", the query would be invalid, making the handle $sth invalid and failing to execute. Right?

Now, in case of a failure as such, what happens to $sth? I can't call finish on it, because it is invalid.

This is by far the best way to do things. Stick with prepare (which you need to do only once) and execute and avoid do . You should also use question marks as placeholders for any parameters to the query and pass the values in the call to execute . Amongst other things, that way handles any necessary quoting of the values for you

It is very rare that a call to finish or disconnect is necessary. You should leave them out until you know your way around DBI better

You're correct, $sth will be undef , and the error code and error message will be returned by $dbh->err and $dbh->errstr . Also, by default the PrintError option is set, which causes DBI to generate a warning if there are any errors in execution. If you want your program to stop altogether instead then disable PrintError and enable RaiseError

Apart from that it's really down to what you choose to do in the case of an error. For instance, some errors might be recoverable, in which case you can disable both PrintError and RaiseError and test whether the returned value is undef . Then you would perform some action possibly based on the error code returned by $dbh->err

I hope that helps

So in a scenario where "table" doesn't have a column "c", the query would be invalid, making the handle $sth invalid and failing to execute. Right?

It's not clear what you mean by "invalid".

Some drivers, like DBD::Oracle, may send the SQL statement to the server when you call prepare , in which case the error will be detected by the server and prepare will fail, returning an undef. (See also @Borodin's note about RaiseError.)

If the driver doesn't send the statement to the server when prepare is called then driver creates and returns a statement handle that has the statement string stored within it.

Now, in case of a failure as such, what happens to $sth? I can't call finish on it, because it is invalid.

Again, it's not clear what you mean by "invalid". (I find it helpful to try to be really clear about the concepts and situations I'm thinking about. Forcing myself to do that often means I find the answers to my own questions because the 'problem' was in the words I was using.)

So, as I described above, either prepare failed and returned an undef (or threw an exception due to RaiseError - recommended), or prepare returned a valid $sth.

If prepare returned an undef then perl will throw an exception when you try to call execute.

If prepare returned a valid $sth then execute will be called, the statement will be sent to the server, the server will detect the error, and execute will return false (or throw an exception if RaiseError is set - recommended).

At no point would I call $sth "invalid". Either you don't have an $sth at all because prepare failed, or you have an $sth that's perfectly valid but experienced an error when executed.

In that case calling $sth->finish would work but, as @ThisSuitIsBlackNot correctly noted, it would be pointless. (I should have renamed finish to discard_pending_rows many many years ago.)

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