12.

DB2のシーケンスおよびインクリメント(ID列)の違いとSQLで確認する方法

編集
この記事の要点
  • SEQUENCE と AUTO_INCREMENT (IDENTITY) は自動採番の仕組み
  • SEQUENCE: 独立オブジェクトとして DB に作成、複数テーブルで共有可
  • AUTO_INCREMENT / IDENTITY: テーブルのカラムに紐付く専用機能
  • 対応 DB: SEQUENCE → Oracle/PostgreSQL/DB2 / IDENTITY → MySQL/PG/SQL Server
  • JPA では @GeneratedValue(strategy=SEQUENCE/IDENTITY) で指定

 

SEQUENCE と AUTO_INCREMENT の違い

項目SEQUENCEAUTO_INCREMENT / IDENTITY
定義場所独立した DB オブジェクトカラムに付与
使い方SQL から明示的に取得INSERT で自動採番
共有複数テーブルで共有可能そのテーブル専用
取得タイミングINSERT 前 or トランザクション独立INSERT 後
パフォーマンスキャッシュで高速 (allocationSize)普通だがバッチが効きにくい
主な対応 DBOracle / PostgreSQL / DB2MySQL / SQL Server / PostgreSQL

SEQUENCE の使い方

Oracle

-- 作成
CREATE SEQUENCE user_seq
    START WITH 1
    INCREMENT BY 1
    NOCACHE
    NOCYCLE;

-- 取得
SELECT user_seq.NEXTVAL FROM DUAL;  -- 次の値 (1, 2, 3, ...)
SELECT user_seq.CURRVAL FROM DUAL;  -- 直前の値

-- INSERT で使用
INSERT INTO users (id, name) VALUES (user_seq.NEXTVAL, 'Alice');

-- バッチで高速化 (キャッシュ)
CREATE SEQUENCE user_seq START WITH 1 INCREMENT BY 1 CACHE 100;

PostgreSQL

-- 作成
CREATE SEQUENCE user_seq START WITH 1 INCREMENT BY 1;

-- 取得
SELECT nextval('user_seq');   -- 次の値
SELECT currval('user_seq');   -- 直前の値 (同セッション内)

-- INSERT
INSERT INTO users (id, name) VALUES (nextval('user_seq'), 'Alice');

-- SERIAL / BIGSERIAL (内部的に SEQUENCE 作成)
CREATE TABLE users (
    id SERIAL PRIMARY KEY,  -- INT + SEQUENCE 自動
    name VARCHAR(100)
);

-- IDENTITY (PostgreSQL 10+, 標準 SQL 準拠)
CREATE TABLE users (
    id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    name VARCHAR(100)
);

AUTO_INCREMENT / IDENTITY の使い方

MySQL

-- AUTO_INCREMENT
CREATE TABLE users (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100)
);

-- INSERT (id 省略可)
INSERT INTO users (name) VALUES ('Alice');  -- id 自動採番

-- 採番された ID 取得
SELECT LAST_INSERT_ID();

-- AUTO_INCREMENT 開始値変更
ALTER TABLE users AUTO_INCREMENT = 1000;

SQL Server

-- IDENTITY
CREATE TABLE users (
    id BIGINT IDENTITY(1, 1) PRIMARY KEY,  -- 開始 1, 増分 1
    name VARCHAR(100)
);

-- INSERT
INSERT INTO users (name) VALUES ('Alice');

-- 採番された ID 取得
SELECT SCOPE_IDENTITY();
SELECT @@IDENTITY;

-- 明示的に ID 指定したい場合
SET IDENTITY_INSERT users ON;
INSERT INTO users (id, name) VALUES (100, 'Special');
SET IDENTITY_INSERT users OFF;

PostgreSQL の SERIAL vs IDENTITY

-- SERIAL (古い書き方、互換性のため残存)
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100)
);
-- 内部的に "users_id_seq" SEQUENCE が自動作成される

-- IDENTITY (推奨、SQL 標準準拠)
CREATE TABLE users (
    id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    name VARCHAR(100)
);
-- 違い:
-- - GENERATED ALWAYS: 明示的に id 指定不可
-- - GENERATED BY DEFAULT: 必要なら指定可

JPA での選択

// IDENTITY (MySQL / SQL Server)
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

// SEQUENCE (Oracle / PostgreSQL)
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_seq")
@SequenceGenerator(name = "user_seq", sequenceName = "user_sequence", allocationSize = 50)
private Long id;

// AUTO (Hibernate が選択)
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

// UUID (Hibernate 6+)
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;

パフォーマンス比較

IDENTITY の制約

// IDENTITY だとバッチ INSERT で各行 1 つずつ ID 取得
// → JDBC バッチが効かない、遅い

// 1000 件 INSERT
for (int i = 0; i < 1000; i++) {
    em.persist(new User("user" + i));
}
// IDENTITY: 1000 個別 INSERT (遅い)
// SEQUENCE + allocationSize=100: 10 回シーケンス + 1000 バッチ (10x 高速)

SEQUENCE の allocationSize

@SequenceGenerator(
    name = "user_seq",
    sequenceName = "user_sequence",
    allocationSize = 100  // 100 件まとめて予約
)

# 動作:
# - シーケンス取得時、Hibernate が 1 回で 100 個 ID を確保
# - JVM メモリ内で 100 個使い切るまで DB アクセスなし
# - 大量 INSERT が大幅高速化

# 注意: 再起動・複数 JVM で ID 抜けが発生
# (許容できれば問題なし、シーケンスの目的は一意性であり連続性ではない)

UUID と比較

方式長所短所
AUTO_INCREMENT / IDENTITYシンプル・単一 DB で確実バッチ INSERT 遅い、分散システム不可
SEQUENCEバッチ最適化可、複数テーブル共有可DB 依存
UUID分散システム OK、ID 採番に DB 不要長い (36 chars)、ソート効率低
Snowflake ID分散 + 時系列順独自実装が必要

主キーの選定指針

  • 単一 DB の中小規模システム: AUTO_INCREMENT / IDENTITY が単純
  • Oracle / PostgreSQL でバッチ多用: SEQUENCE + allocationSize
  • 分散システム / マイクロサービス: UUID
  • 時系列ソートが重要 + 分散: Snowflake / ULID
  • レガシー互換: 既存システムに合わせる

シーケンスのリセット・確認

-- Oracle
SELECT user_seq.NEXTVAL FROM DUAL;  -- 現在値+1 を取得
-- リセットは drop + create (alter で nextval 直接設定不可)
DROP SEQUENCE user_seq;
CREATE SEQUENCE user_seq START WITH 1000;

-- PostgreSQL
SELECT currval('users_id_seq');
SELECT setval('users_id_seq', 1000);  -- 次回 1001 から
SELECT setval('users_id_seq', 1000, false);  -- 次回 1000 から

-- MySQL AUTO_INCREMENT
ALTER TABLE users AUTO_INCREMENT = 1000;
SHOW TABLE STATUS LIKE 'users';  -- 現在値確認

関連記事

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. DB接続コマンド
  2. データベース一覧の確認
  3. テーブル一覧の確認
  4. テーブル定義の確認
  5. DBの設定確認
  6. テーブルスペースの容量の確認および拡張
  7. データ型
  8. 複数カラムのUPDATE
  9. カラムの追加/削除/変更
  10. 自動番号付け (autoincrement) する方法
  11. インデックスの作成
  12. シーケンスおよびインクリメント(ID列)の違いと確認方法
  13. create table文の生成
  14. 特定スキーマの全テーブルの全カラム情報を取得する方法
  15. 【DB2】エラー一覧
  16. 【DB2】テーブル定義からCREATE TABLE文を生成する方法