currval is throwing the error because the sequence hasn't been used in that
session/connection. currval returns the most recent allocated value which is
cached, but not necessarily the next value -1.
Sequences don't have to increment by 1, so if you have multiple concurrent
connections (as I'll show in a moment) the select may not give the correct
result (the race condition you noticed).
The cases where you would (at creation time) set the increment to more than
1 is when you know that in a transaction you'll be allocating multiple
sequence values. Instead of updating the sequence table for each insert, you
allocate a block (say for example 10) of numbers. Another connection would
get the next block of 10, and your connection can safely allocate from the
remaining numbers in the cached block. Cuts down a lot of disk acceses.
Anyhow, here's a real life example of how I use currval. Ok, this is PHP but
you'll get the idea.
This little section of code is used on one of our new websites going live at
the end of the month (and in some ways is one of the other reasons why I'm
behind with JDBC ;-) ). This bit is called when someone is creating a new
user account. Each user is actually stored in three tables (performance
There is a sequence 'users_uid_seq' which lives in the main 'users' table,
but is also the primary key in the userinfo and usercomments tables. Here we
have a transaction where the sequence is updated when the first insert is
done, but we need the allocated value to ensure that the next two inserts
$res=pg_Exec("insert into users
$res=pg_Exec("insert into userinfo
$res=pg_Exec("insert into usercomments
// redir here
$res=pg_Exec("select currval('users_uid_seq') as a");
$date=date("l, d-M-y H:i:s",($time));
Enterprise Support Officer, Maidstone Borough Council
All views expressed within this email are not the views of Maidstone Borough
From: Mark Dzmura [mailto:mdz(at)digital-mission(dot)com]
Sent: Thursday, September 07, 2000 4:15 AM
Subject: [INTERFACES] obtaining primary key/rowid following insert,
Trying to solve my problem mentioned in the email of half an hour ago, I
through the archives of the interface list and found some of your replies
using "currval()" to get the last value assigned from a sequence...
here's what happens in a good database with multiple in-use sequences:
db=# select currval('foo_foo_id_seq');
ERROR: foo_foo_id_seq.currval is not yet defined in this session
As an alternative, I discovered that I can get the value this way:
db=# select last_value from foo_foo_id_seq;
My questions are, (1) why does the currval() approach give the error
(2) is it OK to use my alternative??
Finally, as far as I can tell, there is a real race condition problem here
in a multiple-connection
scenario (e.g. another task can cause the sequence to be incremented between
and the select) - but wrapping a transaction around the insert and select
take care of it... Thoughts??
pgsql-interfaces by date
|Next:||From: Tatsuo Ishii||Date: 2000-09-11 07:13:29|
|Subject: RE: JDBC and Unicode problem|
|Previous:||From: Zeljko Trogrlic||Date: 2000-09-11 07:03:07|
|Subject: Re: obtaining primary key/rowid following insert,