◀ 10.

Db2の自動採番|IDENTITY・ID取得とRESTARTの注意点

▶

Db2 LUWではIDENTITY属性を持つ列で自動採番します。通常のINSERT、生成されたIDの取得、移行時の明示値やRESTART/LOADを分けて確認します。

Db2の自動採番の定義とINSERTとID取得を確認しリセットを別管理とする図

この記事の要点
  • DB2 の自動採番は GENERATED ALWAYS AS IDENTITY / GENERATED BY DEFAULT AS IDENTITY
  • 初期値・増分: START WITH 1 INCREMENT BY 1、NO CACHE / NO CYCLE 等のオプション
  • SEQUENCE オブジェクトも併用可: CREATE SEQUENCE seq_name START WITH 1 → NEXTVAL FOR seq_name
  • RESTARTは採番状態を変える管理操作。確認や欠番解消のために実行しない
  • MySQL の AUTO_INCREMENT、PostgreSQL の SERIAL / GENERATED ... AS IDENTITY も採番の仕組みだが、構文・明示値・取得方法等は製品別に確認する

1. DB2 の IDENTITY 列

DB2 では列に IDENTITY 属性を付けて自動採番します。SQL 標準の GENERATED ... AS IDENTITY 構文に準拠しています。

以下は新規の検証用表を想定する例で、既存表へそのまま実行しません。NO CACHEは例固有の指定で推奨既定値ではありません。出力日時やIDは説明用で、同じ値が必ず返る記録ではなく、SELECT *にも並び順の保証はありません。通常INSERTでのALWAYSの制約と、LOAD等の別管理経路を区別してください。

-- GENERATED ALWAYS: アプリは絶対値を入れられない(DB が必ず採番)
CREATE TABLE customers (
    id          INTEGER NOT NULL
                  GENERATED ALWAYS AS IDENTITY
                  (START WITH 1 INCREMENT BY 1 NO CACHE),
    name        VARCHAR(100) NOT NULL,
    created_at  TIMESTAMP NOT NULL DEFAULT CURRENT TIMESTAMP,
    PRIMARY KEY (id)
);

-- INSERT は id を指定しない
INSERT INTO customers (name) VALUES ('Taro');
INSERT INTO customers (name) VALUES ('Hanako');

SELECT * FROM customers;
-- 1 | Taro   | 2026-05-17 10:00:00
-- 2 | Hanako | 2026-05-17 10:00:01

2. ALWAYS vs BY DEFAULT

属性挙動用途
GENERATED ALWAYS AS IDENTITY通常のLUW INSERTではDEFAULT以外の明示値を与えない。下の旧OVERRIDING例は推奨しないマスタテーブル(厳格)
GENERATED BY DEFAULT AS IDENTITYアプリ指定可(指定しなければ自動)移行 / インポート時

下の旧OVERRIDING SYSTEM VALUE例をLUWの上書き手順として実行しないでください。i等の別製品の構文/権限をLUWへ流用せず、通常INSERTでは列省略/DEFAULT等を使います。BY DEFAULTの明示値は内部の採番状態を自動的に既存最大値へ追従させる手段ではありません。手動値と自動値の衝突・一意制約を別に確認します。

-- ALWAYS の場合
INSERT INTO customers (id, name) VALUES (100, 'Direct');
-- SQL0798N: GENERATED ALWAYS で AS IDENTITY と定義された列に値を割り当てる
-- ことはできません

-- 上書きするには
INSERT INTO customers (id, name)
    OVERRIDING SYSTEM VALUE
    VALUES (100, 'Direct');

-- BY DEFAULT の場合は普通に
CREATE TABLE products (
    id INTEGER NOT NULL
        GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
    name VARCHAR(100),
    PRIMARY KEY (id)
);
INSERT INTO products (id, name) VALUES (1000, 'Direct OK');
INSERT INTO products (name) VALUES ('Auto');

3. オプションを使いこなす

次の開始値/増分/cache等は例で、ORDERのコメントにある「厳密に順序保証」は要求順の生成に限って読み替えます。COMMIT順や欠番なしを保証しません。型・上限・CYCLE・member構成に合わせて検討し、設定を増やすだけで安全/高速になると判断しないでください。

CREATE TABLE orders (
    id BIGINT NOT NULL
        GENERATED ALWAYS AS IDENTITY (
            START WITH 1000          -- 開始値
            INCREMENT BY 10          -- 増分
            MINVALUE 1000
            MAXVALUE 9999999999
            NO CYCLE                 -- 最大値到達でエラー
            CACHE 50                 -- 採番を 50 個ずつメモリにキャッシュ(高速化)
            ORDER                    -- 厳密に順序保証(パフォーマンス低下)
        ),
    customer_id INTEGER,
    PRIMARY KEY (id)
);

CACHEは事前割当による性能上の選択肢です。障害/停止時に未使用の割当値が失われることがあり、NO CACHEでもrollback等による欠番は防げません。ORDERは要求順の生成に関する指定で、COMMIT順や業務処理の完了順を保証しません。NO CACHE + ORDERを連番性や全環境の性能対策として一律に推奨しないでください。

4. SEQUENCE オブジェクト

テーブル列に紐づかない、独立した採番器を作りたい場合は SEQUENCE:

次の各文は独立した説明例で、一括実行しません。NEXTVAL/NEXT VALUEは値を消費し、PREVVAL/PREVIOUS VALUEは同じ接続の前の文で生成した値を参照するもので、旧コメントの「同一文中」とは異なります。直前のorders定義にはorder_no/code列がなく、このINSERTとつなげて動く例ではありません。ALTER/DROPは採番状態/オブジェクトを変更する管理操作です。

CREATE SEQUENCE order_seq
    AS INTEGER
    START WITH 1
    INCREMENT BY 1
    NO CYCLE
    CACHE 20;

-- 次の値を取得
SELECT NEXTVAL FOR order_seq FROM SYSIBM.SYSDUMMY1;

-- 同一文中の現在値を再利用
INSERT INTO orders (order_no, code)
VALUES (NEXTVAL FOR order_seq, 'A');
INSERT INTO order_items (order_no, item)
VALUES (PREVVAL FOR order_seq, 'item1');

-- 変更
ALTER SEQUENCE order_seq RESTART WITH 1000;
ALTER SEQUENCE order_seq INCREMENT BY 5;

-- 削除
DROP SEQUENCE order_seq;

5. リセット(RESTART)

次のRESTART例は確認用ではなく変更操作です。1への戻しやMAX(id)+1は、既存値・参照先・増分/方向・他接続の採番・cacheを確認せず使えません。値を巻き戻しても既存行/外部参照は更新されず、重複が生じ得ます。採番状態の復旧/切戻しも計画してください。

-- IDENTITY 列の次の値を変更
ALTER TABLE customers ALTER COLUMN id RESTART WITH 1;

-- 既存最大値の次から始め直す
SELECT MAX(id) FROM customers;  -- 例: 1234
ALTER TABLE customers ALTER COLUMN id RESTART WITH 1235;

-- 増分を変更
ALTER TABLE customers ALTER COLUMN id SET INCREMENT BY 10;

6. 生成された ID を取得

次の旧ブロックにはSQLとJavaが混在しており、一つのSQLファイルとして実行しません。IDENTITY_VAL_LOCALは同じ処理レベルの単一行VALUES INSERT等の条件があり、複数行分のID一覧や別接続の値を返す関数ではありません。Javaの生成キーは対応ドライバーと返却列/行数を確認し、PreparedStatementも適切にcloseします。FINAL TABLE内のINSERTはSELECTの形でも書込みで、ID取得はCOMMIT成功の証明ではありません。

-- 直前の INSERT で採番された ID
SELECT IDENTITY_VAL_LOCAL() FROM SYSIBM.SYSDUMMY1;

-- アプリから(PreparedStatement)
-- Java 例:
PreparedStatement ps = conn.prepareStatement(
    "INSERT INTO customers (name) VALUES (?)",
    Statement.RETURN_GENERATED_KEYS);
ps.setString(1, "Taro");
ps.executeUpdate();
try (ResultSet keys = ps.getGeneratedKeys()) {
    if (keys.next()) {
        long id = keys.getLong(1);
    }
}

-- SELECT FROM FINAL TABLE で同一文内で取得
SELECT id FROM FINAL TABLE (
    INSERT INTO customers (name) VALUES ('Taro')
);

7. 他 RDBMS との比較

RDBMS採番構文備考
DB2GENERATED ALWAYS AS IDENTITYSQL 標準
MySQLAUTO_INCREMENT独自構文、SEQUENCE 無し
PostgreSQLSERIAL / GENERATED ... AS IDENTITY後者が SQL 標準で推奨
OracleGENERATED AS IDENTITY (12c+) / SEQUENCE12c 未満は SEQUENCE + TRIGGER
SQL ServerIDENTITY(1,1)独自構文

8. INSERT 時の挙動 / 注意点

次の旧ブロックのID=1/2/3は、初期状態・他接続・auto commit等を省いた説明で再現値の保証ではありません。末尾のLOADはINSERTとは別の大きな変更です。IDENTITYの入力値を無視して再採番する修飾子はIDENTITYIGNOREで、生成式列向けのGENERATEDIGNOREと混同しません。IDENTITYMISSING/IDENTITYOVERRIDEも入力と対象属性による別指定で、一律に置換して実行しないでください。

-- ROLLBACK しても採番は戻らない(欠番が出る)
INSERT INTO customers (name) VALUES ('A');   -- id=1
INSERT INTO customers (name) VALUES ('B');   -- id=2
ROLLBACK;
INSERT INTO customers (name) VALUES ('C');   -- id=3(1,2 は欠番)

-- 一意性 + 採番は別概念
-- IDENTITY は採番するが UNIQUE 保証はしない → PRIMARY KEY を別途指定

-- LOAD ユーティリティで取り込み時
-- BY DEFAULT なら入力値を使い、ALWAYS なら IGNORE オプションで採番
LOAD FROM input.del OF DEL MODIFIED BY GENERATEDIGNORE
    INSERT INTO customers;

FAQ

Q: 採番がスキップして「欠番」が出る
A: 採番後のrollback/失敗や未使用cache等で欠番が生じます。単なる接続切断が常に欠番の直接原因とは限りません。欠番なしの業務番号は採番列とは別要件で、取消/監査/同時処理/再送を設計します。「別表とロック」だけで安全・完全になるわけではありません。

Q: 既存テーブルに後から IDENTITY を付けたい
A: LUWにはSET GENERATED ... AS IDENTITYの構文がありますが、列の型/NOT NULL、既存DEFAULT/生成属性、既存のIDENTITY列や依存先等の制限を対象版で確認する変更作業です。既存IDENTITYの属性変更とAS IDENTITYを伴う設定を混同しません。MAX(id)+1を読んだだけでは並行処理やcache/増分を扱えず、安全な移行手順にはなりません。停止/整合性/検証/復旧を計画し、列や表の削除を一律に要求しないでください。

Q: 採番列に NULL を入れたい
A: IDENTITYはNOT NULLです。INSERTで列を省略する、DEFAULTを指定する、明示的にNULLを渡す、という操作は同じではありません。NULLを渡せば必ず自動採番されると扱わず、ドライバーとSQLの指定を確認します。

変更せずに現在のIDENTITY定義を調べる

次はschema名、表名の順で?へ値をバインドする読取SQLです。通常識別子と引用識別子の正確な名前を区別します。COLIDENTATTRIBUTESとは表/schema/列の3キーで結合し、IDENTITY=Yの列を確認します。?はアプリ向けの値パラメーターで、表名/列名の代わりではありません。

SELECT c.TABSCHEMA, c.TABNAME, c.COLNAME, c.GENERATED,
       a."START", a."INCREMENT", a.MINVALUE, a.MAXVALUE,
       a."CYCLE", a."CACHE", a."ORDER"
FROM SYSCAT.COLUMNS c
LEFT JOIN SYSCAT.COLIDENTATTRIBUTES a
  ON a.TABSCHEMA = c.TABSCHEMA
 AND a.TABNAME = c.TABNAME
 AND a.COLNAME = c.COLNAME
WHERE c.TABSCHEMA = ?
  AND c.TABNAME = ?
  AND c.IDENTITY = 'Y'
ORDER BY c.TABSCHEMA, c.TABNAME, c.COLNO;

GENERATEDのAはALWAYS、DはBY DEFAULTです。STARTは定義上の開始値、CACHE/ORDERは割当と生成順の設定で、直前にINSERTしたIDや実データの最大値ではありません。0件はまず接続先・名前・権限を照合し、idという列名だけでIDENTITYと判断しません。定義確認のためにNEXT VALUEを呼ばないでください。

通常利用・移行・障害対応の確認順

  1. 新規設計は値の範囲・増分・一意性/参照・欠番の許容を決め、PRIMARY KEY/UNIQUE等も確認する。ALWAYS/BY DEFAULTを厳格/高速といった単純な優劣で選ばない。
  2. アプリは同じ接続でINSERTと生成キーの受取りを行い、IDが返ってもtransactionの確定を別に確認する。外部へ渡す時点と、失敗/再送時の重複防止を決める。
  3. 明示値の取込やRESTARTは、既存値・参照先・採番方向/範囲と並行処理を停止/調整する方針、検証先・退避/復旧・アプリ影響を決めてから行う。
  4. LOADは入力列の対応・IDENTITY/生成式列の指定・権限・可用性・整合性/バックアップ等を対象版の手順で確認する。通常INSERTの代わりに安易に採用しない。

詳細はIDENTITYと独立シーケンスの違い、定義確認はschemaの列一覧、エラーはDb2エラー一覧へ。Db2親ページの子ページから選択してください。

公式:LUW INSERTの生成列 / ALTER TABLE / 生成属性の制限 / IDENTITYの定義 / LOADの修飾子 / ID取得の条件。

対象範囲と検証

主にDb2 LUWを対象とし、2026年10月に公式資料と照合しました。元のコード/見出し/リンク/画像と過去版を保持し、旧例の誤記や省略はその直前で区別しています。他DB比較表は概要で、別製品の全機能/構文互換性を保証するものではありません。追加の読取SQLの条件/結合/順序をメモリ内の合成データで検査しましたが、Db2実機の構文/権限/採番/計画/ロック・全構成での変更成功を検証したものではありません。

子ページ

子ページはありません

同階層のページ
  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文を生成する方法

最近更新/作成されたページ