はじめに
アプリケーションの中で重複しない連番の採番を実装することがあるかと思います。
連番用をテーブルを作って、そこで管理することもできますが、Oracleのシーケンスを使うともっと簡単に連番の採番機構を実装することができます。
シーケンスの作成
シーケンスは、以下の構文で作成することができます。
-- CREATE SEQUENCE シーケンス名; CREATE SEQUENCE RENBAN;
一度シーケンスを作れば、RENBAN.NEXTVALで次の連番を取得することができます。
また、現在の連番はRENBAN.CURRVALで取得することができます。
その他のパラメタについては、以下のマニュアルを参照してください。
シーケンスを使ったPL/SQL
シーケンスを使ったサンプルのPL/SQLです。
連番を振りながら、100件レコードをinsertしています。
DECLARE vNum NUMBER; BEGIN vNum := 0; LOOP --レコードを挿入 INSERT INTO table01 ( id, name, furigana, seibetsu, birthday ) VALUES ( lpad(RENBAN.NEXTVAL, 8, '0'), concat('テスト 太郎', TO_MULTI_BYTE(RENBAN.CURRVAL)), concat('てすと たろう', TO_MULTI_BYTE(RENBAN.CURRVAL)), CASE MOD(RENBAN.CURRVAL, 2) WHEN 0 THEN '男' ELSE '女' END, TO_CHAR(TO_DATE('20130101','YYYYMMDD') + FLOOR(DBMS_RANDOM.VALUE(0, 365)), 'YYYYMMDD') ); --カウンタのカウントアップ vNum := vNum + 1; --コミット COMMIT; --スリープ DBMS_LOCK.SLEEP(1); -- 100件登録したら終了 IF vNum = 100 THEN EXIT; END IF; END LOOP; dbms_output.put_line (vNum || '件挿入しました'); END; /
シーケンスの排他制御
シーケンスの生成機構によって排他制御が行われているようです。
上記PL/SQLを3多重で流してみましたが、重複した連番が採番されることはありませんでした。
連番は必ず保証されるの?
NOORDERを指定すると、要求どおりの順で順序番号を生成することは保証されません。これはデフォルトです。
CREATE SEQUENCE
シーケンス・ジェネレータはインスタンス毎に存在する。すなわちキャッシュもインスタンス毎に用意される。 デフォルトのシーケンスの場合、キャッシュサイズ 20、NOORDER であるので、たとえば
インスタンスAのキャッシュ 1 ~ 20
インスタンスBのキャッシュ 21 ~ 40
ディクショナリの値 41
のようにキャッシュされる。このため、NOORDER の場合に 1, 21, 2, 22 ... のように採番されることがある。
これは ORDER にして回避することができる。
しかしキャッシュはされなくなる。シングルインスタンスでなければ ORDER とキャッシュは両立しない。
ある特定のインスタンスから取得すれば両立するが、そのインスタンスが停止するとすべての採番が停止する。
シーケンスについての FAQ - オラクル・Oracleをマスターするための基本と仕組み
ロールバックによって、連番が抜ける
1つ以上の表に対して同一の順序を使用できます。順序番号が生成および使用されるトランザクションが最終的にロールバックされた場合、個々の順序番号が連続していないように見える場合があります。
CREATE SEQUENCE