1

In Oracle I can do something like this to fetch a bunch of keys.

select seq.nextval from dual connect by level <= 1000;

I Postgres there is a nextval function, but how can multiple values be pulled at once?`

If someone also knows the answer for InnoDb I would be happy to read it.

0

2 Answers 2

2

In postgresql, you can use something like this:

select nextval('mysequence') from generate_series(1,1000);

to get 1000 values from the sequence! I don't think it's particularly safe to assume that these will be consecutive values, though. You might need to wrap the select in a lock statement to ensure that competing results don't interleave. If you don't care about consecutive values, then you don't need a lock.

Sign up to request clarification or add additional context in comments.

4 Comments

I only need 1000 values that no other transaction will ever get. If they go 1,5,9,12,13,14,150 I don't care. Is that what you mean by "consecutive values"? p.s I'm running in read committed.
yes. if you don't care about gaps, then this is exactly it. I'm not sure your oracle example is any different, but the first thing that popped into my head was firebird's generate(sequence, count) which always returns consecutive values out of the sequence (actually it returns the last generated value, it's up to the caller to interpolate the intervening values.)
perfect, that's all I need. I don't know if the time for firebird has come already. Maybe in a few years time I will move to firebird. I'm happy porting the app to postgres first. p.s oracle is the same: it doesn't gurantee gap free sequences.
mnnneh... I can't think of any reason, in spite of native consecutive sequence reads, to favor firebird for anything. PostgreSQL gets much more development attention, has hugely superior documenation, and has a heap of features firebird probably will never have.
2

PostgreSQL has a suite of functions that manipulate sequences. So you can do something like this. (But don't. See "use PostgreSQL's native cache" below.)

drop sequence test;
create sequence test;

-- You'll want to wrap these in a single transaction.
select nextval('test');                               -- Returns 1
select (setval('test', currval('test') + 1000)) as t; -- Returns 1001
select nextval('test');                               -- Returns 1002

There are a couple of other ways to get a bunch of values from a sequence. See docs for CREATE SEQUENCE.

Have the sequence increment by 1000 instead of by 1. Let your application handle doling out the thousand values lower than nextval(). You will probably end up throwing away a lot of numbers.

drop sequence test;
create sequence test increment by 1000;
select nextval('test'); -- Returns 1; do this when you create the sequence.
select nextval('test'); -- Returns 1001

Use PostgreSQL's native cache. I'm pretty sure this will be the most reliable and robust approach.

drop sequence test;
create sequence test cache 1000;
select nextval('test'); -- Returns 1.
select nextval('test'); -- Returns 2 from the cache; doesn't touch the sequence.

A different, concurrent session won't see the same thing.

select nextval('test'); -- Returns 1001

2 Comments

is the example with + 1000 telling me that between 1 and 1001 no other transaction got any key?
@FranzKafka: Yes, but I think using the native cache is a better idea. See my updated answer.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.