How do I reset a sequence in Oracle?

后端 未结 18 1271
天命终不由人
天命终不由人 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:26

    This stored procedure restarts my sequence:

    Create or Replace Procedure Reset_Sequence  
      is
      SeqNbr Number;
    begin
       /*  Reset Sequence 'seqXRef_RowID' to 0    */
       Execute Immediate 'Select seqXRef.nextval from dual ' Into SeqNbr;
       Execute Immediate 'Alter sequence  seqXRef increment by - ' || TO_CHAR(SeqNbr) ;
       Execute Immediate 'Select seqXRef.nextval from dual ' Into SeqNbr;
       Execute Immediate 'Alter sequence  seqXRef increment by 1';
    END;
    

    /

    0 讨论(0)
  • 2020-11-22 05:27

    The following script set the sequence to a desired value:

    Given a freshly created sequence named PCS_PROJ_KEY_SEQ and table PCS_PROJ:

    BEGIN
       DECLARE
          PROJ_KEY_MAX       NUMBER := 0;
          PROJ_KEY_CURRVAL   NUMBER := 0;
       BEGIN
    
        SELECT MAX (PROJ_KEY) INTO PROJ_KEY_MAX FROM PCS_PROJ;
        EXECUTE IMMEDIATE 'ALTER SEQUENCE PCS_PROJ_KEY_SEQ INCREMENT BY ' || PROJ_KEY_MAX;
        SELECT PCS_PROJ_KEY_SEQ.NEXTVAL INTO PROJ_KEY_CURRVAL FROM DUAL;
        EXECUTE IMMEDIATE 'ALTER SEQUENCE PCS_PROJ_KEY_SEQ INCREMENT BY 1';
    
    END;
    END;
    /
    
    0 讨论(0)
  • 2020-11-22 05:27

    I make an alternative that the user don’t need to know the values, the system get and use variables to update.

    --Atualizando sequence da tabela SIGA_TRANSACAO, pois está desatualizada
    DECLARE
     actual_sequence_number INTEGER;
     max_number_from_table INTEGER;
     difference INTEGER;
    BEGIN
     SELECT [nome_da_sequence].nextval INTO actual_sequence_number FROM DUAL;
     SELECT MAX([nome_da_coluna]) INTO max_number_from_table FROM [nome_da_tabela];
     SELECT (max_number_from_table-actual_sequence_number) INTO difference FROM DUAL;
    IF difference > 0 then
     EXECUTE IMMEDIATE CONCAT('alter sequence [nome_da_sequence] increment by ', difference);
     --aqui ele puxa o próximo valor usando o incremento necessário
     SELECT [nome_da_sequence].nextval INTO actual_sequence_number from dual;
    --aqui volta o incremento para 1, para que futuras inserções funcionem normalmente
     EXECUTE IMMEDIATE 'ALTER SEQUENCE [nome_da_sequence] INCREMENT by 1';
     DBMS_OUTPUT.put_line ('A sequence [nome_da_sequence] foi atualizada.');
    ELSE
     DBMS_OUTPUT.put_line ('A sequence [nome_da_sequence] NÃO foi atualizada, já estava OK!');
    END IF;
    END;
    
    0 讨论(0)
  • 2020-11-22 05:32

    Stored procedure that worked for me

    create or replace
    procedure reset_sequence( p_seq_name in varchar2, tablename in varchar2 )
    is
        l_val number;
        maxvalueid number;
    begin
        execute immediate 'select ' || p_seq_name || '.nextval from dual' INTO l_val;
        execute immediate 'select max(id) from ' || tablename INTO maxvalueid;
        execute immediate 'alter sequence ' || p_seq_name || ' increment by -' || l_val || ' minvalue 0';
        execute immediate 'select ' || p_seq_name || '.nextval from dual' INTO l_val;
        execute immediate 'alter sequence ' || p_seq_name || ' increment by '|| maxvalueid ||' minvalue 0';  
        execute immediate 'select ' || p_seq_name || '.nextval from dual' INTO l_val;
        execute immediate 'alter sequence ' || p_seq_name || ' increment by 1 minvalue 0';
    end;
    

    How to use the stored procedure:

    execute reset_sequence('company_sequence','company');
    
    0 讨论(0)
  • 2020-11-22 05:35

    1) Suppose you create a SEQUENCE like shown below:

    CREATE SEQUENCE TESTSEQ
    INCREMENT BY 1
    MINVALUE 1
    MAXVALUE 500
    NOCACHE
    NOCYCLE
    NOORDER
    

    2) Now you fetch values from SEQUENCE. Lets say I have fetched four times as shown below.

    SELECT TESTSEQ.NEXTVAL FROM dual
    SELECT TESTSEQ.NEXTVAL FROM dual
    SELECT TESTSEQ.NEXTVAL FROM dual
    SELECT TESTSEQ.NEXTVAL FROM dual
    

    3) After executing above four commands the value of the SEQUENCE will be 4. Now suppose I have reset the value of the SEQUENCE to 1 again. The follow the following steps. Follow all the steps in the same order as shown below:

    1. ALTER SEQUENCE TESTSEQ INCREMENT BY -3;
    2. SELECT TESTSEQ.NEXTVAL FROM dual
    3. ALTER SEQUENCE TESTSEQ INCREMENT BY 1;
    4. SELECT TESTSEQ.NEXTVAL FROM dual
    0 讨论(0)
  • 2020-11-22 05:35

    Here's a more robust procedure for altering the next value returned by a sequence, plus a whole lot more.

    • First off it protects against SQL injection attacks since none of the strings passed in are used to directly create any of the dynamic SQL statements,
    • Second it prevents the next sequence value from being set outside the bounds of the min or max sequence values. The next_value will be != min_value and between min_value and max_value.
    • Third it takes the current (or proposed) increment_by setting as well as all the other sequence settings into account when cleaning up.
    • Fourth all parameters except the first are optional and unless specified take on the current sequence setting as defaults. If no optional parameters are specified no action is taken.
    • Finally if you try altering a sequence that doesn't exist (or is not owned by the current user) it will raise an ORA-01403: no data found error.

    Here's the code:

    CREATE OR REPLACE PROCEDURE alter_sequence(
        seq_name      user_sequences.sequence_name%TYPE
      , next_value    user_sequences.last_number%TYPE := null
      , increment_by  user_sequences.increment_by%TYPE := null
      , min_value     user_sequences.min_value%TYPE := null
      , max_value     user_sequences.max_value%TYPE := null
      , cycle_flag    user_sequences.cycle_flag%TYPE := null
      , cache_size    user_sequences.cache_size%TYPE := null
      , order_flag    user_sequences.order_flag%TYPE := null)
      AUTHID CURRENT_USER
    AS
      l_seq user_sequences%rowtype;
      l_old_cache user_sequences.cache_size%TYPE;
      l_next user_sequences.min_value%TYPE;
    BEGIN
      -- Get current sequence settings as defaults
      SELECT * INTO l_seq FROM user_sequences WHERE sequence_name = seq_name;
    
      -- Update target settings
      l_old_cache := l_seq.cache_size;
      l_seq.increment_by := nvl(increment_by, l_seq.increment_by);
      l_seq.min_value    := nvl(min_value, l_seq.min_value);
      l_seq.max_value    := nvl(max_value, l_seq.max_value);
      l_seq.cycle_flag   := nvl(cycle_flag, l_seq.cycle_flag);
      l_seq.cache_size   := nvl(cache_size, l_seq.cache_size);
      l_seq.order_flag   := nvl(order_flag, l_seq.order_flag);
    
      IF next_value is NOT NULL THEN
        -- Determine next value without exceeding limits
        l_next := LEAST(GREATEST(next_value, l_seq.min_value+1),l_seq.max_value);
    
        -- Grab the actual latest seq number
        EXECUTE IMMEDIATE
            'ALTER SEQUENCE '||l_seq.sequence_name
                || ' INCREMENT BY 1'
                || ' MINVALUE '||least(l_seq.min_value,l_seq.last_number-l_old_cache)
                || ' MAXVALUE '||greatest(l_seq.max_value,l_seq.last_number)
                || ' NOCACHE'
                || ' ORDER';
        EXECUTE IMMEDIATE 
          'SELECT '||l_seq.sequence_name||'.NEXTVAL FROM DUAL'
        INTO l_seq.last_number;
    
        l_next := l_next-l_seq.last_number-1;
    
        -- Reset the sequence number
        IF l_next <> 0 THEN
          EXECUTE IMMEDIATE 
            'ALTER SEQUENCE '||l_seq.sequence_name
                || ' INCREMENT BY '||l_next
                || ' MINVALUE '||least(l_seq.min_value,l_seq.last_number)
                || ' MAXVALUE '||greatest(l_seq.max_value,l_seq.last_number)
                || ' NOCACHE'
                || ' ORDER';
          EXECUTE IMMEDIATE 
            'SELECT '||l_seq.sequence_name||'.NEXTVAL FROM DUAL'
          INTO l_next;
        END IF;
      END IF;
    
      -- Prepare Sequence for next use.
      IF COALESCE( cycle_flag
                 , next_value
                 , increment_by
                 , min_value
                 , max_value
                 , cache_size
                 , order_flag) IS NOT NULL
      THEN
        EXECUTE IMMEDIATE 
          'ALTER SEQUENCE '||l_seq.sequence_name
              || ' INCREMENT BY '||l_seq.increment_by
              || ' MINVALUE '||l_seq.min_value
              || ' MAXVALUE '||l_seq.max_value
              || CASE l_seq.cycle_flag
                 WHEN 'Y' THEN ' CYCLE' ELSE ' NOCYCLE' END
              || CASE l_seq.cache_size
                 WHEN 0 THEN ' NOCACHE'
                 ELSE ' CACHE '||l_seq.cache_size END
              || CASE l_seq.order_flag
                 WHEN 'Y' THEN ' ORDER' ELSE ' NOORDER' END;
      END IF;
    END;
    
    0 讨论(0)
提交回复
热议问题