sql >> データベース >  >> RDS >> Oracle

Oracleのシーケンスの値をリセットする必要があります

    使用している場合に値をリセットしない理由:

    20個のレコードがあり、5〜10個のレコードを削除するとどうなりますか?シーケンスを再設定しても解決されないギャップが途中にあります。シーケンスは決してありません ギャップのない数列を生成します。完全な1、2 .. n

    .nextvalを呼び出す場合 なくなった値は使用しないでください 。シーケンスを削除して再作成しますか?挿入を開始してキャンセルし、Oracleが実行した内容をロールバックすると、これらの値はなくなったnocacheを設定した場合 そうすれば、ギャップは少なくなりますが、パフォーマンスが低下します。その価値はありますか?

    キャッシュは、すべてのセッションで一度に実行する予定の挿入の数に設定する必要があります。 パフォーマンスの問題を回避するため。シーケンスは、ロックなどを使用せずに代理キーを作成するための非常に迅速でスケーラブルな方法を提供するように設計されています。 正の整数のセットを再生成します。

    結局のところ、それは少しでも問題ではないはずです。テーブルのキーとして途切れのないシーケンスに依存している場合は、シーケンスではなくデータに問題があります。

    質問への回答:

    実際に質問に答えるには、次のことを行う必要があります。

    1. まず、テーブル内の最大ID(シーケンス)値を確認します。
    2. 次に、シーケンスを削除して再作成します。

    最大値を見つけることは、パフォーマンスへの別のヒットを犠牲にして、シーケンスを動的に再作成する必要があることを意味します。

    これが発生しているときにテーブルに何かを挿入しようとすると、失敗し、シーケンスを使用するトリガーまたはその他のオブジェクトが無効になる可能性があります。

    declare
    
       l_max_value number;
    
    begin
    
       select max(id)
         into l_max_value
         from my_table;
    
       execute immediate 'drop sequence my_sequence_name';
    
       -- nocache is not recommended if you are inserting more than
       -- one row at a time, or inserting with any speed at all.
       execute immediate 'create sequence my_sequence_name
                               start with ' || l_max_value
                          || ' increment by 1
                               nomaxvalue
                               nocycle
                               nocache';
    
    end;
    /
    

    私が言ったように、これは推奨されておらず、ギャップを無視する必要があります。

    更新-別名ジェフリーケンプのおかげでより良い答え:

    ドキュメントの推奨事項に反して、Jeffrey Kempがコメントで提案したように、これをなしで行う方法があります。 シーケンスを削除して再作成します。

    つまり、次のようになります。

    1. 最大のidの違いを計算する テーブル内のシーケンスの現在の値。
    2. この負の数でインクリメントするようにシーケンスを変更する
    3. シーケンスを変更して、もう一度1ずつインクリメントします。

    これの利点は、オブジェクトがまだ存在し、トリガー、付与などが引き続き維持されることです。欠点は、私が見ているように、別のセッションがあなたのセッションと同時にこの負の数だけ増加すると、行き過ぎてしまう可能性があることです。

    これがデモンストレーションです:

    テストを設定します:

    SQL> create sequence test_seq
      2   start with 1
      3   increment by 1
      4   nomaxvalue
      5   nocycle
      6   nocache;
    
    Sequence created.
    
    SQL>
    SQL> create table tmp_test ( id number(16) );
    
    Table created.
    
    SQL>
    SQL> declare
      2     l_nextval number;
      3  begin
      4
      5    for i in 1 .. 20 loop
      6       insert into tmp_test values ( test_seq.nextval );
      7    end loop;
      8
      9  end;
     10  /
    
    PL/SQL procedure successfully completed.
    
    SQL>
    SQL> select test_seq.currval from dual;
    
       CURRVAL
    ----------
            20
    
    SQL>
    SQL> delete from tmp_test where id > 15;
    
    5 rows deleted.
    
    SQL> commit;
    
    Commit complete.
    

    シーケンスを元に戻す

    SQL>
    SQL> declare
      2
      3     l_max_id number;
      4     l_max_seq number;
      5
      6  begin
      7
      8     -- Get the maximum ID
      9     select max(id) into l_max_id
     10       from tmp_test;
     11
     12     -- Get the current sequence value;
     13     select test_seq.currval into l_max_seq
     14       from dual;
     15
     16     -- Alter the sequence to increment by the difference ( -5 in this case )
    .
     17     execute immediate 'alter sequence test_seq
     18                          increment by ' || ( l_max_id - l_max_seq );
     19
     20     -- 'increment' by -5
     21     select test_seq.nextval into l_max_seq
     22       from dual;
     23
     24     -- Change the sequence back to normal
     25     execute immediate 'alter sequence test_seq
     26                          increment by 1';
     27
     28  end;
     29  /
    
    PL/SQL procedure successfully completed.
    
    SQL>
    SQL> select test_seq.currval from dual;
    
       CURRVAL
    ----------
            15
    
    SQL>
    


    1. MySQLとPDO

    2. MariaDBでのLENGTH()のしくみ

    3. Oracleで2つのデータベースオブジェクトを比較する方法は?

    4. datagrip変更を適用できませんこのテーブルは読み取り専用です。セルエディタの変更は適用できません