Thread: nextval() clarification

nextval() clarification

From
Greg Donald
Date:
Long time MySQL user, six weeks into Postgres here.

I'm converting a PHP script that uses MySQL to use Postgres instead.
To substitue the missing MySQL functionaility with mysql_insert_id()
and auto_increment I am using code like this:

$sql = "SELECT nextval('companies_company_id_seq'::text)";

And then I do my insert with that value.

It works fine but I don't understand why it always gives me a +1 value
of what I'm expecting.  For example when I have an empty table it
gives me 2 as the first nextval instead of a 1, or if I have two rows
in there already it gives me a 4.  Is this by design or am I missing
something?  It's not a problem I just want to know what's going on.

TIA..

--
Greg Donald
http://destiney.com/

Re: nextval() clarification

From
Sandip Bhattacharya
Date:
On Tuesday 14 Sep 2004 12:29 am, Greg Donald wrote:
> $sql = "SELECT nextval('companies_company_id_seq'::text)";
>
> And then I do my insert with that value.
>
> It works fine but I don't understand why it always gives me a +1 value
> of what I'm expecting.  For example when I have an empty table it
> gives me 2 as the first nextval instead of a 1, or if I have two rows
> in there already it gives me a 4.  Is this by design or am I missing
> something?  It's not a problem I just want to know what's going on.
>

I new to postgresql too. :)

Even in MySQL, the auto_increment value for a field in the table is kept
separately. I remember using phpmyadmin to change this value. This counter
will keep increasing no matter whether you table is shrinking or increasing.

Just guessing, that sequences in postgesql are kept as separate counters along
with the table, and will only keep on increasing. Postgresql will never check
how many records are there in the table while returning a vlue for this
sequence. Again, I am just guessing that this si teh behaviour. It doesnt
make sense for the databse to check all teh records to find out the value of
a simple counter.

- Sandip


--
Sandip Bhattacharya    *    Puroga Technologies   *     sandip@puroga.com
Work: http://www.puroga.com        *         Home: http://www.sandipb.net

PGP/GPG Signature: 51A4 6C57 4BC6 8C82 6A65 AE78 B1A1 2280 A129 0FF3

It's a naive, domestic operating system without any breeding, but I
think you'll be amused by its presumption.

Re: nextval() clarification

From
Oliver Elphick
Date:
On Mon, 2004-09-13 at 19:59, Greg Donald wrote:
> Long time MySQL user, six weeks into Postgres here.
>
> I'm converting a PHP script that uses MySQL to use Postgres instead.
> To substitue the missing MySQL functionaility with mysql_insert_id()
> and auto_increment I am using code like this:
>
> $sql = "SELECT nextval('companies_company_id_seq'::text)";
>
> And then I do my insert with that value.
>
> It works fine but I don't understand why it always gives me a +1 value
> of what I'm expecting.  For example when I have an empty table it
> gives me 2 as the first nextval instead of a 1, or if I have two rows
> in there already it gives me a 4.  Is this by design or am I missing
> something?  It's not a problem I just want to know what's going on.

I get the impression that you probably know this, but, just in case:
every time you use nextval(), the sequence is incremented.  If you
insert a record with a null value for the SERIAL field, nextval() will
be used to generate a value; if you use it again to find a value it will
increment again.  Once nextval() has been used once, whether by default
or directly, you  should then use currval() to get the value just
returned for the sequence.  You cannot use currval() until after
nextval() has been used in the same session.

I can't see from what you describe how you are managing to run nextval()
twice, but that must be happening somehow.  Perhaps you are using $sql
twice, in which case it will increment the sequence each time ??

--
Oliver Elphick                                          olly@lfix.co.uk
Isle of Wight                              http://www.lfix.co.uk/oliver
GPG: 1024D/A54310EA  92C8 39E7 280E 3631 3F0E  1EC0 5664 7A2F A543 10EA
                 ========================================
     "For my thoughts are not your thoughts, neither are
      your ways my ways, saith the LORD. For as the heavens
      are higher than the earth, so are my ways higher than
      your ways, and my thoughts than your thoughts."
                               Isaiah 55:8,9


Re: nextval() clarification

From
Aarni Ruuhimäki
Date:
Hi,

You don't have to select nextval separately. Just do an INSERT without the id
column (presuming it is declared as SERIAL when created) like:

INSERT INTO companies (company_name, company_whatever ) VALUES ( , );

Auto increment is indeed in a separate table that stores the next number in
the sequence, not the last one used. And yes, this will increase 'forever' no
matter how many rows there are or have been in your table.

If you want to reset or otherwise meddle with the sequence use:

>>
You need to do something like

        select setval('seq-name', (select max(col) + 1 from table));
>>

BR,

Aarni

On Monday 13 September 2004 22:08, you wrote:
> On Tuesday 14 Sep 2004 12:29 am, Greg Donald wrote:
> > $sql = "SELECT nextval('companies_company_id_seq'::text)";
> >
> > And then I do my insert with that value.
> >
> > It works fine but I don't understand why it always gives me a +1 value
> > of what I'm expecting.  For example when I have an empty table it
> > gives me 2 as the first nextval instead of a 1, or if I have two rows
> > in there already it gives me a 4.  Is this by design or am I missing
> > something?  It's not a problem I just want to know what's going on.
>
> I new to postgresql too. :)
>
> Even in MySQL, the auto_increment value for a field in the table is kept
> separately. I remember using phpmyadmin to change this value. This counter
> will keep increasing no matter whether you table is shrinking or
> increasing.
>
> Just guessing, that sequences in postgesql are kept as separate counters
> along with the table, and will only keep on increasing. Postgresql will
> never check how many records are there in the table while returning a vlue
> for this sequence. Again, I am just guessing that this si teh behaviour. It
> doesnt make sense for the databse to check all teh records to find out the
> value of a simple counter.
>
> - Sandip

--
-------------------------------------------------
Aarni Ruuhimäki | Megative Tmi | KYMI.com |
Pääsintie 26 | 45100 Kouvola | FINLAND |
www.kymi.com | cfm.kymi.com |
aarni@kymi.com | info@kymi.com |
+358-5-3755 035 | +358-50-4910 037
-------------------------------------------------
This is a bugfree broadcast to you from a linux system.

Re: nextval() clarification

From
Ennio-Sr
Date:
* Greg Donald <destiney@gmail.com> [130904, 13:59]:
> Long time MySQL user, six weeks into Postgres here.
>
> I'm converting a PHP script that uses MySQL to use Postgres instead.
> To substitue the missing MySQL functionaility with mysql_insert_id()
> and auto_increment I am using code like this:
>
> $sql = "SELECT nextval('companies_company_id_seq'::text)";
>
> And then I do my insert with that value.
> [ cut ]

I think you should put <nextval(....)> directly into the INSERT
instruction, so that it advances only once per added record.
Have a look at Documentation PostgreSQL 7.4, Ch 9.11, table 9.34.
HTH
    Regards, Ennio

--
[Perche' usare Win$ozz (dico io) se ..."anche uno sciocco sa farlo.     \\?//
 Fa' qualche cosa di cui non sei capace!"   (diceva Henry Miller) ]     (°|°)
[Why to use Win$ozz (I say) if ... "even a fool can do that.             )=(
 Do something you aren't good at!" (used to say Henry Miller) ]

Re: nextval() clarification

From
Aarni Ruuhimäki
Date:
Bah,

Just the other way around. Sequence storing the last value used.

dataguard=# SELECT * FROM langs_lang_id_seq;
   sequence_name   | last_value | increment_by |      max_value      |
min_value | cache_value | log_cnt | is_cycled | is_called

-------------------+------------+--------------+---------------------+-----------+-------------+---------+-----------+-----------
 langs_lang_id_seq |         12 |            1 | 9223372036854775807 |
1 |           1 |       0 | f         | t
(1 row)



INSERT INTO lang(lang_name, lang_show, default_lang)
VALUES('#lang_name#', '#lang_show#', '#default_lang#')



dataguard=# SELECT * FROM langs_lang_id_seq;
   sequence_name   | last_value | increment_by |      max_value      |
min_value | cache_value | log_cnt | is_cycled | is_called

-------------------+------------+--------------+---------------------+-----------+-------------+---------+-----------+-----------
 langs_lang_id_seq |         13 |            1 | 9223372036854775807 |
1 |           1 |      32 | f         | t
(1 row)


Sorry...,

Aarni

On Monday 13 September 2004 22:47, you wrote:
> Hi,
>
> You don't have to select nextval separately. Just do an INSERT without the
> id column (presuming it is declared as SERIAL when created) like:
>
> INSERT INTO companies (company_name, company_whatever ) VALUES ( , );
>
> Auto increment is indeed in a separate table that stores the next number in
> the sequence, not the last one used. And yes, this will increase 'forever'
> no matter how many rows there are or have been in your table.
>
> If you want to reset or otherwise meddle with the sequence use:
>
>
> You need to do something like
>
>         select setval('seq-name', (select max(col) + 1 from table));
>
>
> BR,
>
> Aarni
>
> On Monday 13 September 2004 22:08, you wrote:
> > On Tuesday 14 Sep 2004 12:29 am, Greg Donald wrote:
> > > $sql = "SELECT nextval('companies_company_id_seq'::text)";
> > >
> > > And then I do my insert with that value.
> > >
> > > It works fine but I don't understand why it always gives me a +1 value
> > > of what I'm expecting.  For example when I have an empty table it
> > > gives me 2 as the first nextval instead of a 1, or if I have two rows
> > > in there already it gives me a 4.  Is this by design or am I missing
> > > something?  It's not a problem I just want to know what's going on.
> >
> > I new to postgresql too. :)
> >
> > Even in MySQL, the auto_increment value for a field in the table is kept
> > separately. I remember using phpmyadmin to change this value. This
> > counter will keep increasing no matter whether you table is shrinking or
> > increasing.
> >
> > Just guessing, that sequences in postgesql are kept as separate counters
> > along with the table, and will only keep on increasing. Postgresql will
> > never check how many records are there in the table while returning a
> > vlue for this sequence. Again, I am just guessing that this si teh
> > behaviour. It doesnt make sense for the databse to check all teh records
> > to find out the value of a simple counter.
> >
> > - Sandip

--
-------------------------------------------------
Aarni Ruuhimäki | Megative Tmi | KYMI.com |
Pääsintie 26 | 45100 Kouvola | FINLAND |
www.kymi.com | cfm.kymi.com |
aarni@kymi.com | info@kymi.com |
+358-5-3755 035 | +358-50-4910 037
-------------------------------------------------
This is a bugfree broadcast to you from a linux system.

Re: nextval() clarification

From
Ron St-Pierre
Date:
Greg Donald wrote:

>Long time MySQL user, six weeks into Postgres here.
>
>I'm converting a PHP script that uses MySQL to use Postgres instead.
>To substitue the missing MySQL functionaility with mysql_insert_id()
>and auto_increment I am using code like this:
>
>$sql = "SELECT nextval('companies_company_id_seq'::text)";
>
>And then I do my insert with that value.
>
>It works fine but I don't understand why it always gives me a +1 value
>of what I'm expecting.  For example when I have an empty table it
>gives me 2 as the first nextval instead of a 1, or if I have two rows
>in there already it gives me a 4.  Is this by design or am I missing
>something?  It's not a problem I just want to know what's going on.
>
>TIA..
>
>
>
As others have mentioned, you are basically calling the nextval
operation twice. If the field you
are inserting data into is of type serial, whenever a record/row is
inserted, the nextval is inserted.
eg
CREATE TABLE testSeq (
  id serial,
  name text
);
INSERT INTO testSeq (name) VALUES ('foo');
testdb=# SELECT * FROM testSeq;
 id | name
----+------
  1 | foo
See, it automatically increments the value.

then INSERT INTO testSeq (name) VALUES ( 'fooBar');

and then if you re-increment the value yourself:
testdb=# SELECT nextval('public.testseq_id_seq'::text);
 nextval
---------
       3

and then insert another row:
INSERT INTO testSeq (name) VALUES ('bar');
testdb=# SELECT * FROM testSeq;
 id |  name
----+--------
  1 | foo
  2 | fooBar
  4 | bar
(3 rows)

bar is now 4, because you manually called nextval().

hth
Ron



Re: nextval() clarification

From
Greg Donald
Date:
On Mon, 13 Sep 2004 21:54:11 +0200, Ennio-Sr <nasr.laili@tin.it> wrote:
> I think you should put <nextval(....)> directly into the INSERT
> instruction, so that it advances only once per added record.
> Have a look at Documentation PostgreSQL 7.4, Ch 9.11, table 9.34.
> HTH

I would but then I don't know how to ensure I return that exact same
id from the insert, like mysql_insert_id() does.  That's the whole
reason why I aquire the id first, so I know what it is after the
insert.  SELECT max(id) would be off under load I think.

I just didn't understand why it appeared to be +2 and not +1 as a
novice might expect.  But now I get it.  Thanks to all.

--
Greg Donald
http://destiney.com/

Re: nextval() clarification

From
Ron St-Pierre
Date:
Greg Donald wrote:

>On Mon, 13 Sep 2004 21:54:11 +0200, Ennio-Sr <nasr.laili@tin.it> wrote:
>
>
>>I think you should put <nextval(....)> directly into the INSERT
>>instruction, so that it advances only once per added record.
>>Have a look at Documentation PostgreSQL 7.4, Ch 9.11, table 9.34.
>>HTH
>>
>>
>
>I would but then I don't know how to ensure I return that exact same
>id from the insert, like mysql_insert_id() does.  That's the whole
>reason why I aquire the id first, so I know what it is after the
>insert.  SELECT max(id) would be off under load I think.
>
>I just didn't understand why it appeared to be +2 and not +1 as a
>novice might expect.  But now I get it.  Thanks to all.
>
>
>
After your insert statement, you can call CURRVAL to find out what the
value was that you
inserted into the serial column.

eg SELECT currval('companies_company_id_seq'::text)

Ron


Re: nextval() clarification

From
Michael Fuhr
Date:
On Mon, Sep 13, 2004 at 03:55:41PM -0500, Greg Donald wrote:
> On Mon, 13 Sep 2004 21:54:11 +0200, Ennio-Sr <nasr.laili@tin.it> wrote:
> > I think you should put <nextval(....)> directly into the INSERT
> > instruction, so that it advances only once per added record.
> > Have a look at Documentation PostgreSQL 7.4, Ch 9.11, table 9.34.
> > HTH
>
> I would but then I don't know how to ensure I return that exact same
> id from the insert, like mysql_insert_id() does.  That's the whole
> reason why I aquire the id first, so I know what it is after the
> insert.  SELECT max(id) would be off under load I think.

Are you aware of CURRVAL()?

CREATE TABLE foo (
    id    SERIAL PRIMARY KEY,
    info  TEXT NOT NULL
);

INSERT INTO foo (info) VALUES ('First Item');
INSERT INTO foo (info) VALUES ('Second Item');
SELECT CURRVAL('foo_id_seq');

--
Michael Fuhr
http://www.fuhr.org/~mfuhr/