[postgresql] PostgreSQL function for last inserted ID

In PostgreSQL, how do I get the last id inserted into a table?

In MS SQL there is SCOPE_IDENTITY().

Please do not advise me to use something like this:

select max(id) from table

This question is related to postgresql insert lastinsertid

The answer is


Leonbloy's answer is quite complete. I would only add the special case in which one needs to get the last inserted value from within a PL/pgSQL function where OPTION 3 doesn't fit exactly.

For example, if we have the following tables:

CREATE TABLE person(
   id serial,
   lastname character varying (50),
   firstname character varying (50),
   CONSTRAINT person_pk PRIMARY KEY (id)
);

CREATE TABLE client (
    id integer,
   CONSTRAINT client_pk PRIMARY KEY (id),
   CONSTRAINT fk_client_person FOREIGN KEY (id)
       REFERENCES person (id) MATCH SIMPLE
);

If we need to insert a client record we must refer to a person record. But let's say we want to devise a PL/pgSQL function that inserts a new record into client but also takes care of inserting the new person record. For that, we must use a slight variation of leonbloy's OPTION 3:

INSERT INTO person(lastname, firstname) 
VALUES (lastn, firstn) 
RETURNING id INTO [new_variable];

Note that there are two INTO clauses. Therefore, the PL/pgSQL function would be defined like:

CREATE OR REPLACE FUNCTION new_client(lastn character varying, firstn character varying)
  RETURNS integer AS
$BODY$
DECLARE
   v_id integer;
BEGIN
   -- Inserts the new person record and retrieves the last inserted id
   INSERT INTO person(lastname, firstname)
   VALUES (lastn, firstn)
   RETURNING id INTO v_id;

   -- Inserts the new client and references the inserted person
   INSERT INTO client(id) VALUES (v_id);

   -- Return the new id so we can use it in a select clause or return the new id into the user application
    RETURN v_id;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE;

Now we can insert the new data using:

SELECT new_client('Smith', 'John');

or

SELECT * FROM new_client('Smith', 'John');

And we get the newly created id.

new_client
integer
----------
         1

Try this:

select nextval('my_seq_name');  // Returns next value

If this return 1 (or whatever is the start_value for your sequence), then reset the sequence back to the original value, passing the false flag:

select setval('my_seq_name', 1, false);

Otherwise,

select setval('my_seq_name', nextValue - 1, true);

This will restore the sequence value to the original state and "setval" will return with the sequence value you are looking for.


you can use RETURNING clause in INSERT statement,just like the following

wgzhao=# create table foo(id int,name text);
CREATE TABLE
wgzhao=# insert into foo values(1,'wgzhao') returning id;
 id 
----
  1
(1 row)

INSERT 0 1
wgzhao=# insert into foo values(3,'wgzhao') returning id;
 id 
----
  3
(1 row)

INSERT 0 1

wgzhao=# create table bar(id serial,name text);
CREATE TABLE
wgzhao=# insert into bar(name) values('wgzhao') returning id;
 id 
----
  1
(1 row)

INSERT 0 1
wgzhao=# insert into bar(name) values('wgzhao') returning id;
 id 
----
  2
(1 row)

INSERT 0 

Based on @ooZman 's answer above, this seems to work for PostgreSQL v12 when you need to INSERT with the next value of a "sequence" (akin to auto_increment) without goofing anything up in your table(s) counter(s). (Note: I haven't tested it in more complex DB cluster configurations though...)

Psuedo Code

$insert_next_id = $return_result->query(" select (setval('"your_id_seq"', (select nextval('"your_id_seq"')) - 1, true)) +1; ")


I had this issue with Java and Postgres. I fixed it by updating a new Connector-J version.

postgresql-9.2-1002.jdbc4.jar

https://jdbc.postgresql.org/download.html: Version 42.2.12

https://jdbc.postgresql.org/download/postgresql-42.2.12.jar


See the below example

CREATE TABLE users (
    -- make the "id" column a primary key; this also creates
    -- a UNIQUE constraint and a b+-tree index on the column
    id    SERIAL PRIMARY KEY,
    name  TEXT,
    age   INT4
);

INSERT INTO users (name, age) VALUES ('Mozart', 20);

Then for getting last inserted id use this for table "user" seq column name "id"

SELECT currval(pg_get_serial_sequence('users', 'id'));

See the RETURNING clause of the INSERT statement. Basically, the INSERT doubles as a query and gives you back the value that was inserted.


You can use RETURNING id after insert query.

INSERT INTO distributors (id, name) VALUES (DEFAULT, 'ALI') RETURNING id;

and result:

 id 
----
  1

In the above example id is auto-increment filed.


SELECT CURRVAL(pg_get_serial_sequence('my_tbl_name','id_col_name'))

You need to supply the table name and column name of course.

This will be for the current session / connection http://www.postgresql.org/docs/8.3/static/functions-sequence.html


For the ones who need to get the all data record, you can add

returning *

to the end of your query to get the all object including the id.


Postgres has an inbuilt mechanism for the same, which in the same query returns the id or whatever you want the query to return. here is an example. Consider you have a table created which has 2 columns column1 and column2 and you want column1 to be returned after every insert.

# create table users_table(id serial not null primary key, name character varying);
CREATE TABLE
#insert into users_table(name) VALUES ('Jon Snow') RETURNING id;?
 id 
----
  1
(1 row)

# insert into users_table(name) VALUES ('Arya Stark') RETURNING id;?
 id 
----
  2
(1 row)