タイトル: 自動番号付け (autoincrement) する方法
SEOタイトル: DB2 で自動番号付け (autoincrement) する方法完全ガイド
| この記事の要点 |
|
1. DB2 の IDENTITY 列
DB2 では列に IDENTITY 属性を付けて自動採番します。SQL 標準の GENERATED ... AS IDENTITY 構文に準拠しています。
-- 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 | アプリ指定不可。OVERRIDING SYSTEM VALUE で例外的に上書き | マスタテーブル(厳格) |
GENERATED BY DEFAULT AS IDENTITY | アプリ指定可(指定しなければ自動) | 移行 / インポート時 |
-- 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. オプションを使いこなす
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 + ORDER。
4. SEQUENCE オブジェクト
テーブル列に紐づかない、独立した採番器を作りたい場合は SEQUENCE:
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)
-- 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 を取得
-- 直前の 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 | 採番構文 | 備考 |
|---|---|---|
| DB2 | GENERATED ALWAYS AS IDENTITY | SQL 標準 |
| MySQL | AUTO_INCREMENT | 独自構文、SEQUENCE 無し |
| PostgreSQL | SERIAL / GENERATED ... AS IDENTITY | 後者が SQL 標準で推奨 |
| Oracle | GENERATED AS IDENTITY (12c+) / SEQUENCE | 12c 未満は SEQUENCE + TRIGGER |
| SQL Server | IDENTITY(1,1) | 独自構文 |
8. INSERT 時の挙動 / 注意点
-- 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: ALTER TABLE T ALTER COLUMN id SET GENERATED BY DEFAULT AS IDENTITY (START WITH N)。N は MAX(id) + 1。
Q: 採番列に NULL を入れたい
A: 不可。NOT NULL 必須。NULL の概念が無いなら別カラム設計を見直す。