Re: How to create "auto-increment" field WITHOUT a sequence object?

From: Dmitriy Igrishin <dmitigr(at)gmail(dot)com>
To: Chris Travers <chris(dot)travers(at)gmail(dot)com>
Cc: Postgres General <pgsql-general(at)postgresql(dot)org>
Subject: Re: How to create "auto-increment" field WITHOUT a sequence object?
Date: 2011-07-01 08:16:27
Message-ID: BANLkTinr+T_NFQxbVbZCxm+hn6O+UpxyOA@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

Hey Chris,

The suggestion of using for
> update is a good one, but it doesn't entirely get rid of the problem,
> which is inherent in ensuring gapless numbering in a system with
> concurrent transactions.
>
Why not?

I mean the following solution:

CREATE TABLE myseq(tabnm text not null, lastid integer not null);

INSERT INTO myseq SELECT 'mytab', 0; -- initialization

CREATE OR REPLACE FUNCTION public.myseq_nextval(a_tabnm text)
RETURNS integer
LANGUAGE sql
STRICT
AS $function$
UPDATE myseq SET lastid = li + 1 FROM
(SELECT lastid li FROM myseq WHERE tabnm = $1 FOR UPDATE) foo
RETURNING lastid;
$function$

-- Test

dmitigr=> BEGIN;
BEGIN
dmitigr=> SELECT myseq_nextval('mytab');
myseq_nextval
---------------
1
(1 row)

dmitigr=> ROLLBACK;
ROLLBACK
dmitigr=> SELECT * FROM myseq;
tabnm | lastid
-------+--------
mytab | 0
(1 row)

So, with this approach you'll get a lock only on INSERT.

dmitigr=> CREATE TABLE mytab(id integer not null DEFAULT
myseq_nextval('mytab'));
CREATE TABLE
dmitigr=> INSERT INTO mytab DEFAULT VALUES;
INSERT 0 1
dmitigr=> INSERT INTO mytab DEFAULT VALUES;
INSERT 0 1
dmitigr=> SELECT * FROM mytab;
id
----
1
2
(2 rows)

--
// Dmitriy.

In response to

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Chris Travers 2011-07-01 08:21:36 Re: How to create "auto-increment" field WITHOUT a sequence object?
Previous Message mona attariyan 2011-07-01 07:28:16 statically compiling postgres and problem with initdb