last_insert_id() is generally only useful directly after a (successful) INSERT, and even then the exact semantics are riddled with potential pitfalls, especially if you're writing a portable application (see the DBI docs for details.) For MySQL (and incidentally SQLite too) you can list all 4 params to last_insert_id as undef, or more commonly the blank string for brevity, and it should do what you expect, even in transactions. (PostgreSQL gives you the RETURNING clause, which is even better if you can design for that RDBMS.)
Remember to put the rollback inside an eval block too as it may also fail, especially if the handle is now defunct for some reason (connection error or the like.)
I'd also suggest use of Carp::confess() or Carp::croak() so that you can point to a the specific Perl line that caused the error to be thrown inside the eval block.
If you're still having problems, posting a minimal reproduction, including the most basic SQL schema you can design to show the problem, is likely required.
This seems to work as expected for me, printing incrementing PK values for the id column:
use strict; use warnings; use DBI; use Carp qw( confess croak ); my $dbh = DBI->connect( "DBI:mysql:db=test1001;host=localhost", "pm", "correcthorsebatterystaple", { RaiseError => 1, AutoCommit => 0, PrintError => 0, # do our own error handling. } ) or die "DB connect: $DBI::errstr"; eval { $dbh->do(q[ INSERT INTO ref(color) VALUES (?) ], undef, 'blue'); my $last_ref = $dbh->last_insert_id('','','',''); printf STDERR "last ref: %s\n", $last_ref; $dbh->do(q[ INSERT INTO t1(ref_id) VALUES (?) ], undef, $last_ref) +; my $last_t1 = $dbh->last_insert_id('','','',''); printf STDERR "last t1: %s\n", $last_t1; $dbh->commit; }; if ($@) { my $err = $@; # save $@, as rolling back below could also fail. # attempt to rollback, which could also fail. eval { $dbh->rollback; } if ($dbh); confess( "DB error: $err" ); } __END__ Schema used for the test1001 DB is as follows: CREATE DATABASE test1001; use test1001; GRANT ALL ON test1001.* TO pm; CREATE TABLE ref( id BIGINT PRIMARY KEY AUTO_INCREMENT, color TEXT ); CREATE TABLE t1( id BIGINT PRIMARY KEY AUTO_INCREMENT, ref_id BIGINT REFERENCES ref(id) ON DELETE CASCADE ON UPDATE CASCADE );
In reply to Re: Perl msyql last_insert_id works once?
by Apero
in thread Perl msyql last_insert_id works once?
by Anonymous Monk
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |