4

How can I generate the below numbers through sequence in oracle

2
-2
2
-2
2
-2

And so on. I can generate 1,2,1,2,1,2 through cycle but above I am not able to use logic.

Barbaros Özhan
  • 59,113
  • 10
  • 31
  • 55
  • 2
    on what basis you want generate those numbers? – akshay Aug 09 '18 at 08:44
  • 2
    It might also help to show us how you generate `1,2,1,2,1,2` so we can tell you how to adapt that; and explain what you mean by cycle and sequence. – Alex Poole Aug 09 '18 at 08:50
  • @AlexPoole - Cycle is an option on sequences, when it hits max value, it will start again at the min value – Andrew Aug 09 '18 at 09:00
  • OK, just checking you actually meant a real sequence (cycle can refer to other things e.g. in a hierarchical query, and sequence could have meant just a mathematical sequence rather than an actual sequence object.). Including the sequence you use to generate `1,2,1,2` in your question would have clarified that. – Alex Poole Aug 09 '18 at 09:09

4 Answers4

12

This seems like an odd requirement for a sequence, but if you really want to then you can do:

create sequence weird_seq
start with 2
increment by 4
maxvalue 2
minvalue -2
cycle
nocache;

select weird_seq.nextval from dual
connect by level <= 10;

   NEXTVAL
----------
         2
        -2
         2
        -2
         2
        -2
         2
        -2
         2
        -2

The increment 4 is so it steps from -2 to +2. The maxval 2 is so the next call cycles round to the minval -2. And it needs to start with +/-2. The nocache is unfortunate but necessary, otherwise you get "ORA-04013: number to CACHE must be less than one cycle".

If you're just using these numbers as part of a query then you could do it with a hierarchical query instead:

select 2 * (2 * mod(level, 2) - 1)
from dual
connect by level <= 10;

2*(2*MOD(LEVEL,2)-1)
--------------------
                   2
                  -2
                   2
                  -2
                   2
                  -2
                   2
                  -2
                   2
                  -2

but then running multiple times will always start at +2, which might not be what you want. (Depends how it'll be used...)

You could potentially also generate the number on the fly from existing data using an analytic query, but again, it depends what you'll use this for.

Alex Poole
  • 183,384
  • 11
  • 179
  • 318
  • Dear Alex, Can you also tell me what is the concept of nocache here. why it gives error when we dont use it. –  Aug 09 '18 at 10:38
  • 1
    Usually you want the sequence to have a cache as it's much more efficient. The default is 20, it's often better to increase that. But the cache size can't be bigger than the entire cycle range, which is five values here (-2, -1, 0, 1, 2), so you'd be limited to a cache of at most 4 here anyway; but the increment means only 2 values are usable (-2, 2) which makes the cycle size really only 2. You aren't allowed a cache size of 1, so the only option is to turn the cache off completely. – Alex Poole Aug 09 '18 at 10:46
1

Here is simple way of doing the same using CASE and MOD

SELECT CASE WHEN mod(level, 2) = 1 THEN 2 ELSE -2 END sequence 
FROM dual
CONNECT BY LEVEL <= 10;
Shushil Bohara
  • 5,556
  • 2
  • 15
  • 32
0

Use a rownumber selection in your update statement.

UPDATE yourtable
SET yourfield = yourfield*-1
WHERE yourfield IN
(SELECT yourfield FROM 
(SELECT rownum rn, y."yourfield" yourfield FROM yourtable y)
WHERE MOD(rn, 2) = 0)
Matt
  • 14,906
  • 27
  • 99
  • 149
0

I can suggest a method by using PL/SQL :

SQL> set serveroutput on;
SQL> Create sequence my_seq start with 2 minvalue -4;     
Sequence created

SQL> Create or Replace Procedure Pr_Get_MySeq( o_val out pls_integer ) is
  2     i_seq_name varchar2(35):= 'my_seq';
  3  begin
  4      execute immediate 'select '||i_seq_name||'.nextval from dual' INTO o_val;
  5      execute immediate 'alter sequence '||i_seq_name||' increment by ' ||to_char(-2*o_val) || ' minvalue -4';
  6  end;     
  7  /     
Procedure created

SQL> var o_val number;
SQL> begin
  2    Pr_Get_MySeq( :o_val );
  3  end;
  4  /

PL/SQL procedure successfully completed
o_val
---------
2

SQL> /

PL/SQL procedure successfully completed
o_val
---------
-2

SQL> /

PL/SQL procedure successfully completed
o_val
---------
2
Barbaros Özhan
  • 59,113
  • 10
  • 31
  • 55
  • Aside from that seeming like quite a bit of overhead, the `alter sequence` is DDL so it will implicitly commit every time you call the procedure. I think you could also get simultaneous calls from different sessions that overlap - both call `nextval` before either does an `alter`, which would give weird results. (Also not sure why you made the first call dynamic, altering the sequence doesn't invalidate the procedure?) – Alex Poole Aug 09 '18 at 11:08
  • @AlexPoole thank you for the suggestions. "Altering the sequence" doesn't invalidate the procedure. – Barbaros Özhan Aug 09 '18 at 11:29