使用している場合に値をリセットしない理由:
20個のレコードがあり、5〜10個のレコードを削除するとどうなりますか?シーケンスを再設定しても解決されないギャップが途中にあります。数列は、ギャップのない数列、完全な1、2..nを生成することはありません。
呼び出し.nextval
て値を使用しない場合、値はなくなります。シーケンスを削除して再作成しますか?挿入を開始してキャンセルし、Oracleが行ったことをロールバックすると、これらの値は失われます。設定すると、ギャップは少なくなりますが、パフォーマンスが低下します。その価値はありますか?nocache
パフォーマンスの問題を回避するために、キャッシュは、すべてのセッションで一度に実行すると予想される挿入の数に設定する必要があります。シーケンスは、正の整数のセットを再生成しないように、ロックなどを使用せずに代理キーを作成する非常に迅速でスケーラブルな方法を提供するように設計されています。
結局のところ、それは少しでも問題ではないはずです。テーブルのキーとして途切れのないシーケンスに依存している場合は、シーケンスではなくデータに問題があります。
質問への回答:
実際にあなたの質問に答えるには、次のことを行う必要があります。
- まず、テーブル内の最大ID(シーケンス)値を確認します。
- 次に、シーケンスをドロップして再作成します。
最大値を見つけることは、パフォーマンスへの別のヒットを犠牲にして、シーケンスを動的に再作成する必要があることを意味します。
これが発生しているときにテーブルに何かを挿入しようとすると、失敗し、次のシーケンスを使用するトリガーまたはその他のオブジェクトが無効になる可能性があります。
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がコメントで提案したように、シーケンスを削除して再作成せずにこれを行う方法があります。
つまり、次のようになります。
id
テーブルの最大値とシーケンスの現在の値の差を計算します。
- この負の数で増分するようにシーケンスを変更する
- シーケンスを変更して、もう一度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>