Oracleデータベースで連番を自動生成するシーケンス(SEQUENCE)は、主キーの採番やユニークIDの生成に欠かせないオブジェクトです。
しかし、テーブル設計の見直しやシステム移行の際に「シーケンスを削除したい」「番号をリセットしたい」と思ったことはありませんか?
この記事では、DROP SEQUENCEによるシーケンスの削除方法を中心に、シーケンスの作成・確認・変更・リセット、NEXTVAL/CURRVALの使い方、他RDBMS(PostgreSQL・SQL Server・MySQL)との比較、よくあるエラー(ORA-02289等)と対処法まで、実務で使える知識を網羅的に解説します。
シーケンス(SEQUENCE)とは
シーケンスとは、Oracleが提供する一意の連番を自動生成するデータベースオブジェクトです。テーブルとは独立して存在し、複数のテーブルやセッションから共有して利用できます。
シーケンスの特徴
- テーブルとは独立したデータベースオブジェクト
- 複数のテーブル・セッションから同時アクセス可能
- 採番はギャップ(欠番)が発生する場合がある(ロールバック時など)
- 主キーやユニークIDの生成に最適
- MySQLの
AUTO_INCREMENT とは異なり、テーブルに紐付かない
AUTO_INCREMENTとの違い
MySQLの AUTO_INCREMENT はテーブルのカラムに直接設定しますが、Oracleのシーケンスはテーブルから独立しています。
| 比較項目 |
Oracle SEQUENCE |
MySQL AUTO_INCREMENT |
| オブジェクト種別 |
独立したDBオブジェクト |
カラム属性 |
| テーブルとの関係 |
1つのシーケンスを複数テーブルで共有可能 |
1テーブル1カラムのみ |
| 採番タイミング |
NEXTVAL呼び出し時 |
INSERT時に自動 |
| 欠番の可能性 |
あり(ロールバック・キャッシュ等) |
あり(ロールバック時) |
| 減少方向の採番 |
可能(DECREMENT BY) |
不可 |
| 循環(サイクル) |
可能(CYCLE) |
不可 |
シーケンスの削除方法(DROP SEQUENCE)
シーケンスを削除するには、DROP SEQUENCE 文を使用します。
基本構文
構文
DROP SEQUENCE [スキーマ名.]シーケンス名;
ポイント:DROP SEQUENCE はDDL文のため、実行と同時に暗黙的にCOMMITされます。ROLLBACK で取り消すことはできません。
実行例
SQL
-- シーケンスを削除
DROP SEQUENCE emp_seq;
-- スキーマを指定して削除
DROP SEQUENCE hr.emp_seq;
削除前の確認
シーケンスを削除する前に、そのシーケンスが他のオブジェクト(トリガー、プロシージャ等)で参照されていないか確認しましょう。
SQL
-- シーケンスを参照しているオブジェクトを確認
SELECT name, type, referenced_name
FROM user_dependencies
WHERE referenced_name = 'EMP_SEQ'
AND referenced_type = 'SEQUENCE';
注意:シーケンスを削除しても、そのシーケンスを参照しているトリガーやプロシージャは自動削除されません。参照元オブジェクトは INVALID(無効)状態になり、次回実行時にエラーが発生します。
存在しないシーケンスの削除
存在しないシーケンスを削除しようとすると ORA-02289 エラーが発生します。スクリプトで安全に削除したい場合は、PL/SQLで例外処理を行います。
PL/SQL
-- 存在する場合のみ削除(エラーを無視)
BEGIN
EXECUTE IMMEDIATE 'DROP SEQUENCE emp_seq';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -2289 THEN
RAISE;
END IF;
END;
/
Oracle 23c以降の新構文
- Oracle 23cから
DROP SEQUENCE IF EXISTS 構文が使えます
- 例:
DROP SEQUENCE IF EXISTS emp_seq;
- 23c未満ではPL/SQLの例外処理で代替してください
シーケンスの確認方法
現在のスキーマに存在するシーケンスの一覧や設定を確認する方法です。
USER_SEQUENCES:自分のシーケンスを確認
SQL
-- 自分が所有するシーケンスの一覧と設定を確認
SELECT sequence_name,
min_value,
max_value,
increment_by,
last_number,
cache_size,
cycle_flag,
order_flag
FROM user_sequences
ORDER BY sequence_name;
実行結果
SEQUENCE_NAME MIN_VALUE MAX_VALUE INCREMENT_BY LAST_NUMBER CACHE_SIZE CYCLE_FLAG ORDER_FLAG
------------- --------- -------------------- ------------ ----------- ---------- ---------- ----------
DEPT_SEQ 1 9999999999999999999 1 100 20 N N
EMP_SEQ 1 9999999999999999999 1 1050 20 N N
ORDER_SEQ 1 9999999999999999999 10 1 20 N N
| カラム名 |
説明 |
SEQUENCE_NAME |
シーケンス名 |
MIN_VALUE |
最小値 |
MAX_VALUE |
最大値 |
INCREMENT_BY |
増分値 |
LAST_NUMBER |
次にキャッシュされる値(現在値ではない) |
CACHE_SIZE |
キャッシュするシーケンス値の数 |
CYCLE_FLAG |
最大値到達時に循環するか(Y/N) |
ORDER_FLAG |
順序保証するか(Y/N、RAC環境用) |
注意:LAST_NUMBER は「次に払い出される値」ではなく、「次にキャッシュされる先頭の値」です。現在の採番値を正確に知りたい場合は シーケンス名.CURRVAL を使用してください。
ALL_SEQUENCES:アクセス可能なすべてのシーケンス
SQL
-- 他スキーマのシーケンスも含めて確認
SELECT sequence_owner,
sequence_name,
increment_by,
last_number
FROM all_sequences
WHERE sequence_owner = 'HR'
ORDER BY sequence_name;
特定のシーケンスが存在するか確認
SQL
-- 特定のシーケンスが存在するか確認
SELECT COUNT(*) AS seq_exists
FROM user_sequences
WHERE sequence_name = 'EMP_SEQ';
シーケンスの作成(CREATE SEQUENCE)
新しいシーケンスを作成する構文とオプションを解説します。
基本構文
構文
CREATE SEQUENCE [スキーマ名.]シーケンス名
[START WITH 初期値]
[INCREMENT BY 増分値]
[MINVALUE 最小値 | NOMINVALUE]
[MAXVALUE 最大値 | NOMAXVALUE]
[CACHE キャッシュ数 | NOCACHE]
[CYCLE | NOCYCLE]
[ORDER | NOORDER];
オプションの詳細
| オプション |
説明 |
デフォルト |
START WITH |
シーケンスの開始値 |
1(昇順)/ MAXVALUE(降順) |
INCREMENT BY |
増分値(負数で降順も可) |
1 |
MINVALUE |
シーケンスの最小値 |
1(昇順)/ -(10^27)(降順) |
MAXVALUE |
シーケンスの最大値 |
10^28 – 1(昇順)/ -1(降順) |
CACHE n |
メモリにキャッシュする採番数 |
20 |
NOCACHE |
キャッシュしない(欠番が少ない) |
– |
CYCLE |
最大値/最小値到達後に循環する |
NOCYCLE |
ORDER |
採番の順序を保証(RAC環境向け) |
NOORDER |
作成例:基本的なシーケンス
SQL
-- 最もシンプルなシーケンス(デフォルト設定)
CREATE SEQUENCE emp_seq;
作成例:オプションを指定
SQL
-- 実務でよく使うシーケンス設定
CREATE SEQUENCE order_seq
START WITH 1000
INCREMENT BY 1
MINVALUE 1000
MAXVALUE 9999999
CACHE 50
NOCYCLE
NOORDER;
降順シーケンスの作成例
SQL
-- 降順(デクリメント)のシーケンス
CREATE SEQUENCE countdown_seq
START WITH 100
INCREMENT BY -1
MINVALUE 1
MAXVALUE 100
NOCACHE
NOCYCLE;
循環(CYCLE)シーケンスの作成例
SQL
-- 1〜12を繰り返す(月番号の生成等)
CREATE SEQUENCE month_seq
START WITH 1
INCREMENT BY 1
MINVALUE 1
MAXVALUE 12
CACHE 12
CYCLE;
シーケンスの使い方(NEXTVAL / CURRVAL)
シーケンスから値を取得するには、疑似カラムの NEXTVAL と CURRVAL を使用します。
NEXTVAL:次の値を取得
NEXTVAL を呼び出すたびに、シーケンスの値がインクリメント(増分)されます。
SQL
-- 次の連番を取得
SELECT emp_seq.NEXTVAL FROM dual;
-- INSERT文で使用(最も一般的な使い方)
INSERT INTO employees (emp_id, emp_name, email)
VALUES (emp_seq.NEXTVAL, '山田太郎', 'yamada@example.com');
実行結果(SELECT)
NEXTVAL
---------
1
CURRVAL:現在の値を取得
CURRVAL は、同一セッションで最後に取得した NEXTVAL の値を返します。
SQL
-- 先にNEXTVALを呼び出す(必須)
SELECT emp_seq.NEXTVAL FROM dual;
-- 現在のセッションで最後に取得した値を確認
SELECT emp_seq.CURRVAL FROM dual;
注意:セッション開始後に一度も NEXTVAL を呼び出していない状態で CURRVAL を参照すると、ORA-08002: sequence EMP_SEQ.CURRVAL is not yet defined in this session エラーが発生します。
NEXTVAL / CURRVALが使える場所・使えない場所
| 場所 |
NEXTVAL |
CURRVAL |
| SELECT … FROM dual |
○ |
○ |
| INSERT文のVALUES句 |
○ |
○ |
| INSERT文のSELECT句 |
○ |
○ |
| UPDATE文のSET句 |
○ |
○ |
| WHERE句 |
× |
× |
| DEFAULT値 |
×(12c以降は○) |
× |
| CHECK制約 |
× |
× |
| ビュー定義のSELECT |
× |
× |
実務での使用パターン
SQL
-- パターン1: 親子テーブルへの同時INSERT(CURRVALで同じIDを使う)
INSERT INTO orders (order_id, customer_id, order_date)
VALUES (order_seq.NEXTVAL, 101, SYSDATE);
INSERT INTO order_details (detail_id, order_id, product_id, qty)
VALUES (detail_seq.NEXTVAL, order_seq.CURRVAL, 501, 2);
-- パターン2: PL/SQLで変数に格納して使い回す
DECLARE
v_id NUMBER;
BEGIN
v_id := emp_seq.NEXTVAL;
INSERT INTO employees (emp_id, emp_name) VALUES (v_id, '鈴木一郎');
INSERT INTO emp_history (emp_id, action) VALUES (v_id, 'CREATED');
END;
/
シーケンスの変更(ALTER SEQUENCE)
既存のシーケンスの設定を変更するには ALTER SEQUENCE を使用します。
基本構文
構文
ALTER SEQUENCE シーケンス名
[INCREMENT BY 新しい増分値]
[MINVALUE 新しい最小値]
[MAXVALUE 新しい最大値]
[CACHE 新しいキャッシュ数 | NOCACHE]
[CYCLE | NOCYCLE]
[ORDER | NOORDER];
注意:ALTER SEQUENCE では START WITH は変更できません。開始値を変えたい場合は、シーケンスを DROP して再作成するか、後述のリセット方法を使用してください。
変更例
SQL
-- 増分値を変更
ALTER SEQUENCE emp_seq INCREMENT BY 5;
-- 最大値を変更
ALTER SEQUENCE emp_seq MAXVALUE 100000;
-- キャッシュサイズを変更
ALTER SEQUENCE emp_seq CACHE 100;
-- 循環を有効にする
ALTER SEQUENCE emp_seq CYCLE;
シーケンスのリセット方法
シーケンスの値を特定の値にリセットしたい場面は実務でよくあります。Oracleにはリセット専用の構文がないため、いくつかの方法があります。
方法1:DROP & CREATE で再作成(推奨)
最もシンプルで確実な方法です。
SQL
-- 手順1: シーケンスを削除
DROP SEQUENCE emp_seq;
-- 手順2: 同じ名前で再作成(START WITHで開始値を指定)
CREATE SEQUENCE emp_seq
START WITH 1
INCREMENT BY 1
NOCACHE;
注意:シーケンスを参照しているトリガーやプロシージャがある場合、DROP後にそれらは INVALID になります。再作成後に ALTER TRIGGER トリガー名 COMPILE; などで再コンパイルしてください。
方法2:INCREMENT BY を使ったリセット(DROPしない方法)
シーケンスをDROPしたくない場合(権限の問題やGRANTの再設定を避けたい場合)は、増分値を一時的に変更する方法が使えます。
SQL
-- 現在値が1050だとして、1にリセットしたい場合
-- 手順1: 現在値を確認
SELECT emp_seq.NEXTVAL FROM dual; -- 結果: 1050
-- 手順2: 増分値を「-(現在値 - 目標値)」に設定
ALTER SEQUENCE emp_seq INCREMENT BY -1049;
-- 手順3: NEXTVALで目標値まで戻す
SELECT emp_seq.NEXTVAL FROM dual; -- 結果: 1(1050 + (-1049) = 1)
-- 手順4: 増分値を元に戻す
ALTER SEQUENCE emp_seq INCREMENT BY 1;
PL/SQLで汎用的にリセットするプロシージャ
PL/SQL
CREATE OR REPLACE PROCEDURE reset_sequence(
p_seq_name IN VARCHAR2,
p_target IN NUMBER DEFAULT 1
) AS
v_current NUMBER;
v_diff NUMBER;
BEGIN
EXECUTE IMMEDIATE
'SELECT ' || p_seq_name || '.NEXTVAL FROM dual'
INTO v_current;
v_diff := p_target - v_current - 1;
IF v_diff != 0 THEN
EXECUTE IMMEDIATE
'ALTER SEQUENCE ' || p_seq_name ||
' INCREMENT BY ' || v_diff;
EXECUTE IMMEDIATE
'SELECT ' || p_seq_name || '.NEXTVAL FROM dual'
INTO v_current;
EXECUTE IMMEDIATE
'ALTER SEQUENCE ' || p_seq_name ||
' INCREMENT BY 1';
END IF;
END;
/
-- 使用例
EXEC reset_sequence('EMP_SEQ', 1);
方法3:Oracle 18c以降の RESTART(推奨)
Oracle 18c以降では、ALTER SEQUENCE ... RESTART 構文で簡単にリセットできます。
SQL(Oracle 18c以降)
-- 初期値(START WITH値)にリセット
ALTER SEQUENCE emp_seq RESTART;
-- 指定した値からリスタート
ALTER SEQUENCE emp_seq RESTART START WITH 500;
ポイント:Oracle 18c以降を使っている場合は、RESTART が最も簡単で安全なリセット方法です。DROPせずに権限やGRANT設定もそのまま維持できます。
他のRDBMSとの比較
シーケンス関連の構文はRDBMSによって大きく異なります。
| 操作 |
Oracle |
PostgreSQL |
SQL Server |
| 作成 |
CREATE SEQUENCE |
CREATE SEQUENCE |
CREATE SEQUENCE |
| 削除 |
DROP SEQUENCE |
DROP SEQUENCE |
DROP SEQUENCE |
| 次の値 |
seq.NEXTVAL |
nextval('seq') |
NEXT VALUE FOR seq |
| 現在値 |
seq.CURRVAL |
currval('seq') |
なし(変数で保持) |
| リセット |
RESTART(18c〜) |
RESTART WITH |
RESTART WITH |
| IF EXISTS |
IF EXISTS(23c〜) |
IF EXISTS(9.1〜) |
IF EXISTS(2016〜) |
MySQL には SEQUENCE がない
MySQLにはシーケンスオブジェクトがなく、代わりに AUTO_INCREMENT カラム属性を使います。
MySQL
-- MySQLでの連番生成(AUTO_INCREMENT)
CREATE TABLE employees (
emp_id INT AUTO_INCREMENT PRIMARY KEY,
emp_name VARCHAR(100) NOT NULL
);
-- AUTO_INCREMENTのリセット
ALTER TABLE employees AUTO_INCREMENT = 1;
PostgreSQL でのシーケンス操作
PostgreSQL
-- シーケンスの作成
CREATE SEQUENCE emp_seq START WITH 1 INCREMENT BY 1;
-- 次の値を取得(関数形式)
SELECT nextval('emp_seq');
-- 現在値を取得
SELECT currval('emp_seq');
-- リセット
ALTER SEQUENCE emp_seq RESTART WITH 1;
-- 安全な削除
DROP SEQUENCE IF EXISTS emp_seq;
SQL Server でのシーケンス操作
SQL Server
-- シーケンスの作成
CREATE SEQUENCE dbo.emp_seq
START WITH 1
INCREMENT BY 1;
-- 次の値を取得
SELECT NEXT VALUE FOR dbo.emp_seq;
-- リセット
ALTER SEQUENCE dbo.emp_seq RESTART WITH 1;
-- 安全な削除(SQL Server 2016以降)
DROP SEQUENCE IF EXISTS dbo.emp_seq;
よくあるエラーと対処法
シーケンス操作で発生しやすいエラーを一覧にまとめます。
| エラーコード |
メッセージ |
原因 |
対処法 |
ORA-02289 |
sequence does not exist |
指定したシーケンスが存在しない |
シーケンス名・スキーマを確認 |
ORA-08002 |
CURRVAL is not yet defined |
セッション内でNEXTVAL未実行 |
先にNEXTVALを呼び出す |
ORA-08004 |
sequence exceeds MAXVALUE |
MAXVALUEに到達(NOCYCLE時) |
MAXVALUEを増やすかCYCLEに変更 |
ORA-02283 |
cannot alter starting sequence number |
ALTER SEQUENCEでSTART WITHを変更 |
DROPして再作成、またはRESTART |
ORA-01722 |
invalid number |
シーケンス値を文字列カラムに使用 |
TO_CHARで型変換する |
ORA-01031 |
insufficient privileges |
シーケンスの操作権限がない |
GRANT SELECT ON seq TO ユーザー |
ORA-02289 の詳細と対処
最も頻繁に発生するエラーです。
エラー再現と対処
-- エラー発生例
SELECT nonexistent_seq.NEXTVAL FROM dual;
-- ORA-02289: sequence does not exist
-- 対処1: シーケンスの存在を確認
SELECT sequence_name
FROM user_sequences
WHERE sequence_name = 'NONEXISTENT_SEQ';
-- 対処2: 他のスキーマの場合はスキーマ名を指定
SELECT hr.emp_seq.NEXTVAL FROM dual;
-- 対処3: シノニムを確認
SELECT synonym_name, table_owner, table_name
FROM user_synonyms
WHERE synonym_name = 'EMP_SEQ';
ORA-08004 の詳細と対処
エラー再現と対処
-- MAXVALUE到達でエラー
-- ORA-08004: sequence SMALL_SEQ.NEXTVAL exceeds MAXVALUE
-- 対処1: MAXVALUEを増やす
ALTER SEQUENCE small_seq MAXVALUE 999999999;
-- 対処2: 最大値の制限を撤廃
ALTER SEQUENCE small_seq NOMAXVALUE;
-- 対処3: 循環を有効にする(用途に応じて)
ALTER SEQUENCE small_seq CYCLE;
実務でのベストプラクティス
シーケンスを本番環境で運用する際のポイントをまとめます。
1. 命名規則を統一する
| 命名パターン |
例 |
説明 |
テーブル名_SEQ |
EMPLOYEES_SEQ |
最も一般的 |
SEQ_テーブル名 |
SEQ_EMPLOYEES |
プレフィックス型 |
テーブル名_カラム名_SEQ |
EMPLOYEES_EMP_ID_SEQ |
カラムまで特定 |
2. CACHEの設定を最適化する
CACHEの使い分け
- CACHE 20(デフォルト):通常のOLTP処理に適切
- CACHE 100〜1000:大量INSERT(バッチ処理)時のパフォーマンス向上
- NOCACHE:欠番を最小限にしたい場合(ただしパフォーマンスが低下)
- キャッシュされた値はインスタンス障害時に失われ、欠番の原因になります
3. シーケンスの権限管理
SQL
-- 他のユーザーにシーケンスの使用を許可
GRANT SELECT ON emp_seq TO app_user;
-- シノニムを作成して他スキーマからシンプルにアクセス
CREATE SYNONYM emp_seq FOR hr.emp_seq;
-- 権限を取り消す
REVOKE SELECT ON emp_seq FROM app_user;
4. Oracle 12c以降のIDENTITYカラム
Oracle 12c以降では、テーブルカラムに直接連番を設定できる IDENTITY が追加されました。内部的にはシーケンスが自動作成されます。
SQL(Oracle 12c以降)
-- IDENTITYカラム(12c以降推奨)
CREATE TABLE employees (
emp_id NUMBER GENERATED ALWAYS AS IDENTITY,
emp_name VARCHAR2(100) NOT NULL
);
-- オプション付きIDENTITY
CREATE TABLE orders (
order_id NUMBER GENERATED BY DEFAULT AS IDENTITY
(START WITH 1000 INCREMENT BY 1),
customer_id NUMBER NOT NULL
);
| 種類 |
手動指定 |
用途 |
GENERATED ALWAYS |
不可(必ず自動採番) |
厳密にシステムが管理する連番 |
GENERATED BY DEFAULT |
可能(省略時のみ自動採番) |
データ移行時に手動値も入れたい場合 |
GENERATED BY DEFAULT ON NULL |
NULL指定時のみ自動採番 |
NULLを渡した場合にも自動採番 |
シーケンス操作のまとめ
| 操作 |
SQL構文 |
| 作成 |
CREATE SEQUENCE seq_name START WITH 1 INCREMENT BY 1 |
| 削除 |
DROP SEQUENCE seq_name |
| 次の値を取得 |
SELECT seq_name.NEXTVAL FROM dual |
| 現在値を取得 |
SELECT seq_name.CURRVAL FROM dual |
| 設定変更 |
ALTER SEQUENCE seq_name INCREMENT BY 5 |
| リセット(18c〜) |
ALTER SEQUENCE seq_name RESTART START WITH 1 |
| 一覧確認 |
SELECT * FROM user_sequences |
| 依存関係確認 |
SELECT * FROM user_dependencies WHERE referenced_type = 'SEQUENCE' |
まとめ
| 項目 |
内容 |
| シーケンスの削除 |
DROP SEQUENCE シーケンス名 で削除(DDL、暗黙コミット) |
| 削除前の確認 |
USER_DEPENDENCIES で参照元オブジェクトを確認 |
| シーケンスの確認 |
USER_SEQUENCES / ALL_SEQUENCES ビューで一覧・設定を確認 |
| 値の取得 |
NEXTVAL(次の値)/ CURRVAL(現在値) |
| リセット方法 |
DROP & CREATE、INCREMENT BY操作、RESTART(18c以降) |
| よくあるエラー |
ORA-02289(存在しない)、ORA-08002(CURRVAL未定義)、ORA-08004(MAXVALUE超過) |
| 12c以降の推奨 |
単純な連番には IDENTITY カラムが便利 |
シーケンスはOracleの基本オブジェクトですが、キャッシュによる欠番、DDLの暗黙コミット、DROP時の依存関係など、実務で注意すべきポイントが多くあります。特に本番環境でDROP SEQUENCEを実行する場合は、事前に参照元オブジェクトを確認し、影響範囲を把握してから実行しましょう。