Search code examples
oracle-databaseplsqlsql-functiondatabase-sequence

Implement a sequence that increments by value of a function


I am looking to create a simple sequence:

 CREATE SEQUENCE supplier_seq
   MINVALUE 1
  START WITH 3
  INCREMENT BY  4
  CACHE 20000;

However, I want to semi-randomize the incrementing values with a function determined by some factors implemented on the java side.

I thought the first step for testing this might look something like this:

   CREATE SEQUENCE supplier_seq
       MINVALUE 1
      START WITH 3
     INCREMENT BY  myfunction
      CACHE 20000;

I tried this:

     CREATE SEQUENCE supplier_seq
        MINVALUE 1
      START WITH 3
        INCREMENT BY  (declare 
   rtrnt number;
  begin 
      rtrnt :=semiRandomize();
   end; 
    )
     CACHE 20000;

which I realize is ridiculous.. but there must be some way to do something like this. Any pointers?


Solution

  • How about this? Not really a sequence, but - might suit your needs. It is a function that selects a random number and stores it into a table with a primary key. If the number has already been used, it is skipped. The function checks whether all numbers have been used; if so, it raises an error.

    In this example, I'm creating a 5-numbers "sequence" (so that it fails soon enough).

    Table & function:

    SQL> create table t_seq (supseq  number constraint pk_tseq primary key);
    
    Table created.
    
    SQL> create or replace function f_supseq
      2    return number
      3  as
      4    l_range  number := 5; -- number of values in a "sequence"
      5    l_seq    number;      -- a new "sequence" number
      6    l_cnt    number;      -- number of used numbers
      7    pragma autonomous_transaction;
      8  begin
      9    select count(*) into l_cnt from t_seq;
     10    if l_cnt < l_range then
     11       -- there are still some available numbers so - let's get them
     12
     13       -- don't let anyone mess with the table
     14       lock table t_seq in exclusive mode;
     15       while l_seq is null loop
     16         begin
     17           insert into t_seq (supseq) values
     18             (round(dbms_random.value(1, l_range)))
     19             returning supseq into l_seq;
     20         exception
     21           when dup_val_on_index then
     22             -- that number has already been used; skip it
     23             null;
     24         end;
     25       end loop;
     26       commit;
     27    else
     28       raise_application_error(-20001, 'No more available numbers');
     29    end if;
     30
     31    return l_seq;
     32  end;
     33  /
    
    Function created.
    

    Fetching random "sequence" values:

    SQL> select f_supseq from dual;
    
      F_SUPSEQ
    ----------
             2
    
    SQL> select f_supseq from dual;
    
      F_SUPSEQ
    ----------
             4
    
    SQL> select f_supseq from dual;
    
      F_SUPSEQ
    ----------
             1
    
    SQL> select f_supseq from dual;
    
      F_SUPSEQ
    ----------
             3
    
    SQL> select f_supseq from dual;
    
      F_SUPSEQ
    ----------
             5
    
    SQL> select f_supseq from dual;
    select f_supseq from dual
           *
    ERROR at line 1:
    ORA-20001: No more available numbers
    ORA-06512: at "SCOTT.F_SUPSEQ", line 28
    

    Table contents:

    SQL> select * From t_seq;
    
        SUPSEQ
    ----------
             1
             2
             3
             4
             5
    
    SQL>