dbi beginner

How to check for DBI errors and retrieve error messages in Perl?

Question

How to check for DBI errors and retrieve error messages in Perl?

When working with DBI in Perl to interact with databases, proper error handling is crucial. The DBI module provides several ways to detect and retrieve error information after database operations. Understanding how to check for errors and obtain descriptive messages helps you debug and make your code more robust.

Common DBI Error Handling Methods

  • RaiseError attribute: Automatically dies on errors, enabling exception-style handling.
  • err, errstr, and state: Methods to inspect the error code, message, and SQL state.
  • Return values of DBI methods: Generally, methods return undef or false on failure.

Using RaiseError for Simple Error Handling

Setting RaiseError => 1 on your database handle means DBI will automatically die if an error occurs. This simplifies error handling by stopping execution immediately, letting you catch errors with eval or by a higher-level exception handler.

Manual Error Checking Without RaiseError

If you don’t want exceptions, you can disable RaiseError and check errors manually. After each DBI call, check if the method returned false or undef, then inspect $dbh->err and $dbh->errstr for error code and message.

Key DBI Variables for Error Info

  • $dbh->err: Numeric error code (0 means no error)
  • $dbh->errstr: Human-readable error message
  • $dbh->state: SQLSTATE error code (useful for specific error types)

Example: Checking for DBI Errors and Retrieving Messages

use strict;
use warnings;
use DBI;

# Connect to an in-memory SQLite database for demonstration
my $dsn = "dbi:SQLite:dbname=:memory:";
my $username = "";
my $password = "";

# Disable RaiseError: handle errors manually
my $dbh = DBI->connect($dsn, $username, $password, {
    RaiseError => 0,
    PrintError => 0,
    AutoCommit => 1,
});

if (!$dbh) {
    die "Failed to connect: $DBI::errstr\n";
}

# Prepare a statement with incorrect SQL to trigger an error
my $sth = $dbh->prepare("SELECT * FROM non_existing_table");

# Check for error after prepare
if (!$sth) {
    print "Error preparing statement:\n";
    print "  err   : ", $dbh->err, "\n";
    print "  errstr: ", $dbh->errstr, "\n";
    print "  state : ", $dbh->state, "\n";
} else {
    # Execute query if prepare succeeded (unlikely here)
    if (!$sth->execute()) {
        print "Error executing statement:\n";
        print "  err   : ", $sth->err, "\n";
        print "  errstr: ", $sth->errstr, "\n";
        print "  state : ", $sth->state, "\n";
    }
}

# Clean up
$dbh->disconnect();

Explanation:

  • We connect to a SQLite in-memory database without RaiseError set.
  • We attempt to prepare a SQL statement on a non-existent table, guaranteed to cause an error.
  • After prepare, we check if the statement handle is defined. If not, we print error information from $dbh.
  • If prepare succeeded, similar error checking can be done after execute using the statement handle $sth.

Notes and Gotchas

  • RaiseError is very convenient for beginners because it eliminates the need for manual error checking everywhere.
  • PrintError enables or disables printing errors automatically to STDERR. It is often set off in scripts to avoid duplicate error messages.
  • Remember to check either the return value or error variables for each call.
  • Error info is available both on the database handle $dbh and statement handle $sth. For example, $dbh->errstr gives errors related to connection or prepare, while $sth->errstr relates to statement execution.
  • SQLSTATE codes (state) are standardized error codes useful if you want to handle specific database error types (e.g. unique violation).

This approach, combined with Perl’s flexible DBI interface, gives you full control over error handling and reporting.

Verified Code

Executed in a sandbox to capture real output. • v5.34.1 • 39ms

Tip: edit code and use “Run (Browser)”. Server runs always execute the published, verified snippet.
STDOUT
Error preparing statement:
  err   : 1
  errstr: no such table: non_existing_table
  state : S1000
STDERR
(empty)

Was this helpful?

Related Questions