Oracleでシーケンスをリセットするにはどうすればよいですか?


170

ではPostgreSQLの、私はこのような何かを行うことができます。

ALTER SEQUENCE serial RESTART WITH 0;

Oracleに相当するものはありますか?


1
こちらの「シーケンスのリセット」をご覧ください
gerikson 2008

3
警告:以下のすべてのコードは、「1ずつ増加」で最初に作成されたシーケンスに対してのみ有効です。元のシーケンスが増分!= 1で作成された場合。上記の手順のいずれかを適用すると、増分が1に変わります。使用する正しい増分値は、user_sequencesビューから取得できます。

1
シーケンスをドロップして再作成
Viswanath Lekshmanan '27 / 07/13

回答:


153

次に、Oracleの第一人者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
もう1つの良い議論もここにあります:シーケンスをリセットする方法?


@Dougman:hi 'beginner ....上記の回答で、なぜ最後の節に言及するのですか?p_seq_name || '.nextval INTO l_val from dual';
Thiyagu ATR 2013

@Thiyagu:PL / SQLでは、これは、execute immediate最大で1行を返す選択の出力をキャプチャするために使用する場合の構文です。即時実行に関するドキュメントは次のとおり
Doug Porter

@matraシーケンスをリセットし、同じシーケンスの他のユーザーと並行環境にいる必要があるシナリオはありません。
Ekevoo 2014

なぜシーケンスを選択する必要があるのか​​、なぜ最後の行を実行しないのか'alter sequence ' || p_seq_name || ' increment by 1 minvalue 0';
悟空

100

真の再起動は不可能です。(私が間違っている場合は修正してください!)

ただし、0に設定したい場合は、削除して再作成するだけです。

特定の値に設定する場合は、INCREMENTを負の値に設定して、次の値を取得できます。

つまり、シーケンスが500の場合、次のようにして100に設定できます。

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

4
PLSQLの人々のためのちょうどメモ。必ず「制限1」を追加してください。または、 "rownum = 1"をselectステートメントに指定しないと、nextValが数回実行されて、-400だけインクリメントされることになります。
user830914 2014年

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
ドロップすると、そのシーケンスに依存するオブジェクトがすべて無効になり、再コンパイルする必要があることに注意してください。
Doug Porter

22
また、シーケンスから選択するために与えられたすべての許可を再付与する必要があります。
GreenGiant 2013年

37
alter sequence serial restart start with 1;

この機能は18cで公式に追加されましたが、12.1では非公式に利用可能です。

12.1でこの文書化されていない機能を使用することは間違いなく安全です。構文は公式ドキュメントに含まれていませんが、OracleパッケージDBMS_METADATA_DIFFによって生成されます。実動システムで何度か使用しました。しかし、Oracleサービスリクエストを作成し、ドキュメントのバグではないことを確認しました。この機能は本当にサポートされていません。

18cでは、この機能はSQL言語構文には表示されませんが、 『データベース管理者ガイド』に含まれています。


@Jonさん、ドキュメントに記載されていない機能は知っていますが、DBMS_METADATA_DIFFから生成されたスクリプトに表示されることを知りませんでした。スクリプトの生成方法、手順などを教えてください。私もそれをテストしようとします。
Lalit Kumar B

@LalitKumarB この質問に答えている間、私はその機能を偶然見つけました。
Jon Heller

1
ああ、今それを得た。ありがとう:-)
Lalit Kumar B

これは、「alter table your_table modify(id is default for null on identity as start with limit value)」をサポートするために実装されたと思います。標準シーケンスでも動作することを知ってうれしいです!
オリバー

1
シーケンスの最小値が0より大きい場合は、書き込みを検討してください... RESTART START WITH 0 MINVALUE 0
conceptdeluxe

33

私のアプローチは、ダグマンの例に対するほんの少しの拡張です。

拡張機能は...

シード値をパラメーターとして渡します。どうして?シーケンスをいくつかのテーブルで使用されいる最大IDにリセットするものを呼び出すのが好きです。一連のシーケンス全体に対して複数の呼び出しを実行する別のスクリプトからこのプロシージャを呼び出し、nextvalを、一意の識別子にシーケンスの値を使用している主キー違反を引き起こさないほど高いレベルにリセットします。

また、以前のminvalueを尊重します。実際に、必要な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可能性があることです。スクリプトが実行されるノードに応じて、さまざまな値のいずれかになる可能性があります。スクリプトを再実行すると、結果が異なる場合があります。複数回実行すると、最終的に特定の値に落ち着きました。
ジェフリーケンプ

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 16

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 2013

4

Oracleでシーケンスをリセットする別の方法があります。maxvalueおよびcycleプロパティを設定します。nextvalシーケンスのがにヒットしたときに、プロパティが設定されているmaxvalue場合はcycleminvalueは、シーケンスのます。

ネガティブを設定することと比較したこの方法の利点 increment by、リセットプロセスの実行中にシーケンスを引き続き使用できるため、リセットを実行するために何らかの形式の停止を行う必要がなくなるということです。

の値maxvalueはcurrentより大きい必要がある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最初の変更で設定
  • 2番目のnextvalフェッチを除外する
  • ステートメントを移動して、nocycleプロパティを別のプロシージャに設定し、後で実行します(これを実行する場合)。

3

Jezus、このすべてのプログラミングはインデックスの再起動のみです...おそらく私はばかですが、Oracle 12より前(再起動機能があります)の場合、simpelの何が問題になっていますか。

drop sequence blah;
create sequence blah 


2
シーケンスの削除に関する主な問題は、シーケンスに付与された特権を失うことです。
Jon Heller

1
承知しました、ジョン。ほとんどの場合、これらを復元することは、すべてのプログラミングよりもはるかに少ない時間で済みます。良いDBAは通常、スクリプトを持っているので問題になりません:-)
Lawrence

2

1)以下に示すようなシーケンスを作成するとします。

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
  • 3つ目は、increment_byクリーンアップ時に現在の(または提案された)設定とその他すべてのシーケンス設定を考慮に入れます。
  • 4番目のパラメーターを除くすべてのパラメーターはオプションであり、指定されていない限り、現在のシーケンス設定がデフォルトとして使用されます。オプションのパラメーターが指定されていない場合、アクションは実行されません。
  • 最後に、存在しない(または現在のユーザーが所有していない)シーケンスを変更しようとすると、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
ダウンボーター(このコメントは決して表示されません)の場合: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. 実行前に生成されたコードを確認するには、最後の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.