使用している場合に値をリセットしない理由:
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>