理系学生日記

おまえはいつまで学生気分なのか

シーケンスオブジェクトの現在値を変更する方法

Oracle にはシーケンスオブジェクトというものがあって、これを使えばシステムグローバルなシーケンス値が取得できます。

この値を使って主キーを生成するとかよくあるパターンですね。

select sequence_name.nextval from dual;
-- これを連続で実行すると、順に n, n+1, n+2 みたいなシーケンス値が返ってくる

で、ときどき、このシーケンス値の現在値を変更したい、みたいな状況があります。
例えば、

  1. テーブル A の主キーはシーケンスオブジェクトから取得している
  2. 本番環境のテーブル A のデータを開発環境にコピったら、主キーが開発環境のシーケンス値よりもずっと大きいレコードができてしまった
  3. ヤバい

というような状況です。開発環境のシーケンス値が 10, でも主キーが 100000000 でした、みたいな状況ヤバいですね。

この場合、開発環境のシーケンス値を 100000000 まで増やせば良いわけですが、シーケンスオブジェクトの取る値を変更する便利な術は提供されいません。なんとかする方法はいくつかあるのですが、わりかしダルかったりします。

  • 以下のようなのを 100000000 回ほどブン回すプロシージャを書いて実行する→結構時間がかかってダルい
select sequence_name.nextval from dual;
  • シーケンスオブジェクトを作り直す (drop & create) → 当該シーケンスに関する権限とかシノニムとか作り直すことになってダルい

生きていくのがそもそもダルいし、これ以上ダルくなりたくないです。そんなダルさを嫌う人間のために、以下のような回避策が存在します。

  1. シーケンスオブジェクトに取らせたい値を n, 現在値を s として、n-sを計算します
  2. シーケンスの increment by の値を変更します。
alter sequence sequence_name increment by n-s;
  1. increment by を変更した状態で、一回だけカウントアップします。
select sequence_name.nextval from dual;
  1. increment by の値を元に戻します。
alter sequence sequence_name increment by 1;

こんなふうにすれば、事実上シーケンス値を変更できた! みたいなことになります。よかったですね。