Oracle에서 시퀀스를 어떻게 재설정합니까?


170

에서 PostgreSQL을 , 나는 같은 것을 할 수 있습니다 :

ALTER SEQUENCE serial RESTART WITH 0;

오라클과 동등한 제품이 있습니까?


1
여기 에서 "시퀀스 재설정"을 살펴보십시오 .
gerikson

3
경고 : 아래의 모든 코드는 "1 씩 증가"로 처음 ​​생성 된 시퀀스에만 유효합니다. 원래 시퀀스가 ​​증분으로 생성 된 경우! = 1; 위의 절차 중 하나를 적용하면 증분이 1로 변경됩니다! 사용할 올바른 증분 값은 user_sequences보기에서 얻을 수 있습니다.

1
순서를 삭제하고 다시 만드십시오
Viswanath Lekshmanan

답변:


153

다음은 Oracle guru Tom Kyte의 시퀀스를 0으로 재설정하는 좋은 절차입니다 . 아래 링크에서도 장단점에 대한 훌륭한 토론.

tkyte@TKYTE901.US.ORACLE.COM> 
create or replace
procedure reset_seq( p_seq_name in varchar2 )
is
    l_val number;
begin
    execute immediate
    'select ' || p_seq_name || '.nextval from dual' INTO l_val;

    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 1 minvalue 0';
end;
/

이 페이지에서 : 시퀀스 값을 재설정하는 동적 SQL
또 다른 좋은 논의는 다음과 같습니다. 시퀀스를 재설정하는 방법?


@Dougman : hi 'm beginner .... 위의 답변에서 왜 마지막에 절에 언급합니까? 즉시'select '를 실행하십시오. p_seq_name || '.nextval INto l_val from dual';
Thiyagu ATR

@Thiyagu : PL / SQL에서 이것은 execute immediate최대 1 행을 리턴하는 선택의 출력을 캡처하는 데 사용할 때 사용되는 구문 입니다. 다음은 즉시 실행에 대한 설명서는 다음과 같습니다 docs.oracle.com/cd/B28359_01/appdev.111/b28370/...
더그 포터

@matra 나는 시퀀스를 재설정하고 동일한 시퀀스의 다른 사용자와 동시 환경에 있어야하는 시나리오를 보지 못했습니다.
Ekevoo

시퀀스를 선택해야하는 이유, 마지막 행을 선택하지 않는 이유'alter sequence ' || p_seq_name || ' increment by 1 minvalue 0';
Goku

100

진정한 재시작은 불가능합니다 AFAIK . (내가 틀렸다면 나를 정정하십시오!).

그러나 0으로 설정하려면 삭제하고 다시 만들면됩니다.

특정 값으로 설정하려면 INCREMENT를 음수 값으로 설정하고 다음 값을 얻을 수 있습니다.

즉, 시퀀스가 ​​500 인 경우 다음을 통해 시퀀스를 100으로 설정할 수 있습니다.

ALTER SEQUENCE serial INCREMENT BY -400;
SELECT serial.NEXTVAL FROM dual;
ALTER SEQUENCE serial INCREMENT BY 1;

4
PLSQL 사용자를위한 참고 사항입니다. "limit 1;"을 추가하십시오 또는 select 문에 "rownum = 1"이면 nextVal을 몇 번 실행하고 여러 번 -400 씩 증가시킬 수 있습니다.
user830914

1
오류 시퀀스 .NEXTVAL이 MINVALUE 아래로 내려 가면 INCREMENT BY-<< big_number >>
zloctb

47

이것은 내 접근 방식입니다.

  1. 순서를 버리다
  2. 그것을 재창조하십시오

예:

--Drop sequence

DROP SEQUENCE MY_SEQ;

-- Create sequence 

create sequence MY_SEQ
minvalue 1
maxvalue 999999999999999999999
start with 1
increment by 1
cache 20;

29
삭제는 해당 시퀀스에 종속 된 모든 개체를 무효화하므로 다시 컴파일해야합니다.
더그 포터

22
또한 시퀀스에서 선택하기 위해 부여 된 보조금을 다시 부여해야합니다.
GreenGiant

37
alter sequence serial restart start with 1;

이 기능은 공식적으로 18c에 추가되었지만 12.1에서는 비공식적으로 제공됩니다.

이 문서화되지 않은 기능을 12.1에서 사용하는 것이 틀림없이 안전합니다. 구문은 공식 문서에 포함되어 있지 않지만 Oracle 패키지 DBMS_METADATA_DIFF에 의해 생성됩니다 . 프로덕션 시스템에서 여러 번 사용했습니다. 그러나 Oracle Service 요청을 작성했으며 설명서 버그가 아닌지 확인했으며이 기능은 실제로 지원되지 않습니다.

18c에서이 기능은 SQL 언어 구문에는 나타나지 않지만 데이터베이스 관리자 안내서에 포함되어 있습니다.


@Jon, 나는 문서화되지 않은 기능을 알고 있지만 DBMS_METADATA_DIFF의 생성 된 스크립트에서 볼 수 있다는 것을 몰랐습니다. 스크립트 생성 방법, 절차 등을 알려 주시겠습니까? 나는 그것을 테스트하려고합니다.
Lalit Kumar B

@LalitKumarB 이 질문에 대답하면서 그 기능을 우연히 발견했습니다 .
Jon Heller

1
아아, 지금 알았어 감사합니다 :-)
Lalit Kumar B

이것은 "테이블 변경 your_table 수정 (ID가 한계 값으로 시작하여 null에 기본적으로 생성 된 ID);"을 지원하기 위해 구현 된 것 같습니다. 표준 시퀀스에서도 작동한다는 것을 알고 반갑습니다!
Oliver

1
시퀀스의 최소값이 더 큰 경우 0 쓰기를 고려하십시오... RESTART START WITH 0 MINVALUE 0
conceptdeluxe

33

내 접근 방식은 Dougman의 예에 대한 십대 확장 입니다.

확장은 ...

시드 값을 매개 변수로 전달하십시오. 왜? 시퀀스를 재설정하는 것을 일부 테이블에서 사용되는 최대 ID로 다시 호출하는 것을 좋아 합니다 . 나는 전체 시퀀스에 대해 여러 번의 호출을 실행하는 다른 스크립트 에서이 proc을 호출하고, nextval을 고유 식별자에 시퀀스 값을 사용하는 경우 기본 키 위반을 일으키지 않을 정도로 높은 수준으로 다시 설정합니다.

또한 이전 최소값도 준수 합니다. 원하는 p_val 또는 기존 최소값 이 현재 또는 계산 된 다음 값보다 높으면 실제로 다음 값을 더 높게 푸시 할 수 있습니다 .

무엇보다도 지정된 값으로 재설정하도록 호출 할 수 있으며 마지막에 래퍼 "모든 시퀀스 수정"프로 시저가 표시 될 때까지 기다리십시오.

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;

그 절차는 그 자체로 유용하지만 이제는 그것을 명명하고 시퀀스 명명 규칙을 사용하여 프로그래밍 방식으로 모든 것을 지정하고 기존 테이블 / 필드에서 사용되는 최대 값을 찾는 다른 것을 추가합시다 ...

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;

이제 우리는 가스로 요리하고 있습니다!

위의 절차는 테이블에서 필드의 최대 값을 확인하고 테이블 / 필드 쌍에서 시퀀스 이름을 작성하고 감지 된 최대 값으로 "Reset_Sequence" 를 호출 합니다.

이 퍼즐의 마지막 조각과 케이크의 장식은 다음에옵니다 ...

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;

내 실제 데이터베이스에는이 메커니즘을 통해 재설정되는 약 100 개의 다른 시퀀스가 ​​있으므로 위의 해당 절차에서 Reset_Sequence_to_Data 에 대한 97 개의 호출이 더 있습니다.

좋아? 싫다? 무관심한?


2
나는 그것을 좋아한다. user_sequences 테이블에서 값으로 증가분을 가져오고 저장하는 변수를 추가합니다. (1이 아닐 수도 있습니다). 참고 : all_sequences 테이블을 대신 사용해야 할 수도 있습니다. 이 경우 sequence_owner도 전달할 수 있습니다.
Harv

1
당신을 충분히 표명 할 수 없습니다. 이는 데이터 마이그레이션을 처리 할 때 흔히 발생하는 문제이며 시퀀스가 ​​멈춘 경우 AFAIK에 가장 적합한 방법입니다.
Dominique Eav

1
이것은 훌륭한 접근 방식이기 때문에 공감되었습니다. 단점은 RAC 시스템에서 예측할 수없는 동작을 초래할 l_current수 있다는 것입니다. 여기서 스크립트가 실행되는 노드에 따라 다양한 값 중 하나 일 수 있습니다. 스크립트를 다시 실행하면 다른 결과가 발생할 수 있습니다. 여러 번 실행하면 결국 특정 값으로 설정되었습니다.
Jeffrey Kemp

10

다음 스크립트는 시퀀스를 원하는 값으로 설정합니다.

PCS_PROJ_KEY_SEQ 및 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;
/

1
첫 번째 DDL 문에서 빼기를 잊어 버렸습니다 (추가 END키워드도 있음).
Priidu Neemre

5

저장 프로시 저는 시퀀스를 다시 시작합니다.

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;

/


+1-시퀀스 이름을 전달하도록 매개 변수를 지정할 수도 있습니다.
DCookie

4

Oracle에서 시퀀스를 재설정하는 또 다른 방법이 있습니다 : maxvaluecycle속성 설정 . 때 nextval시퀀스가 안타 maxvalue경우, cycle프로퍼티가 설정되어 그것을부터 다시 시작됩니다 minvalue시퀀스.

음수를 설정하는 것과 비교하여이 방법의 장점은 increment by재설정 프로세스가 실행되는 동안 시퀀스를 계속 사용할 수있어 재설정을 수행하기 위해 일부 중단 형식이 필요할 가능성을 줄입니다.

의 값 maxvalue은 전류보다 커야 nextval하므로 아래 절차에는 절차에서를 선택 nextval하고 cycle속성을 설정하는 사이에 시퀀스에 다시 액세스 할 경우 버퍼를 허용하는 선택적 매개 변수가 포함 됩니다.

create sequence s start with 1 increment by 1;

select s.nextval from dual
connect by level <= 20;

   NEXTVAL
----------
         1 
...
        20

create or replace procedure reset_sequence ( i_buffer in pls_integer default 0)
as
  maxval pls_integer;
begin

  maxval := s.nextval + greatest(i_buffer, 0); --ensure we don't go backwards!
  execute immediate 'alter sequence s cycle minvalue 0 maxvalue ' || maxval;
  maxval := s.nextval;
  execute immediate 'alter sequence s nocycle maxvalue 99999999999999';

end;
/
show errors

exec reset_sequence;

select s.nextval from dual;

   NEXTVAL
----------
         1 

이 절차는 여전히 다른 세션이 값 0을 가져올 가능성을 허용하며, 이는 문제가 될 수도 있고 아닐 수도 있습니다. 그렇다면 항상 다음을 수행 할 수 있습니다.

  • minvalue 1첫 번째 변경에서 설정
  • 두 번째 nextval반입 제외
  • nocycle나중에 실행되도록 속성을 다른 프로 시저로 설정하기 위해 명령문을 이동하십시오 (이를 원한다고 가정).

3

Jezus, 인덱스 재시작을위한이 모든 프로그래밍 ... 아마도 바보 일지 모르지만, Oracle 12 이전 버전 (다시 시작 기능이 있음)의 경우 simpel의 문제점은 무엇입니까?

drop sequence blah;
create sequence blah 

?


2
시퀀스를 삭제하는 주된 문제는 시퀀스에 부여 된 권한이 손실된다는 것입니다.
Jon Heller

1
알았어, 존 대부분을 복원하는 것은 모든 프로그래밍보다 훨씬 적은 시간이 소요됩니다. 좋은 DBA는 보통 문제가되지 않도록 스크립트를 가지고 있습니다 :-)
Lawrence

2

1) 아래와 같이 SEQUENCE를 작성한다고 가정하십시오.

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

2) 이제 SEQUENCE에서 값을 가져옵니다. 아래 그림과 같이 4 번 가져 왔다고합시다.

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

3) 위의 4 가지 명령을 실행 한 후 SEQUENCE의 값은 4가됩니다. 이제 SEQUENCE의 값을 1로 다시 설정했다고 가정합니다. 다음 단계를 따르십시오. 아래에 표시된 순서대로 모든 단계를 수행하십시오.

  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

2

시퀀스의 INCREMENT 값을 변경하고, 증가시킨 다음 다시 변경하는 것은 매우 고통스럽지 않으며 시퀀스를 삭제 / 재 작성했을 때 모든 보조금을 다시 설정할 필요가 없다는 추가 이점이 있습니다.


2

모든 시퀀스를 재설정하는 블록을 만듭니다.

DECLARE
    I_val number;
BEGIN
    FOR US IN
        (SELECT US.SEQUENCE_NAME FROM USER_SEQUENCES US)
    LOOP
        execute immediate 'select ' || US.SEQUENCE_NAME || '.nextval from dual' INTO l_val;
        execute immediate 'alter sequence ' || US.SEQUENCE_NAME || ' increment by -' || l_val || ' minvalue 0';
        execute immediate 'select ' || US.SEQUENCE_NAME || '.nextval from dual' INTO l_val;
        execute immediate 'alter sequence ' || US.SEQUENCE_NAME || ' increment by 1 minvalue 0';
    END LOOP;
END;

2

다음은 시퀀스에 의해 반환 된 다음 값과 훨씬 더 많은 값을 변경하는보다 강력한 절차입니다.

  • 먼저 전달 된 문자열이 동적 SQL 문을 직접 작성하는 데 사용되지 않으므로 SQL 주입 공격으로부터 보호합니다.
  • 둘째, 다음 시퀀스 값이 최소 또는 최대 시퀀스 값의 범위를 벗어나는 것을 방지합니다. 는 next_value! 수 = 것 min_value사이 min_valuemax_value.
  • 셋째, 현재 (또는 제안 된) increment_by설정과 다른 모든 시퀀스 설정을 정리할 때 고려합니다.
  • 네 번째 매개 변수는 첫 번째 매개 변수를 제외한 모든 매개 변수는 선택 사항이며, 지정하지 않는 한 현재 시퀀스 설정을 기본값으로 사용합니다. 선택적 매개 변수를 지정하지 않으면 조치가 수행되지 않습니다.
  • 마지막으로 존재하지 않거나 현재 사용자가 소유하지 않은 시퀀스를 변경하려고하면 ORA-01403: no data found오류가 발생합니다.

코드는 다음과 같습니다.

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;

2

내 프로젝트에서 누군가 시퀀스를 사용하지 않고 수동으로 레코드를 입력 한 경우 시퀀스 값을 수동으로 재설정해야합니다.

declare
max_db_value number(10,0);
cur_seq_value number(10,0);
counter number(10,0);
difference number(10,0);
dummy_number number(10);

begin

-- enter table name here
select max(id) into max_db_value from persons;
-- enter sequence name here
select last_number into cur_seq_value from user_sequences where  sequence_name = 'SEQ_PERSONS';

difference  := max_db_value - cur_seq_value;

 for counter in 1..difference
 loop
    -- change sequence name here as well
    select SEQ_PERSONS.nextval into dummy_number from dual;
 end loop;
end;

시퀀스가 지연되는 경우 위의 코드가 작동합니다.


1

아래에 표시된 CYCLE 옵션을 사용할 수 있습니다.

CREATE SEQUENCE test_seq
MINVALUE 0
MAXVALUE 100
START WITH 0
INCREMENT BY 1
CYCLE;

이 경우 시퀀스가 ​​MAXVALUE (100)에 도달하면 MINVALUE (0)로 재순환됩니다.

감소 된 시퀀스의 경우 시퀀스는 MAXVALUE로 재순환됩니다.


1
downvoter의 경우 (이 의견을 보지 못할 것입니다) CYCLE 속성은 시퀀스 재설정을 수행하는 데 사용한 것과 정확히 같습니다. 재설정이 자동이라는 사실이 목표를 달성하지 못했다는 것을 의미하지는 않습니다. OP는 기존 시퀀스에 대해 재설정을 수행하도록 지정하지 않았습니다 !
Jeromy French

1

모든 자동 증가 시퀀스를 실제 데이터와 일치시키는 방법은 다음과 같습니다.

  1. 이 스레드에서 이미 설명한대로 다음 값을 적용하는 프로 시저를 작성하십시오.

    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 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;

노트:

  1. 프로시 저는 트리거 코드에서 이름을 추출하며 명명 규칙에 의존하지 않습니다.
  2. 실행하기 전에 생성 된 코드를 확인하려면 마지막 두 줄에서 주석을 전환하십시오.

1

사용자가 값을 알 필요가 없으며 시스템이 변수를 가져 와서 업데이트하는 대안을 만듭니다.

--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;

-1

나를 위해 일한 저장 프로 시저

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;

저장 프로 시저를 사용하는 방법 :

execute reset_sequence('company_sequence','company');
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.