mysql's last_insert_id

Started by Michal Adamczakkover 22 years ago19 messagesgeneral
Jump to latest
#1Michal Adamczakk
pokryfka@artland.com.pl

hi,

how to implement mysql's last_insert_id() ?

i know that seqences and oids are great.
the one thing i miss is that they are not session specific.

i mean selecting last_value from seqence can give me a value which was
inserted by a different user.

regards
Michal

#2Michal Adamczakk
pokryfka@artland.com.pl
In reply to: Michal Adamczakk (#1)
Re: mysql's last_insert_id

k, i found:

curval/nextval/...

iwas misled for almost everyone writes to use last_value in 'conversion
howto' which i believe is wrong

using pgsql is a pleasure

#3Eric Johnson
ej@ejinnovations.com
In reply to: Michal Adamczakk (#1)
Re: mysql's last_insert_id

I'm doing this in an app right now by using stored procedures and sequences.
The stored procedure for a table will get the next value of the sequence and
use that in the insert statement. It then returns that id as the result so
the application can use it elsewhere.

Eric Johnson

----- Original Message -----
From: "Michal Adamczakk" <pokryfka@artland.com.pl>
To: <pgsql-general@postgresql.org>
Sent: Friday, August 22, 2003 3:03 PM
Subject: [GENERAL] mysql's last_insert_id

Show quoted text

hi,

how to implement mysql's last_insert_id() ?

i know that seqences and oids are great.
the one thing i miss is that they are not session specific.

i mean selecting last_value from seqence can give me a value which was
inserted by a different user.

regards
Michal

---------------------------(end of broadcast)---------------------------
TIP 6: Have you searched our list archives?

http://archives.postgresql.org

#4Bruno BAGUETTE
pgsql-ml@baguette.net
In reply to: Michal Adamczakk (#1)
RE : mysql's last_insert_id

Hello,

how to implement mysql's last_insert_id() ?

i know that seqences and oids are great.
the one thing i miss is that they are not session specific.
i mean selecting last_value from seqence can give me a value
which was inserted by a different user.

Am I wrong or do you misunderstand the documentation about sequences ?

If you read the documentation about the sequences functions
(http://www.postgresql.org/docs/view.php?version=7.3&amp;idoc=1&amp;file=functio
ns-sequence.html), you can see that the currval functions return the
value most recently obtained by nextval for this sequence IN THE CURRENT
SESSION. (An error is reported if nextval has never been called for this
sequence in this session.) Notice that because this is returning a
session-local value, it gives a predictable answer even if other
sessions are executing nextval meanwhile.

So, if you need to do two inserts where you have to add the new added
sequence value, you can do something like :

INSERT INTO authors (pk_author_id,lastname,firstname) VALUES
(NEXTVAL('seq_author_id'),'Baguette','Bruno');
INSERT INTO books (fk_author_id,title) VALUES
(CURRVAL('seq_author_id'),'Deafness related bibliography');

Hope this helps :-)

Regards,

---------------------------------------
Bruno BAGUETTE - pgsql-ml@baguette.net

#5deststar
deststar@blueyonder.co.uk
In reply to: Michal Adamczakk (#1)
Re: mysql's last_insert_id

Michal Adamczakk wrote:

hi,

how to implement mysql's last_insert_id() ?

i know that seqences and oids are great.
the one thing i miss is that they are not session specific.

i mean selecting last_value from seqence can give me a value which was
inserted by a different user.

regards
Michal

The currval('seq_name') returns the last for the specific connection,
not the last returned of any
hth,
- Stuart

#6Bo Lorentsen
bl@netgroup.dk
In reply to: Michal Adamczakk (#1)
Re: mysql's last_insert_id

On Fri, 2003-08-22 at 22:03, Michal Adamczakk wrote:

how to implement mysql's last_insert_id() ?

You will be able to use the "PQoidValue" function that returns the last
inserted row oid, just after an insert command.

Then if you want the newly inserted row you do something like this
"SELECT * FROM table_name WHERE oid=42", where 42 is the oid number
returned from the "PQoidValue".

Now ... I know that its possible to omit the oid's from large tables,
and then this method will not work anymore. What to do in this case
still eludes me (Anyone ?) :-)

/BL

#7Dennis Bjorklund
db@zigo.dhs.org
In reply to: Bo Lorentsen (#6)
Re: mysql's last_insert_id

On 28 Aug 2003, Bo Lorentsen wrote:

Now ... I know that its possible to omit the oid's from large tables,
and then this method will not work anymore. What to do in this case
still eludes me (Anyone ?) :-)

Yes, never use the oid at all is my suggestion.

If you need a unique id for a row then add a serial column that will
provide that, and use currval('the_sequence') to get the last inserted
value in that column for a session.

--
/Dennis

#8Bo Lorentsen
bl@netgroup.dk
In reply to: Dennis Bjorklund (#7)
Re: mysql's last_insert_id

On Thu, 2003-08-28 at 10:02, Dennis Bj�rklund wrote:

Yes, never use the oid at all is my suggestion.

Hmm, will oid's not change so that they are unique regardless, or will
oid be removed.

If you need a unique id for a row then add a serial column that will
provide that, and use currval('the_sequence') to get the last inserted
value in that column for a session.

This is just not a general solution to this problem, and will need
awareness of the id type in the application layer.

/BL

#9Martijn van Oosterhout
kleptog@svana.org
In reply to: Bo Lorentsen (#8)
Re: mysql's last_insert_id

On Thu, Aug 28, 2003 at 02:52:57PM +0200, Bo Lorentsen wrote:

On Thu, 2003-08-28 at 10:02, Dennis Björklund wrote:

Yes, never use the oid at all is my suggestion.

Hmm, will oid's not change so that they are unique regardless, or will
oid be removed.

OIDs have never beebn unique, it's just that most databases never get big
enough to experience wraparound. They are also now optional per table and
may soon no longer be available by default.

If you need a unique id for a row then add a serial column that will
provide that, and use currval('the_sequence') to get the last inserted
value in that column for a session.

This is just not a general solution to this problem, and will need
awareness of the id type in the application layer.

There are various solutions. Some people use functions to do inserts, I just
use the string "currval(whatever)" in the application layer which the
database replaces with the appropriate value.

Whatever works for you.
--
Martijn van Oosterhout <kleptog@svana.org> http://svana.org/kleptog/

Show quoted text

"All that is needed for the forces of evil to triumph is for enough good
men to do nothing." - Edmond Burke
"The penalty good people pay for not being interested in politics is to be
governed by people worse than themselves." - Plato

#10Bo Lorentsen
bl@netgroup.dk
In reply to: Martijn van Oosterhout (#9)
Re: mysql's last_insert_id

On Fri, 2003-08-29 at 04:11, Martijn van Oosterhout wrote:

OIDs have never beebn unique, it's just that most databases never get big
enough to experience wraparound. They are also now optional per table and
may soon no longer be available by default.

Ok, that may break some of my code :-( But as long as oid's are enabled
and are unique for the current table, I'm happy.

I made a general insert (executeUpdate) function to my general DB layer,
that returned the newly inserted row (to be able to use the default
initealized elements). This code will stop working when oid is disabled,
very sad thing.

I will have to push this row awareness to a higher level in the future.

But, how does PG refer to rows internally, and why can't we get this
reference in the application layer. I don't care if its an integer, long
or even a string, but I like to know the unique id of the currently and
newly inserted row, without knowing the datamodel (table layout).

There are various solutions. Some people use functions to do inserts, I just
use the string "currval(whatever)" in the application layer which the
database replaces with the appropriate value.

Hmm, but what happends if more than one connection does this at the same
time ? Then, only one of the concurrent connections will have a insert
on the returned value, and the rest will get a wrong row reference
returned.

The only safe methode would be to do a "select nextval(whatever)", and
aply this number by "hand" to the insert, but that remove the
possibility to make general code even more, but it will be safe.

/BL

#11Dennis Bjorklund
db@zigo.dhs.org
In reply to: Bo Lorentsen (#10)
Re: mysql's last_insert_id

On 29 Aug 2003, Bo Lorentsen wrote:

There are various solutions. Some people use functions to do inserts,
I just use the string "currval(whatever)" in the application layer
which the database replaces with the appropriate value.

Hmm, but what happends if more than one connection does this at the same
time ? Then, only one of the concurrent connections will have a insert
on the returned value, and the rest will get a wrong row reference
returned.

That is not a problem, it's perfectly safe. It's all described in

http://www.postgresql.org/docs/7.3/static/functions-sequence.html

Basicly, currval() gives the last id for that sequence in that session. So
other sessions does not break anything.

The only safe methode would be to do a "select nextval(whatever)", and
aply this number by "hand" to the insert, but that remove the
possibility to make general code even more, but it will be safe.

It's not needed. The following works fine (if the tables exists of course)
and has no problems with concurrency:

INSERT INTO foo(id,x) VALUES (DEFAULT, 'value');
INSERT INTO bar(id,foo_ref) VALUES (DEFAULT, currval('foo_id_seq'));

--
/Dennis

#12Martijn van Oosterhout
kleptog@svana.org
In reply to: Bo Lorentsen (#10)
Re: mysql's last_insert_id

On Fri, Aug 29, 2003 at 08:36:50AM +0200, Bo Lorentsen wrote:

I made a general insert (executeUpdate) function to my general DB layer,
that returned the newly inserted row (to be able to use the default
initealized elements). This code will stop working when oid is disabled,
very sad thing.

I will have to push this row awareness to a higher level in the future.

Not really, the sequences have very predicatble names. For tables X with
primary key Y, the sequence is usually called X_Y_seq.

But, how does PG refer to rows internally, and why can't we get this
reference in the application layer. I don't care if its an integer, long
or even a string, but I like to know the unique id of the currently and
newly inserted row, without knowing the datamodel (table layout).

Oh, there's a CTID but that doesn't keep over an update and isn't
transaction safe anyway. Mind, you could always just call your sequences
seq_<TABLENAME>, then you wouldn't have to guess. This is how DCL does it.

There are various solutions. Some people use functions to do inserts, I just
use the string "currval(whatever)" in the application layer which the
database replaces with the appropriate value.

Hmm, but what happends if more than one connection does this at the same
time ? Then, only one of the concurrent connections will have a insert
on the returned value, and the rest will get a wrong row reference
returned.

Wrong. What gave you that impression? nextval() and currval() work fine with
transactions, look through the docs.

The only safe methode would be to do a "select nextval(whatever)", and
aply this number by "hand" to the insert, but that remove the
possibility to make general code even more, but it will be safe.

Like I said, currval() will do what you want. Make predicatable names for
your sequences and you won't need to worry about it anymore.

--
Martijn van Oosterhout <kleptog@svana.org> http://svana.org/kleptog/

Show quoted text

"All that is needed for the forces of evil to triumph is for enough good
men to do nothing." - Edmond Burke
"The penalty good people pay for not being interested in politics is to be
governed by people worse than themselves." - Plato

#13Bo Lorentsen
bl@netgroup.dk
In reply to: Dennis Bjorklund (#11)
Re: mysql's last_insert_id

On Fri, 2003-08-29 at 09:05, Dennis Bj�rklund wrote:

That is not a problem, it's perfectly safe. It's all described in

http://www.postgresql.org/docs/7.3/static/functions-sequence.html

Ups, nice that ...

currval will generate an error if nextval is not called in current
session, insuring :-)

But, I still need to be aware of the datamodel.

/BL

#14Dennis Bjorklund
db@zigo.dhs.org
In reply to: Bo Lorentsen (#13)
Re: mysql's last_insert_id

On 29 Aug 2003, Bo Lorentsen wrote:

currval will generate an error if nextval is not called in current
session, insuring :-)

Yea, that is a good thing. It gives you the last generated id in your
session. If you have never generated an id with nextval() there is no id
to give you. It can't just give you an id from another session, now can
it.

--
/Dennis

#15Dennis Gearon
gearond@fireserve.net
In reply to: Dennis Bjorklund (#11)
Re: mysql's last_insert_id

Dennis Bj�rklund wrote:

It's not needed. The following works fine (if the tables exists of course)
and has no problems with concurrency:

INSERT INTO foo(id,x) VALUES (DEFAULT, 'value');
INSERT INTO bar(id,foo_ref) VALUES (DEFAULT, currval('foo_id_seq'));

You don't even need the 'DEFAULT' word as I remember, but it makes for
easier code to follow.

#16Bo Lorentsen
bl@netgroup.dk
In reply to: Martijn van Oosterhout (#9)
Re: mysql's last_insert_id

On Fri, 2003-08-29 at 04:11, Martijn van Oosterhout wrote:

OIDs have never beebn unique, it's just that most databases never get big
enough to experience wraparound. They are also now optional per table and
may soon no longer be available by default.

It would be a god idea to remove the oid reference from the FAQ
4.15.2, to make sure no one in the futhere makes my mistake again :-)

/BL

#17Bruce Momjian
bruce@momjian.us
In reply to: Bo Lorentsen (#16)
Re: mysql's last_insert_id

Bo Lorentsen wrote:

On Fri, 2003-08-29 at 04:11, Martijn van Oosterhout wrote:

OIDs have never beebn unique, it's just that most databases never get big
enough to experience wraparound. They are also now optional per table and
may soon no longer be available by default.

It would be a god idea to remove the oid reference from the FAQ
4.15.2, to make sure no one in the futhere makes my mistake again :-)

I have added the last clause to the FAQ:

Finally, you could use the <A href="#4.16"><SMALL>OID</SMALL></A>
returned from the <SMALL>INSERT</SMALL> statement to look up the
default value, though this is probably the least portable approach,
and the oid value will wrap around when it reaches 4 billion.

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
#18Bo Lorentsen
bl@netgroup.dk
In reply to: Bruce Momjian (#17)
Re: mysql's last_insert_id

On Mon, 2003-09-01 at 18:47, Bruce Momjian wrote:

I have added the last clause to the FAQ:

Are there not a case where a table does not relate to a oid anymore ? In
that case, it does not work at all :-)

/BL

#19Bruce Momjian
bruce@momjian.us
In reply to: Bo Lorentsen (#18)
Re: mysql's last_insert_id

Bo Lorentsen wrote:

On Mon, 2003-09-01 at 18:47, Bruce Momjian wrote:

I have added the last clause to the FAQ:

Are there not a case where a table does not relate to a oid anymore ? In
that case, it does not work at all :-)

Yes, if you create a table without oids, yes, it isn't going to work,
but if you did that, I assume you already would know that the oid will
not be there.

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073