http://www.perlmonks.org?node_id=466693


in reply to Sequences, last_insert_id, SQLite, and Oracle

The way that you do this *correctly* in oracle is to make use of its "returning" clause, and the DBI's bind_param_in_out() method. This is the only way to properly avoid concurrency issues, and it also works cleanly and is fast.

In code, it looks something like this:

my $sql = "insert into foo (name,value) values (?,?) returning id into + ?"; my $sth = $dbh->prepare($sql); $sth->bind_param(0, $name); $sth->bind_param(1, $value); $sth->bind_param_inout(2, \$id, 1024); # this is a reference that gets + written to! $sth->execute; print $id; # or whatever... $id has been written into by the execute
Assuming that the id column is driven by a sequence and a trigger.

Granted, doing individual calls to bind_param / bind_param_inout is kind of painful and ugly, so when I do this I actually written a wrapper around calling all the binding, but this is the crux of what it does / how it works.

------------ :Wq Not an editor command: Wq

Replies are listed 'Best First'.
Re^2: Sequences, last_insert_id, SQLite, and Oracle
by gaal (Parson) on Jun 15, 2005 at 03:48 UTC
    This looks like a nice technique. A couple of questions:
    1. What's the DML for the id field?
    2. What's the SQLite equivalent? (If there is one.)
    3. Aren't Oracle sequences safe to use unlocked from within a transaction? I was under the impression that they do work that way, so I can request a sequence and then use it. Obviously slower than what you do above, but a little more straightforward. Hmmmm, is your id just that, a sequence?
    Thanks!
      Yes, you can do this by accessing the sequence, and then inserting that value (explicitly), as two sequential statements in a transaction. What I was referring to was the standard oracle method of defining a sequence and using an on-insert trigger to bind the sequence to the id column of the table (so that inserts *implicitly* fetch from the sequence). For the case of the sequence used in a trigger (thus your code is not directly accessing the sequence), this is The Way. However, if you're not using triggers to pull from your sequence implicitly, then you can certainly fetch from the sequence and just use that value.
      ------------ :Wq Not an editor command: Wq