1

I have a big problem. I need to know the next value of an oracle sequence without changing it.

If I use sequence.NEXTVAL , I get what I need. The problem is that the value changed, so the next record will get this value + 1 and it's not good for me.

I know I can use sequence.CURRVAL and it's great because it does not change the value, but in case of no records, it's not working and in this case the sequence value can be any number (and not only 1 cause the sequence value steel exist).

Please help me to find a solution.

Thank you vary much !!!!!

S.K
  • 185
  • 2
  • 2
  • 6
  • What do you mean by "but in case of no records, it's not working"? – Wernfried Domscheit Jan 13 '14 at 14:27
  • 5
    Why do you need to know that? You can't use that value for anything - someone else could grab it before you do call `nextval`? `currval` will be undefined unless you've called `nextval` in this session; you could query the `user_sequences` view but that won't necessarily be accurate either (other sessions, caching, RAC, ...). – Alex Poole Jan 13 '14 at 14:28
  • "but in case of no records, it's not working" means that you will get error when you have no records and an existing sequence and I need to know it so I can synk something. – S.K Jan 13 '14 at 14:41
  • [possible duplicate](http://stackoverflow.com/questions/15011444/oracle-sequences-without-a-sequence) and [another one](http://stackoverflow.com/questions/17165954/oracle-sequence-not-generating-the-continuous-number). – ThinkJet Jan 13 '14 at 14:49
  • 1
    'I need to know it so I can synk something' - why don't you explain (in the question) what you're actually trying to achieve, and how you think knowing this would help? – Alex Poole Jan 13 '14 at 14:52
  • "I have a big problem". You haven't described your problem yet. "The problem is that the value changed" describes the normal expected behaviour of a sequence! – Jeffrey Kemp Jan 17 '14 at 04:41

5 Answers5

3

You should definitely not rely on never missing a value in a sequence, as they optimise for concurrency over sequential numbering. There are quite a few situations in which a number can be "lost".

Furthermore, the value visible in the dba_sequences may not be the actual next value, as the numbers are assigned from an in-memory cache. The underlying sequence metadata table has no data on the usage of that cache. You should also bear in mind that in a RAC system each instance has its own cache of sequence numbers.

You might describe the problem you are trying to solve, as it could be that sequences are not an appropriate mechanism for you.

David Aldridge
  • 51,479
  • 8
  • 68
  • 96
  • I know. you right but I dont do anything critic. I just want to get the NEXTVAL value without change it, or the CURRVAL value without use NEXTVAL before. This is so simple in SQL!!! – S.K Jan 13 '14 at 14:47
  • 1
    What's the use case for doing it? – David Aldridge Jan 13 '14 at 16:31
  • I took your advice. I used a whole different way. didn't want to rely on it. Thank you all. – S.K Feb 03 '14 at 06:54
1

In multi-user environment there is no way. The value is either known - when you call .NEXTVAL or unknown. Sequences can not be locked.

ibre5041
  • 4,903
  • 1
  • 20
  • 35
1

Well the only suggestion that I can give you is to get the nextval and then revert back. But CAUTION: Perform these operations only while you sequence is not begin used from any other session. Otherwise if sequence is fetched from another session during this operation, it is possible that you could never revert back to the original value. So be cautious before checking:

In my database, current value of seq_test is 6

--Get the next value

SQL> SELECT seq_test.NEXTVAL FROM dual;

   NEXTVAL
----------
         7

-- Ok, so this is the next value, now Restore to Original

SQL> ALTER SEQUENCE seq_test INCREMENT BY -1;

Sequence altered.

SQL> SELECT seq_test.NEXTVAL FROM dual;

   NEXTVAL
----------
         6

-- Restore original increment by clause

SQL> ALTER SEQUENCE seq_test INCREMENT BY 1;

Sequence altered.

--Check

SQL> SELECT seq_test.CURRVAL FROM dual;

   CURRVAL
----------
         6

I again warn you that this could be fatal ;-)

San
  • 4,508
  • 1
  • 13
  • 19
  • You would definitely need to use a locking mechanism, such as DBMS_Lock, so make this a practical system, and that would need to be included in every call to the sequence nextval. – David Aldridge Jan 14 '14 at 13:13
0

Look at the "last_number" column from

select * from USER_SEQUENCES

Edit:

This works only if the sequence is created with the nocache option.

So if the sequence does has a cache setting, drop it and recreate it with nocache, and then you can use user_sequences.last_number +1.

Note that if the sequence is heavily used than this does impact performance. If on the other hand, the sequence is not used so much, it will be fine.

Short of writing the application (which is the best solution), this is only solution.

Brian McGinity
  • 5,777
  • 5
  • 36
  • 46
  • Thank you but it's not the same value as NEXTVAL. – S.K Jan 13 '14 at 14:43
  • I did not understand the problem with currval. Sounds like you're saying if the seq has no value yet, then it errors? When this happens could you just assume the value is 0? Or check user_sequences and see the value is 0? Also user_sequences has a column for "cache_size" which my help lead the nextval. (I don't know...would need to expirement in a RAC environment.) – Brian McGinity Jan 13 '14 at 14:56
  • Ahh...I see it now.... currval is not defined until nextval has been hit. You can only approximate the next val as: last_number-cache_size+1 see http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:277215805229 – Brian McGinity Jan 13 '14 at 15:04
0

I can't see any reason why you want to know the next value of a sequence. The only importance for the value is when you have used it for a new record. So you either create a new record and return the ID value immediately:

declare
  l_id number;
begin
   Insert into table (id) 
   values (sequence.nextval) 
   return id into l_id;

   -- and then do something more with the ID value
end;

or first get a new ID and use it afterwards

declare   
   l_id number; 
begin
   select sequence.nextval    
   into l_id    
   from dual;

    -- then do something with the ID value 
end;
Rene
  • 10,391
  • 5
  • 33
  • 46