MySQL ERROR 1406:INSERT/UPDATE時にカラムのデータが長すぎる問題の修正方法

beginner🗄️ MySQL2026-03-18| MySQL 5.7 / 8.0+, MariaDB 10.x — Linux, Windows, macOS

Error Message

ERROR 1406 (22001): Data too long for column 'username' at row 1
#mysql#varchar#データ切り捨て#スキーマ#カラム長

エラーの概要

INSERT または UPDATE を実行すると、MySQL が次のエラーをスローします:

ERROR 1406 (22001): Data too long for column 'username' at row 1

これは、保存しようとしている値がカラムのデータ型で許可されている長さを超えていることを意味します。VARCHAR(50) カラムは50文字を超える値を例外なく拒否します。本番環境での INSERT で深夜2時にこのエラーが発生した場合、ここで素早く解決する方法を説明します。

原因

通常、以下の3つのいずれかが原因です:

  • カラムの定義が実際のデータに対して狭すぎる(例:VARCHAR(50) と定義しているが、ユーザーが200文字の文字列を貼り付ける)
  • 上流で変更があった — フォームフィールドの文字数制限が削除された、または API がより長い文字列を返すようになった
  • STRICT_TRANS_TABLES モードが有効になっている(MySQL 5.7.5 以降のデフォルト)。これにより、値がサイズを超えた場合に黙って切り捨てる代わりにエラーが発生する

ステップ1:カラムの現在の長さを確認する

推測せず、カラムの実際の定義を確認しましょう:

DESCRIBE users;
-- または
SHOW COLUMNS FROM users LIKE 'username';

文字セットを含む詳細情報を確認するには:

SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'your_database'
  AND TABLE_NAME = 'users'
  AND COLUMN_NAME = 'username';

次に、問題の値の正確な長さを確認します:

SELECT LENGTH('the_value_that_failed');

両方の数値を把握することで、必要な余裕が正確にわかります。

ステップ2:カラムの長さを増やす(推奨の修正方法)

最もクリーンな解決策:実際のデータに合わせてカラムを拡張します。

ALTER TABLE users MODIFY COLUMN username VARCHAR(255) NOT NULL;

VARCHAR(255) はほとんどのユーザー名や名前フィールドに十分対応できます。自己紹介、説明文、または長さが不定のフィールドには、VARCHAR を避けて TEXT を使用しましょう:

ALTER TABLE users MODIFY COLUMN bio TEXT;

大きなテーブルの場合、ALTER TABLE はその間テーブルをロックする可能性があります。1000万行以上のテーブルでは、数分のダウンタイムが発生します。代わりに pt-online-schema-change または MySQL 8.0 のインスタント DDL を使用しましょう:

-- MySQL 8.0: テーブルの再構築なしで即座にカラムを変更
ALTER TABLE users
  MODIFY COLUMN username VARCHAR(255) NOT NULL,
  ALGORITHM=INSTANT;

INSTANT はほとんどの場合 VARCHAR の拡張に対応しています。ただし、型の変更や文字セットの変換には使用できません。

ステップ3:データを切り捨てる(データ損失を許容できる場合)

今すぐスキーマを変更できない場合は、挿入時に値を切り捨てることができます:

INSERT INTO users (username) VALUES (LEFT('some_very_long_username_here', 50));

または、データベースに到達する前にアプリケーションコードで切り詰めることもできます。いずれにしても、これは一時的な対処策です。落ち着いたらスキーマを修正しましょう。

ステップ4:ストリクトモードを無効にする(一時的な回避策)

バッチインポートが失敗していて、今は暗黙的な切り捨てが許容できる場合は、セッションのみストリクトモードを無効にできます:

SET SESSION sql_mode = REPLACE(@@SESSION.sql_mode, 'STRICT_TRANS_TABLES', '');

-- ここで INSERT を実行

-- 完了後に再有効化
SET SESSION sql_mode = @@GLOBAL.sql_mode;

**本番環境でグローバルに無効にしないでください。**ストリクトモードは、不正なデータがテーブルを破損する前に検出するためのものです。これは、制御されたマイグレーションやデータインポート時の一時的な使用にとどめてください。

修正の確認

カラムを拡張した後、新しい定義を再確認しましょう:

SHOW COLUMNS FROM users LIKE 'username';
-- VARCHAR(255) または設定した値が表示されるはずです

失敗していたクエリを再実行します:

INSERT INTO users (username) VALUES ('the_value_that_was_failing');
-- Query OK, 1 row affected

データが正しく保存されたことを確認します:

SELECT username, LENGTH(username) FROM users ORDER BY id DESC LIMIT 1;

アプリケーションコードでの対応

データベースエラーで入力が検証されていないことを発見するのは大変です。DB 呼び出しの前に長さのチェックを追加しましょう:

# Python の例 — 挿入前にバリデーション
if len(username) > 255:
    raise ValueError(f"ユーザー名が長すぎます: {len(username)} 文字")

DB レベルでもルールを適用したい場合は、MySQL 8.0.16+ が CHECK 制約をサポートしています:

ALTER TABLE users
  ADD CONSTRAINT chk_username_length CHECK (CHAR_LENGTH(username) <= 255);

これにより、ORM、生のクエリ、または直接の psql 接続など、データがデータベースに入る方法に関わらず明確なエラーが表示されます。

文字セットの問題に注意

絵文字や CJK 文字(漢字・ひらがななど)を保存する場合は注意が必要です。文字セットは各文字が実際に使用するスペースに影響します。utf8mb4 では、1つの絵文字が4バイトを占める場合があります。VARCHAR(255) カラムは255文字を保存できますが、最大1020バイトを消費する可能性があります — これはインデックスキーの制限に影響します。

カラムの文字セットを確認します:

SELECT COLUMN_NAME, CHARACTER_SET_NAME, COLLATION_NAME
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'your_database'
  AND TABLE_NAME = 'users'
  AND COLUMN_NAME = 'username';

utf8mb4 を使用していてインデックスプレフィックスの制限に達している場合(InnoDB のデフォルトキー制限は MySQL 5.7 では767バイト、MySQL 8.0 では innodb_large_prefix で3072バイト)、プレフィックスインデックスを使用するか、カラム定義を短くしてください。

クイックリファレンス

  • 素早い修正(スキーマ変更): ALTER TABLE t MODIFY COLUMN col VARCHAR(255);
  • 現在のサイズを確認: SHOW COLUMNS FROM table LIKE 'column';
  • 一時的な回避策: SET SESSION sql_mode = REPLACE(@@sql_mode, 'STRICT_TRANS_TABLES', '');
  • 非常に長いテキストの場合: VARCHAR から TEXT に切り替え
  • 本番環境の大きなテーブル: ALGORITHM=INSTANT または pt-online-schema-change を使用

Related Error Notes