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
Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.
Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.
Lost your password? Please enter your email address. You will receive a link and will create a new password via email.
Please briefly explain why you feel this question should be reported.
Please briefly explain why you feel this answer should be reported.
Please briefly explain why you feel this user should be reported.
(
tl;dr: goto option 3: INSERT with RETURNING )Recall that in postgresql there is no “id” concept for tables, just sequences (which are typically but not necessarily used as default values for surrogate primary keys, with the SERIAL pseudo-type).
If you are interested in getting the id of a newly inserted row, there are several ways:
Option 1:
CURRVAL(<sequence name>);.For example:
The name of the sequence must be known, it’s really arbitrary; in this example we assume that the table
personshas anidcolumn created with theSERIALpseudo-type. To avoid relying on this and to feel more clean, you can use insteadpg_get_serial_sequence:Caveat:
currval()only works after anINSERT(which has executednextval()), in the same session.Option 2:
LASTVAL();This is similar to the previous, only that you don’t need to specify the sequence name: it looks for the most recent modified sequence (always inside your session, same caveat as above).
Both
CURRVALandLASTVALare totally concurrent safe. The behaviour of sequence in PG is designed so that different session will not interfere, so there is no risk of race conditions (if another session inserts another row between my INSERT and my SELECT, I still get my correct value).However they do have a subtle potential problem. If the database has some TRIGGER (or RULE) that, on insertion into
personstable, makes some extra insertions in other tables… thenLASTVALwill probably give us the wrong value. The problem can even happen withCURRVAL, if the extra insertions are done intto the samepersonstable (this is much less usual, but the risk still exists).Option 3:
INSERTwithRETURNINGThis is the most clean, efficient and safe way to get the id. It doesn’t have any of the risks of the previous.
Drawbacks? Almost none: you might need to modify the way you call your INSERT statement (in the worst case, perhaps your API or DB layer does not expect an INSERT to return a value); it’s not standard SQL (who cares); it’s available since Postgresql 8.2 (Dec 2006…)
Conclusion: If you can, go for option 3. Elsewhere, prefer 1.
Note: all these methods are useless if you intend to get the last inserted id globally (not necessarily by your session). For this, you must resort to
SELECT max(id) FROM table(of course, this will not read uncommitted inserts from other transactions).Conversely, you should never use
SELECT max(id) FROM tableinstead one of the 3 options above, to get the id just generated by yourINSERTstatement, because (apart from performance) this is not concurrent safe: between yourINSERTand yourSELECTanother session might have inserted another record.