How do I reset a sequence in Oracle?

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

    Here's how to make all auto-increment sequences match actual data:

    1. Create a procedure to enforce next value as was already described in this thread:

      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;
      
    2. Create another procedure to reconcile all sequences with actual content:

      CREATE OR REPLACE PROCEDURE RESET_USER_SEQUENCES_TO_DATA
      IS
        STMT CLOB;
      BEGIN
        SELECT 'select ''BEGIN'' || chr(10) || x || chr(10) || ''END;'' FROM (select listagg(x, chr(10)) within group (order by null) x FROM ('
          || X
          || '))'
        INTO STMT
        FROM
          (SELECT LISTAGG(X, ' union ') WITHIN GROUP (
          ORDER BY NULL) X
          FROM
            (SELECT CHR(10)
              || 'select ''Reset_Sequence('''''
              || SEQ_NAME
              || ''''','' || coalesce(max('
              || COL_NAME
              || '), 0) || '');'' x from '
              || TABLE_NAME X
            FROM
              (SELECT TABLE_NAME,
                REGEXP_SUBSTR(WTEXT, 'NEW\.(\S*) IS NULL',1,1,'i',1) COL_NAME,
                REGEXP_SUBSTR(BTEXT, '(\.|\s)([a-z_]*)\.nextval',1,1,'i',2) SEQ_NAME
              FROM USER_TRIGGERS
              LEFT JOIN
                (SELECT NAME BNAME,
                  TEXT BTEXT
                FROM USER_SOURCE
                WHERE TYPE = 'TRIGGER'
                AND UPPER(TEXT) LIKE '%NEXTVAL%'
                )
              ON BNAME = TRIGGER_NAME
              LEFT JOIN
                (SELECT NAME WNAME,
                  TEXT WTEXT
                FROM USER_SOURCE
                WHERE TYPE = 'TRIGGER'
                AND UPPER(TEXT) LIKE '%IS NULL%'
                )
              ON WNAME             = TRIGGER_NAME
              WHERE TRIGGER_TYPE   = 'BEFORE EACH ROW'
              AND TRIGGERING_EVENT = 'INSERT'
              )
            )
          ) ;
        EXECUTE IMMEDIATE STMT INTO STMT;
        --dbms_output.put_line(stmt);
        EXECUTE IMMEDIATE STMT;
      END RESET_USER_SEQUENCES_TO_DATA;
      

    NOTES:

    1. Procedure extracts names from trigger code and does not depend on naming conventions
    2. To check generated code before execution, switch comments on last two lines

提交回复
热议问题