シーケンス(SEQUENCE)は Oracle が提供する連番生成オブジェクトです。テーブルの主キー(サロゲートキー)として自動採番する際に最もよく使われます。
MySQL の AUTO_INCREMENT や PostgreSQL の SERIAL と異なり、Oracle のシーケンスはテーブルとは独立した別オブジェクトです。INSERT 時に シーケンス名.NEXTVAL で次の値を取得して使います。Oracle 12c 以降は IDENTITY 列を使ってテーブルに直接組み込む方法も使えます。
この記事でわかること
- CREATE SEQUENCE の各オプション(INCREMENT BY・START WITH・MAXVALUE・CACHE・CYCLE・ORDER)
- NEXTVAL・CURRVAL の使い方とセッションスコープの制約
- CACHE でパフォーマンスを上げる仕組みとギャップ(欠番)が発生する理由
- Oracle 12c 以降の IDENTITY 列(GENERATED ALWAYS / BY DEFAULT)
- シーケンスの値をリセット・変更する方法
CREATE SEQUENCE でシーケンスを作成する
CREATE SEQUENCE の基本構文とオプション
-- 最もシンプルな作成(すべてデフォルト値)
CREATE SEQUENCE order_id_seq;
-- INCREMENT BY 1(1ずつ増加)
-- START WITH 1(1から開始)
-- MAXVALUE 9999999999999999999999999999(最大値)
-- MINVALUE 1(最小値)
-- NOCYCLE(最大値に達したら停止)
-- CACHE 20(20個の値をメモリに事前生成)
-- NOORDER(RAC 環境でも発行順序を保証しない)
-- よくある主キー用のシーケンス設定
CREATE SEQUENCE order_id_seq
START WITH 1
INCREMENT BY 1
MAXVALUE 999999999 -- 明示的に最大値を設定(省略可)
NOCYCLE -- 最大値に達したらエラー(推奨)
CACHE 100 -- パフォーマンスのため 100 個キャッシュ
NOORDER; -- 発行順序を保証しない(シングルノードでは関係ない)
-- 逆順(デクリメント)シーケンス
CREATE SEQUENCE priority_seq
START WITH 100
INCREMENT BY -1
MAXVALUE 100
MINVALUE 1
NOCYCLE
NOCACHE;
-- CYCLE: 最大値に達したら最小値から繰り返す
CREATE SEQUENCE daily_seq
START WITH 1
INCREMENT BY 1
MAXVALUE 9999
CYCLE -- 9999 の次は MINVALUE(1) から再開
CACHE 50;
NEXTVAL と CURRVAL の使い方
NEXTVAL・CURRVAL・DEFAULT NEXTVAL の使い方
-- NEXTVAL: 次の値を取得する(取得するたびに値が進む)
SELECT order_id_seq.NEXTVAL FROM DUAL; -- 1
SELECT order_id_seq.NEXTVAL FROM DUAL; -- 2
-- CURRVAL: 現在のセッションで最後に取得した NEXTVAL の値を返す
-- ※ 同一セッションで NEXTVAL を少なくとも1回呼び出した後でないと使えない
SELECT order_id_seq.CURRVAL FROM DUAL; -- 2(直前の NEXTVAL と同じ)
-- INSERT で NEXTVAL を使う(最もよくある使い方)
INSERT INTO orders (order_id, customer_id, order_date)
VALUES (order_id_seq.NEXTVAL, 100, SYSDATE);
-- 親子テーブルに同じ NEXTVAL を使う(CURRVAL を活用)
INSERT INTO orders (order_id, customer_id) VALUES (order_id_seq.NEXTVAL, 100);
INSERT INTO order_items (order_id, item_id, product_id, qty)
VALUES (order_id_seq.CURRVAL, 1, 5001, 3); -- CURRVAL で親の order_id を再利用
-- DEFAULT 値に NEXTVAL を使う(Oracle 12c 以降)
CREATE TABLE products (
product_id NUMBER DEFAULT product_id_seq.NEXTVAL PRIMARY KEY,
name VARCHAR2(100) NOT NULL
);
INSERT INTO products (name) VALUES ('Widget'); -- product_id に自動採番
-- NEXTVAL が使える場所
-- ① SELECT ... FROM DUAL(単純な取得)
-- ② INSERT の VALUES 句
-- ③ SELECT リスト(INSERT INTO ... SELECT でも可)
-- ④ DEFAULT 値(12c 以降)
-- NEXTVAL が使えない場所
-- ① WHERE 句
-- ② GROUP BY / ORDER BY / HAVING 句
-- ③ DEFAULT 値(11g 以前)
-- ④ サブクエリの SELECT リスト(一部制限あり)
-- ⑤ CHECK 制約
CACHE の仕組みとギャップ(欠番)が発生する理由
シーケンスの CACHE はパフォーマンスのためにメモリ上に複数の値を事前確保する機能です。しかしキャッシュされた値はインスタンスの再起動やロールバックで失われるため、採番した値に欠番(ギャップ)が発生します。これはシーケンスの正常な動作であり、ギャップがあっても主キーとしての一意性は保たれます。
ギャップが発生するパターンと NOCACHE の使い方
-- ギャップが発生する主なパターン:
-- ① INSERT を ROLLBACK した場合(NEXTVAL で取得した値は戻らない)
BEGIN
INSERT INTO orders (order_id, ...) VALUES (order_id_seq.NEXTVAL, ...);
-- 何らかのエラーで ROLLBACK
ROLLBACK; -- order_id の値は失われる(次の NEXTVAL は連続していない)
END;
/
-- ② インスタンスの再起動(キャッシュされた値が失われる)
-- CACHE 100 に設定している場合、再起動ごとに最大 100 個の欠番が発生する可能性がある
-- ③ INSERT ALL でのシーケンス(INSERT ALL では NEXTVAL が1回だけ評価される・同じ値になる)
-- NG: INSERT ALL で NEXTVAL を使うと全行同じ値になりユニーク制約違反になる
-- → INSERT ALL ではシーケンスを使わず、別途採番してからデータを挿入する
-- NOCACHE: ギャップを最小化する(ただし毎回ディスク I/O が発生し低速)
CREATE SEQUENCE no_gap_seq
START WITH 1 INCREMENT BY 1
NOCACHE; -- キャッシュなし。再起動でもギャップが発生しにくいが遅い
-- ORDER: RAC 環境で複数ノードをまたいでも採番順序を保証する
-- (シングルノードでは NOORDER で問題ない)
CREATE SEQUENCE ordered_seq
START WITH 1 INCREMENT BY 1
CACHE 50 ORDER; -- RAC で順序保証が必要な場合
-- シーケンスの現在値を確認する
SELECT sequence_name, last_number, cache_size, increment_by,
cycle_flag, order_flag
FROM USER_SEQUENCES
WHERE sequence_name = 'ORDER_ID_SEQ';
-- last_number: 次に払い出す値(CACHE 分だけ先読みしているため実際より大きい場合がある)
シーケンスの変更とリセット
ALTER SEQUENCE でシーケンスを変更する
-- CACHE サイズを変更する ALTER SEQUENCE order_id_seq CACHE 200; -- MAXVALUE を変更する ALTER SEQUENCE order_id_seq MAXVALUE 9999999999; -- INCREMENT BY を変更する ALTER SEQUENCE order_id_seq INCREMENT BY 1; -- シーケンスをリセットする(値を初期値に戻す) -- Oracle 18c 以降: ALTER SEQUENCE ... RESTART が使える ALTER SEQUENCE order_id_seq RESTART; -- START WITH 値に戻す ALTER SEQUENCE order_id_seq RESTART START WITH 1; -- 指定した値に戻す(18c 以降) -- 18c 未満: 一度 DROP して再作成する(最もシンプル) DROP SEQUENCE order_id_seq; CREATE SEQUENCE order_id_seq START WITH 1 INCREMENT BY 1 CACHE 100; -- 18c 未満の代替: 現在値を取得してから大きな INCREMENT BY で一気に進める -- → 現在値を確認して、目的の値までジャンプさせる手法 -- ①現在の last_number を確認: SELECT last_number FROM USER_SEQUENCES WHERE sequence_name='ORDER_ID_SEQ'; -- ②INCREMENT BY を (目的値 - last_number) に設定して NEXTVAL を1回取得 ALTER SEQUENCE order_id_seq INCREMENT BY -100; -- 100 戻す例 SELECT order_id_seq.NEXTVAL FROM DUAL; -- 値を移動 ALTER SEQUENCE order_id_seq INCREMENT BY 1; -- 元の増分に戻す
Oracle 12c 以降の IDENTITY 列
Oracle 12c からは MySQL の AUTO_INCREMENT に近い IDENTITY 列を使えます。シーケンスを別途作成する必要がなく、テーブル定義にインラインで自動採番を設定できます。
IDENTITY 列の作成と挙動の違い
-- GENERATED ALWAYS AS IDENTITY: 常に自動採番(INSERT で値を指定するとエラー)
CREATE TABLE orders_v2 (
order_id NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
customer_id NUMBER NOT NULL,
order_date DATE DEFAULT SYSDATE
);
INSERT INTO orders_v2 (customer_id) VALUES (100); -- OK: order_id は自動採番
INSERT INTO orders_v2 (order_id, customer_id) VALUES (9999, 100); -- ORA-32795: エラー
-- GENERATED BY DEFAULT AS IDENTITY: デフォルトは自動採番だが INSERT で値を指定できる
CREATE TABLE orders_v3 (
order_id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
customer_id NUMBER NOT NULL
);
INSERT INTO orders_v3 (customer_id) VALUES (100); -- OK: 自動採番
INSERT INTO orders_v3 (order_id, customer_id) VALUES (9999, 100); -- OK: 値を指定できる
-- GENERATED BY DEFAULT ON NULL AS IDENTITY: NULL 挿入時に自動採番する
CREATE TABLE orders_v4 (
order_id NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY PRIMARY KEY,
customer_id NUMBER NOT NULL
);
-- IDENTITY 列のシーケンスオプションを指定する
CREATE TABLE orders_v5 (
order_id NUMBER GENERATED ALWAYS AS IDENTITY (
START WITH 1000
INCREMENT BY 1
CACHE 50
NOCYCLE
) PRIMARY KEY,
customer_id NUMBER
);
-- IDENTITY 列で内部的に作成されたシーケンスを確認する
SELECT table_name, column_name, identity_column, default_on_null
FROM USER_TAB_COLUMNS
WHERE identity_column = 'YES';
まとめ
- CREATE SEQUENCE:START WITH・INCREMENT BY・MAXVALUE・NOCYCLE・CACHE でシーケンスを定義する。主キー用には CACHE 100 程度が性能と管理のバランスが取れた設定
- NEXTVAL / CURRVAL:NEXTVAL は呼び出すたびに値が進む。同一セッション内で CURRVAL を使うと直前の NEXTVAL 値を再利用できる(親子テーブルの連携に便利)
- ギャップ(欠番)は正常動作:ROLLBACK・インスタンス再起動・INSERT ALL でギャップが発生する。ギャップを許容できない連番管理(連続した請求書番号など)には別の設計が必要
- CACHE vs NOCACHE:CACHE はパフォーマンスを上げるがギャップが増える。NOCACHE はギャップを減らすが遅い。本番用主キーは CACHE 20〜200 が一般的
- IDENTITY 列(12c 以降):GENERATED ALWAYS(値の指定不可)と GENERATED BY DEFAULT(値の指定可)の2種類。シーケンスを別途管理しなくて済むので新規テーブルには IDENTITY 列が便利
主キー・ユニーク制約との組み合わせ方は Oracle 制約(CONSTRAINT)完全ガイドを参照してください。Oracle 23ai の新機能(IF NOT EXISTS など)については Oracle 23ai 新機能完全ガイドも参照してください。