How do I use currval() in PostgreSQL to get the last inserted id?
If you create a column as serial
PostgreSQL automatically creates a sequence for that.
The name of the sequence is autogenerated and is always tablename_columnname_seq, in your case the sequence will be names names_id_seq
.
After inserting into the table, you can call currval()
with that sequence name:
postgres=> CREATE TABLE names in schema_name (id serial, name varchar(20));
CREATE TABLE
postgres=> insert into names (name) values ('Arthur Dent');
INSERT 0 1
postgres=> select currval('names_id_seq');
currval
---------
1
(1 row)
postgres=>
Instead of hardcoding the sequence name, you can also use pg_get_serial_sequence()
instead:
select currval(pg_get_serial_sequence('names', 'id'));
That way you don't need to rely on the naming strategy Postgres uses.
Or if you don't want to use the sequence name at all, use lastval()
This is straight from Stack Overflow
As it was pointed out by @a_horse_with_no_name and @Jack Douglas, currval works only with the current session. So if you are ok with the fact that the result might be affected by an uncommitted transaction of another session, and you still want something that will work across sessions, you can use this:
SELECT last_value FROM your_sequence_name;
Use the link to SO for more information.
From Postgres documentation though, it is clearly stated that
It is an error to call lastval if nextval has not yet been called in the current session.
So I guess strictly speaking in order to properly use currval or last_value for a sequence across sessions, you would need to do something like that?
SELECT setval('serial_id_seq',nextval('serial_id_seq')-1);
Assuming, of course, that you will not have an insert or any other way of using the serial field in the current session.
You need to call nextval
for this sequence in this session before currval
:
create sequence serial;
select nextval('serial');
nextval
---------
1
(1 row)
select currval('serial');
currval
---------
1
(1 row)
so you cannot find the 'last inserted id' from the sequence unless the insert
is done in the same session (a transaction might roll back but the sequence will not)
as pointed out in a_horse's answer, create table
with a column of type serial
will automatically create a sequence and use it to generate the default value for the column, so an insert
normally accesses nextval
implicitly:
create table my_table(id serial);
NOTICE: CREATE TABLE will create implicit sequence "my_table_id_seq" for
serial column "my_table.id"
\d my_table
Table "stack.my_table"
Column | Type | Modifiers
--------+---------+-------------------------------------------------------
id | integer | not null default nextval('my_table_id_seq'::regclass)
insert into my_table default values;
select currval('my_table_id_seq');
currval
---------
1
(1 row)