◀ 8.

MySQL/MariaDBのAUTO_INCREMENT追加・確認|既存IDと属性の保持

▶

追加前に、既存ID・属性・利用側を照合する

保存済みIDと採番カウンタと接続の取得値は異なり、既存IDを安易に変えない図

既存列へAUTO_INCREMENTを付けるには、対象列と索引/制約・既存値・INSERTする側を先に確認します。主キー追加や既存IDの変更を自動的に続ける手順ではありません。テーブル関連の親ページから子ページを選択し、採番の仕様とIDの取得、MODIFYでの定義変更、外部キーも別に確認できます。

2026-10-26の検査はMySQL8.4.13 / MariaDB11.8.9-ubu2404の新規InnoDB検体です。本番の列/索引/ID/設定は変更していません。小さい検体で成功しても、実アプリの全書込み処理、lock時間、replication/trigger、外部参照の互換まで保証した意味ではありません。

1. 読取りで条件を確認する

SELECT VERSION(), DATABASE(), @@SESSION.sql_mode,
       @@SESSION.auto_increment_increment, @@SESSION.auto_increment_offset,
       @@GLOBAL.innodb_autoinc_lock_mode;

型/符号・NULL・既定値・COMMENT、索引の列順/一意性、既存のAUTO_INCREMENT、FKと参照する外部システムを照合します。InnoDBでは採番列を先頭にする索引が必要ですが、非UNIQUE索引だけでも定義できるため、一意性は別に確認します。FLOAT/DOUBLEの旧対応を現行MySQLへ適用せず、MySQL8.4では非対応です。

2. 同じ属性と既存値を保持できるか検体で確認する

次は新しく作った空のcwiki_w27データベース用です。既存の同名表へ実行せず、実データも転載しません。既存PRIMARY KEY(id)とID10/20、コメント付きの列を準備します。

-- Separate disposable fixture. Do not replace an existing table.
CREATE TABLE cwiki_w27.existing (
    id INT UNSIGNED NOT NULL COMMENT 'preserved id',
    label VARCHAR(40) NOT NULL,
    PRIMARY KEY (id)
) ENGINE=InnoDB;
INSERT INTO cwiki_w27.existing (id,label) VALUES (10,'keep A'),(20,'keep B');
SHOW CREATE TABLE cwiki_w27.existing;
SELECT COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, COLUMN_DEFAULT, EXTRA, COLUMN_COMMENT
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA='cwiki_w27' AND TABLE_NAME='existing'
ORDER BY ORDINAL_POSITION;
SELECT INDEX_NAME, NON_UNIQUE, SEQ_IN_INDEX, COLUMN_NAME
FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA='cwiki_w27' AND TABLE_NAME='existing'
ORDER BY INDEX_NAME, SEQ_IN_INDEX;
SELECT CONSTRAINT_NAME, CONSTRAINT_TYPE
FROM information_schema.TABLE_CONSTRAINTS
WHERE TABLE_SCHEMA='cwiki_w27' AND TABLE_NAME='existing'
ORDER BY CONSTRAINT_NAME;
SELECT id,label FROM cwiki_w27.existing ORDER BY id;
SELECT id,label FROM cwiki_w27.existing WHERE id=0 ORDER BY id;

0やNULL/重複は、存在確認だけで勝手に消す/書き換える対象ではありません。既存0を含む別検体では、通常modeでAUTO_INCREMENTを付けると0の行のIDが1に変わりました。行数や名前が残っていても同じIDを保持したことにはならず、参照元も含む移行設計が必要です。本番でSQL modeを変えれば解決と扱いません。

次はこの検体の型/符号/NULL/COMMENTを明記した変更です。実表の定義をこの列へ合わせる例ではありません。DEFAULTや他の属性にも対象型とAUTO_INCREMENTの制約があるため、元定義の全項目がそのまま併用できるとも決めつけません。

-- Exact definition of the new fixture only, not a template for a production column.
ALTER TABLE cwiki_w27.existing
MODIFY id INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'preserved id';

前の定義・索引/制約・SELECTを再実行して比較します。検体では10/20のIDとlabel、unsigned/NOT NULL/COMMENT、PRIMARYを保持し、AUTO_INCREMENT属性が追加されました。新しいINSERTでidを省略すると21でした。SELECTした予測番号を予約済みIDとして外部システムへ先に渡しません。

3. 外す操作も利用側の仕様変更になる

検体だけで次を実行して、同じ定義とSELECTを比較しました。既存行と主キー/COMMENTは残り、属性だけがなくなりました。しかし、その後idを省略したINSERTはstrict modeで1364となりました。行が残ることと既存アプリが動くことは別なので、全書込み処理や接続条件を確認せず本番へ適用しません。

-- Separate operation on the disposable fixture; check every writer before removal.
ALTER TABLE cwiki_w27.existing
MODIFY id INT UNSIGNED NOT NULL COMMENT 'preserved id';

4. 確認用の番号は、次のINSERTの確約ではない

information_schemaやSHOW CREATE TABLEのカウンタ表示は観測時点の情報です。他接続のINSERT/取消/明示値、増分やoffsetで変わり、読むだけで番号を予約できません。MySQLのinformation_schema_stats_expiryは統計キャッシュの鮮度を制御しますが、0でも「自分の次のID」を確保する設定ではありません。今回のMariaDBにはその変数がなく1193となりました。製品を確認せず旧SETをそのまま実行しません。

既存のSHOW CREATE TABLEの\Gはmysql/mariadbクライアントの表示指定です。driverへ送るSQLの末尾として転用せず、出力には内部定義も含まれるため全文を公開しません。実行したINSERTのIDは同じ接続のdriver/APIと成功結果から取得し、詳細は採番の仕様を参照してください。

5. 新しいID列や移行値は、再採番と分ける

既存表へ新しい採番列を追加した検体ではlabelと行数、採番の一意性を保持しましたが、業務上の順番とIDの対応は保証していません。FIRSTは列位置の指定で、行の採番順の指定ではありません。順番を整えるために既存IDをUPDATEせず、必要なら別の並び順列を設計します。

現在のカウンタを低く指定する操作でも既存IDを振り直しません。移行で元IDを維持する場合は型/範囲・制約/参照・重複・同時書込み・復旧手順を照合します。MAX(id)+1というSQL式をALTER TABLEの値へ直接書く旧案内は1064で拒否されました。値を読んで埋め込むだけの競合対策や、欠番を埋めるためのTRUNCATE/全行DELETEへ置き換えません。

この記事の要点
  • 既存カラムに付ける: ALTER TABLE t MODIFY id INT UNSIGNED NOT NULL AUTO_INCREMENT;
  • 条件は「整数型」「インデックス(主キーなど)が張られている」「1 テーブルに 1 列だけ」。条件/製品/版と操作によってエラー番号も異なるため、1075だけで一原因に断定しない
  • MODIFY はカラム定義をまるごと置き換えるので、NOT NULL・UNSIGNED・COMMENT など元の定義も書き直す
  • 次の番号を変えるには ALTER TABLE t AUTO_INCREMENT = 1000;
  • 確認は DESC の Extra 列、SHOW CREATE TABLE、information_schema の 3 通り
  • MySQL 8.0 の information_schema.tables の AUTO_INCREMENT 値はキャッシュされていて古いことがある

AUTO_INCREMENT とは

AUTO_INCREMENT は、INSERT 時に値を省略(または NULL を指定)すると、MySQL が自動で連番を振ってくれるカラム属性です。主に主キーの ID に使います。テーブル作成時に付け忘れた場合や、既存テーブルに後から ID 列を追加したい場合に、ALTER TABLE で追加します。

既存カラムに AUTO_INCREMENT を追加する

カラム定義を MODIFY で変更し、AUTO_INCREMENT を付けます。

旧例の注意:構文の旧例です。実表の型/符号/NULL/COMMENT/既存値/制約を照合し、INTへ一律変更しません。

ALTER TABLE table_name MODIFY column_name INT NOT NULL AUTO_INCREMENT;

INT の部分は、そのカラムの実際のデータ型(BIGINT UNSIGNED など)に合わせて変更してください。旧来の書き方の int(10) の (10) は表示幅で、MySQL 8.0.17 以降は非推奨のため省略して構いません。

追加できる条件

条件満たさない場合
整数型(TINYINT〜BIGINT)であること製品/版を確認。MySQL8.4ではFLOAT/DOUBLEのAUTO_INCREMENTは非対応で1063となる
そのカラムにインデックスがあること(主キー、UNIQUE、または複合インデックスの先頭列)ERROR 1075: Incorrect table definition; there can be only one auto column and it must be defined as a key
テーブル内で AUTO_INCREMENT は 1 列だけ同じく ERROR 1075
既存の値に重複が無いこと(主キー・UNIQUE の場合)ERROR 1062: Duplicate entry

InnoDBでは先頭列となる索引が必要ですが、PRIMARY/UNIQUE必須ではありません。非UNIQUEなら明示値の重複を防ぎません。主キー追加は既存値/依存と保持要件から別に判断し、常に同時追加しません。

旧例の注意:MODIFYと主キー追加の別例です。既存主キー/依存/重複がある場合までそのまま通す操作ではありません。

ALTER TABLE table_name
  MODIFY id INT UNSIGNED NOT NULL AUTO_INCREMENT,
  ADD PRIMARY KEY (id);

ID 列そのものを新しく追加する場合

新しい採番列を追加すると既存行にも値が付きますが、開始値/増分/製品と処理条件を確認し、必ず1から希望の順番で付くと保証しません。

旧例の注意:新列の追加例です。FIRSTは列位置だけで行の採番順を保証せず、既存列/主キー/参照先も先に調べます。

ALTER TABLE table_name
  ADD id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST;

FIRSTは列位置を指定するもので、業務上の行順やID対応を指定しません。順番のために既存IDをUPDATEせず、参照や別の並び順列を含む設計を先に決めます。

次に振られる番号を変更する

旧例の注意:カウンタの変更例で、既存IDを再採番するものではありません。本番の値をこの例へ合わせません。

ALTER TABLE table_name AUTO_INCREMENT = 1000;

低い値を指定しても既存行は再採番されず、次の値は既存値/カウンタ/増分/offsetと製品条件を照合します。欠番を埋めるためにテストデータや本番行を消す手順ではありません。

AUTO_INCREMENT が貼られているテーブルと値の確認

スキーマを限定して採番カウンタの観測値を調べます。権限による可視範囲とキャッシュを確認し、次のINSERTのIDを予約した意味ではありません。

旧例の注意:読取例です。schema名を限定し、HTML文字参照の引用符をそのままSQLへ送らず、観測値を次IDの予約と扱いません。

SELECT table_name, auto_increment
FROM information_schema.tables
WHERE table_schema = 'スキーマ名'
  AND auto_increment IS NOT NULL;

MySQL 8.0 の注意点: information_schema.tables の統計値はキャッシュされており、既定(information_schema_stats_expiry = 86400 秒)では最大 1 日古い値が表示されることがあります。MySQLの対象版でキャッシュの影響を確認する方法ですが、読取負荷も考慮します。MariaDBへそのまま転用せず、変更した検体session値は元へ戻しました。最新表示でも採番の予約にはなりません。

旧例の注意:MySQL用のsession設定です。MariaDBへそのまま転用しません。検体以外の既存session/globalを診断のために変更しません。

SET SESSION information_schema_stats_expiry = 0;

どの列が AUTO_INCREMENT か確認

旧例の注意:日本語は対象名の記号です。取得できた列のExtraを確認し、一覧から次のIDを確保したと扱いません。

DESC テーブル名;

Extra 列に auto_increment と表示されている列が対象です。テーブル定義全体と次の値は SHOW CREATE TABLE で確認できます(AUTO_INCREMENTオプションは観測時点の状態で、自分の次のINSERTへの確約ではありません)。

旧例の注意:SHOW CREATEの\Gはクライアント表示指定でdriver SQLではありません。続くmetadata照会もschemaを限定し、元のHTML引用符/出力全文を転載しません。

SHOW CREATE TABLE テーブル名\G

-- スキーマ全体から AUTO_INCREMENT 列を探す
SELECT table_name, column_name, column_type
FROM information_schema.columns
WHERE table_schema = 'スキーマ名'
  AND extra LIKE '%auto_increment%';

よくある落とし穴

  • MODIFY で元の属性が消える: MODIFY はカラム定義を丸ごと置き換えます。UNSIGNED、NOT NULL、COMMENT、文字コードなどを書き忘れると、それらが外れます。実行前に SHOW CREATE TABLE で元の定義をコピーしておきましょう
  • 値が 0 の行がある: AUTO_INCREMENT に変更すると、既存の 0 は新しい連番に置き換えられ、重複エラー(ALTER TABLE causes auto_increment resequencing...)になることがあります。0の行を読取で確認し、参照先/元ID保持と移行・復旧を設計します。自動で0を修正/削除したり、本番SQL modeを変更したりしません
  • 大きなテーブルではロックに注意: AUTO_INCREMENT の追加はテーブルの再構築を伴うことがあり、件数が多いと時間がかかり書き込みが止まります。本番ではメンテナンス時間に実行するか、事前に検証環境で所要時間を測ります
  • 番号は欠番が出る: ロールバックや INSERT の失敗、INSERT ... ON DUPLICATE KEY UPDATE などで番号は飛びます。連番に業務上の意味を持たせないようにします
  • 再起動後の挙動の違い: MySQL5.7以前と8.0以降のカウンタ永続化を区別します。MariaDBは10.2.4以降で永続化。再起動で1に戻る/失敗や取消の値が必ず再利用される意味ではありません

AUTO_INCREMENT を外すには

他の属性/依存を照合してAUTO_INCREMENTを省いた定義へ変更する操作です。今回の検体は行/PRIMARY/COMMENTを保持しましたが、id省略INSERTが1364となりました。全書込み処理の互換を確認せず外しません。

旧例の注意:属性を外す旧例です。既存の型/符号/NULL/COMMENT/依存と全書込み処理を確認し、省略INSERTの失敗も検証します。

ALTER TABLE table_name MODIFY id INT UNSIGNED NOT NULL;

関連

元の書式付き変更・確認SQL

元v5の黒SQL表3個を保持します。誤って主キー必須とした旧要約は復元せず、現行の条件説明を訂正します。int(10)は型名の例で、元注記のintoは誤記です。実製品/定義/既存ID/参照先を照合せず変更せず、一覧を次のIDの予約と扱いません。

元例の注意:日本語の対象名は置換位置です。変更例は実表へ適用せず、読取例もschema/接続先とキャッシュ・可視範囲を確認します。

ALTER TABLE table_name MODIFY column_name int(10) NOT NULL AUTO_INCREMENT;

元例の注意:日本語の対象名は置換位置です。変更例は実表へ適用せず、読取例もschema/接続先とキャッシュ・可視範囲を確認します。

SELECT table_name, auto_increment FROM information_schema.tables WHERE table_schema = 'スキーマ名' and auto_increment is not null;

元例の注意:日本語の対象名は置換位置です。変更例は実表へ適用せず、読取例もschema/接続先とキャッシュ・可視範囲を確認します。

DESC テーブル名;

確認範囲と一次資料

新規の小規模検体で掲載SQLと限定した失敗/保持条件を確認しています。本番の全負荷/同時実行/全engine/replication/再起動復旧/他製品・driverの実行保証ではありません。元のコードも記録として保持し、実行を推奨しない例には直前で注意を示します。

子ページ

子ページはありません

同階層のページ
  1. テーブル作成
  2. カラムの定義変更
  3. カラム名の変更
  4. カラム追加 / 削除
  5. インデックスの作成
  6. インデックスの削除
  7. AUTO_INCREMENTの仕様について
  8. AUTO_INCREMENTの追加と確認方法
  9. 外部キーの追加/削除と制約名の確認方法