From: | rob stone <floriparob(at)gmail(dot)com> |
---|---|
To: | Albe Laurenz <laurenz(dot)albe(at)wien(dot)gv(dot)at> |
Cc: | Anil Menon <gakmenon(at)gmail(dot)com>, "pgsql-general(at)postgresql(dot)org" <pgsql-general(at)postgresql(dot)org> |
Subject: | Re: Referencing serial col's sequence for insert |
Date: | 2014-07-22 14:30:55 |
Message-ID: | 1406039455.2414.31.camel@roblaptop.virtua.com.br |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-general |
On Tue, 2014-07-22 at 13:32 +0000, Albe Laurenz wrote:
> rob stone wrote:
> >> I have a question on the right/correct practice on using the serial
> >> col's sequence for insert.
> >>
> >> Best way of explanation is by an example:
> >>
> >> create table id01 (col1 serial, col2 varchar(10));
> >>
> >> insert into id01(col2) values ( 'data'||
> >> currval('id01_col1_seq')::varchar);
> >>
> >> while I do get what I want:
> >>
> >> select * from id01;
> >> col1 | col2
> >> ------+-------
> >> 1 | data1
> >>
> >> Is this guaranteed to work : I am assuming that an insert triggers the
> >> id01_col1_seq's nextval first hence using
> >> id01_col1_seq's currval subsequently will have the "correct" /
> >> expected value (and not the previous value before the insert).
> >>
> >> Is my assumption correct?
>
> > I would do the following:-
> >
> > create table id01 (col1 serial NOT NULL PRIMARY KEY, col2 varchar(10));
> >
> > In a try . . catch block:-
> >
> > BEGIN;
> > INSERT INTO id01 (col2) VALUES ('data');
> > SELECT lastval() AS last_row_id;
> > COMMIT; or ROLLBACK; if you have errors.
> >
> > There is also "insert . . returning" syntax which can make the value
> > assigned to the serial column available to your application. I prefer
> > using the "select lastval()" method.
>
> Your example seems incomplete.
>
> Also, I think that your method is vulnerable to race conditions:
> If somebody else increments the sequence between the INSERT and
> "SELECT lastval()" you'd get a wrong value.
>
> The same might hold for the original example.
>
> I would suggest something like that:
>
> WITH seq(i) AS (SELECT nextval('id01_col1_seq'))
> INSERT INTO id01 (col1, col2) (SELECT i, 'data' || i FROM seq);
>
> Yours,
> Laurenz Albe
Hi Laurenz,
The documentation in chapter 9.16 says otherwise.
SELECT lastval() may only be called after a nextval which is issued
implicitly by the INSERT statement as a column is defined as SERIAL.
As you are in transaction state (via BEGIN;) I don't believe that
another process accessing the same sequence can upset the SELECT
lastval(). I could be wrong but I don't have the means to test this out.
Regards,
Rob
From | Date | Subject | |
---|---|---|---|
Next Message | Torsten Förtsch | 2014-07-22 14:44:48 | Re: check database integrity |
Previous Message | David G Johnston | 2014-07-22 14:24:42 | Re: Referencing serial col's sequence for insert |