dbi intermediate

How to get the last inserted ID after INSERT in Perl DBI?

Question

How to get the last inserted ID after INSERT in Perl DBI?

How to Get the Last Inserted ID After INSERT in Perl DBI

When working with databases through Perl's DBI module, a frequent task is to retrieve the last inserted row's ID after executing an INSERT statement. This is especially common for tables with auto-increment primary keys. Perl’s DBI provides the last_insert_id method, but its behavior depends on the database driver (DBD) and proper connection setup.

Key Points About last_insert_id

  • The method is called on a valid $dbh (database handle) and takes four arguments: catalog, schema, table, and field (column) names. Passing empty strings or undef often works for many DBDs.
  • Not all drivers implement last_insert_id uniformly; some require alternative methods such as running SQL queries like SELECT LAST_INSERT_ID() (MySQL) or SELECT last_insert_rowid() (SQLite).
  • AutoCommit should generally be on for reliable retrieval immediately after insert with last_insert_id.
  • For PostgreSQL, it’s usually better to use the RETURNING clause in the INSERT statement to get the inserted ID directly.

Corrected Runnable Example Using SQLite and DBI

The following example uses an in-memory SQLite database (no file or network access needed) and demonstrates inserting a row and retrieving the last inserted ID with last_insert_id. It includes strict and warnings, proper DBI connect, and prints the results.


use strict;
use warnings;
use DBI;

# Connect to an in-memory SQLite database
my $dbh = DBI->connect("dbi:SQLite:dbname=:memory:", "", "",
    { RaiseError => 1, AutoCommit => 1 });

# Create table with auto-increment primary key
$dbh->do(q{
    CREATE TABLE users (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        name TEXT NOT NULL
    )
});

# Insert a row using placeholders for safety
my $name = "Alice";
$dbh->do("INSERT INTO users (name) VALUES (?)", undef, $name);

# Retrieve last inserted ID using last_insert_id method
# For SQLite, catalog and schema are empty strings
my $last_id = $dbh->last_insert_id("", "", "users", "") 
    or die "Could not get last insert id";

print "Inserted user ID: $last_id\n";

# Verify by selecting the inserted row
my $row = $dbh->selectrow_hashref("SELECT * FROM users WHERE id = ?", undef, $last_id);
print "User name for inserted ID $last_id is: $row->{name}\n";

Explanation

  • DBI->connect creates a valid database handle $dbh connected to an SQLite in-memory database, enabling quick testing.
  • The table users has id as an auto-increment primary key, perfect for testing last_insert_id.
  • $dbh->do safely inserts a row using a bound parameter.
  • last_insert_id is called on the valid database handle with empty strings as catalog and schema, signifying SQLite defaults.
  • Finally, we verify by fetching and printing the inserted row.

Common Gotchas

  • Calling last_insert_id on an undefined or invalid $dbh will cause errors (like the "Can't call method ... on undefined value"). Always check your DBI->connect result before proceeding.
  • Some DBDs don't support last_insert_id; you'll need to resort to database-specific methods or SQL queries.
  • AutoCommit must usually be enabled to get reliable results from last_insert_id.
  • Remember that last_insert_id returns the ID for the last insertion on the current database handle, so avoid reusing handles in concurrent or threaded contexts without care.

By ensuring you have a valid database handle and using last_insert_id properly with your DBD, you can easily obtain the last inserted row’s primary key in Perl DBI.

Verified Code

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

Tip: edit code and use “Run (Browser)”. Server runs always execute the published, verified snippet.
STDOUT
Inserted user ID: 1
User name for inserted ID 1 is: Alice
STDERR
(empty)

Was this helpful?

Related Questions