How do I reset a sequence in Oracle?

后端 未结 18 1499
天命终不由人
天命终不由人 2020-11-22 05:09

In PostgreSQL, I can do something like this:

ALTER SEQUENCE serial RESTART WITH 0;

Is there an Oracle equivalent?

18条回答
  •  北荒
    北荒 (楼主)
    2020-11-22 05:36

    My approach is a teensy extension to Dougman's example.

    Extensions are...

    Pass in the seed value as a parameter. Why? I like to call the thing resetting the sequence back to the max ID used in some table. I end up calling this proc from another script which executes multiple calls for a whole bunch of sequences, resetting nextval back down to some level which is high enough to not cause primary key violations where I'm using the sequence's value for a unique identifier.

    It also honors the previous minvalue. It may in fact push the next value ever higher if the desired p_val or existing minvalue are higher than the current or calculated next value.

    Best of all, it can be called to reset to a specified value, and just wait until you see the wrapper "fix all my sequences" procedure at the end.

    create or replace
    procedure Reset_Sequence( p_seq_name in varchar2, p_val in number default 0)
    is
      l_current number := 0;
      l_difference number := 0;
      l_minvalue user_sequences.min_value%type := 0;
    
    begin
    
      select min_value
      into l_minvalue
      from user_sequences
      where sequence_name = p_seq_name;
    
      execute immediate
      'select ' || p_seq_name || '.nextval from dual' INTO l_current;
    
      if p_Val < l_minvalue then
        l_difference := l_minvalue - l_current;
      else
        l_difference := p_Val - l_current;
      end if;
    
      if l_difference = 0 then
        return;
      end if;
    
      execute immediate
        'alter sequence ' || p_seq_name || ' increment by ' || l_difference || 
           ' minvalue ' || l_minvalue;
    
      execute immediate
        'select ' || p_seq_name || '.nextval from dual' INTO l_difference;
    
      execute immediate
        'alter sequence ' || p_seq_name || ' increment by 1 minvalue ' || l_minvalue;
    end Reset_Sequence;
    

    That procedure is useful all by itself, but now let's add another one which calls it and specifies everything programmatically with a sequence naming convention and looking for the maximum value used in an existing table/field...

    create or replace
    procedure Reset_Sequence_to_Data(
      p_TableName varchar2,
      p_FieldName varchar2
    )
    is
      l_MaxUsed NUMBER;
    BEGIN
    
      execute immediate
        'select coalesce(max(' || p_FieldName || '),0) from '|| p_TableName into l_MaxUsed;
    
      Reset_Sequence( p_TableName || '_' || p_Fieldname || '_SEQ', l_MaxUsed );
    
    END Reset_Sequence_to_Data;
    

    Now we're cooking with gas!

    The procedure above will check for a field's max value in a table, builds a sequence name from the table/field pair and invokes "Reset_Sequence" with that sensed max value.

    The final piece in this puzzle and the icing on the cake comes next...

    create or replace
    procedure Reset_All_Sequences
    is
    BEGIN
    
      Reset_Sequence_to_Data( 'ACTIVITYLOG', 'LOGID' );
      Reset_Sequence_to_Data( 'JOBSTATE', 'JOBID' );
      Reset_Sequence_to_Data( 'BATCH', 'BATCHID' );
    
    END Reset_All_Sequences;
    

    In my actual database there are around one hundred other sequences being reset through this mechanism, so there are 97 more calls to Reset_Sequence_to_Data in that procedure above.

    Love it? Hate it? Indifferent?

提交回复
热议问题