56.

MySQLの1366 Incorrect string value|Laravelの文字コード・絵文字エラー

この記事の要点
  • Laravel の SQLSTATE[22007] Invalid datetime format: 1366 Incorrect string value(絵文字エラー)
  • 確認: 4バイトUTF-8の文字を接続・保存先カラムの文字コードで扱えるか。テーブルのデフォルトだけで判断しない
  • 対処: 実際の接続・対象カラムを診断。utf8mb4への変換は既存データと運用への影響を検証してから
  • .envだけでなく、有効な接続設定と設定キャッシュを確認。特定の照合順序へ一律変更しない

 

エラー内容

SQLSTATE[22007]: Invalid datetime format: 1366 Incorrect string value: ~

 

発生条件/原因/対処法

アプリの4バイトUTF-8文字をMySQL接続と保存先カラムの両方で扱えるか確認する構成図

この例ではエラー本文の1366 Incorrect string valueと対象カラムに注目します。SQLSTATEのInvalid datetime formatという表記だけで、日時の書式の問題と決めつけないでください。4バイト文字の非対応は典型例ですが、不正な入力バイト列などもあるため、エラー番号・対象カラム・入力の文字コードを合わせて確認します。

変更する前の確認SQL

失敗したアプリと同じDB・接続で実行してください。example_messagesは実際のテーブル名へ読み替えます。以下はSELECTとSHOWだけで、データやスキーマを変更しません。CLIでの確認だけではアプリ接続の文字コードが同じとは限りません。

SELECT VERSION() AS mysql_version, DATABASE() AS current_database,
       @@session.character_set_client AS client_charset,
       @@session.character_set_connection AS connection_charset,
       @@session.character_set_results AS results_charset,
       @@session.collation_connection AS connection_collation;

SHOW CREATE TABLE example_messages;

SELECT COLUMN_NAME, COLUMN_TYPE, CHARACTER_SET_NAME, COLLATION_NAME
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'example_messages'
ORDER BY ORDINAL_POSITION;

SELECT TABLE_NAME, TABLE_COLLATION
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'example_messages';

見る場所は、接続のclient / connectionと、対象カラムのCHARACTER_SET_NAMEです。整数カラムなどは文字コードがNULLになります。TABLE_COLLATIONはテーブルの既定値であり、全カラムの実値を表すものではありません。

前提:Laravel, MySQL

絵文字を入力した際に発生するエラー。

対応策は複数あるので以下に挙げるもの全てを確認すること。

 

1. テーブルの文字コード

対象の文字列カラムがutf8mb4を使っているか確認します。utf8mb4は文字集合、utf8mb4_general_ciなどは比較・並べ替えのルールである照合順序です。MySQL 8.0のutf8はutf8mb3の別名で、4バイトの文字を扱えません。

※文字コード変換はバックアップと検証環境での確認が必要です。カラム型・NULL/DEFAULT・インデックス・一意制約・照合順序・ロック時間への影響を確認し、正式な変更手順で実施してください。

 

2. Laravelのconfig/database.phpと実接続

以下の旧設定例のcharset / collationは値を直接書いています。この場合、.envのDB_CHARSET / DB_COLLATIONだけを変えてもその設定値は変わりません。対象版・実際のconfig/database.phpを読んで判断してください。旧コード全体を現行アプリへ置き換える例ではありません。

        'mysql' => [
            'driver' => 'mysql',
            'url' => env('DATABASE_URL'),
            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '3306'),
            'database' => env('DB_DATABASE', 'forge'),
            'username' => env('DB_USERNAME', 'forge'),
            'password' => env('DB_PASSWORD', ''),
            'unix_socket' => env('DB_SOCKET', ''),

            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_general_ci',

            'prefix' => '',
            'prefix_indexes' => true,
            'strict' => true,
            'engine' => null,
            'options' => extension_loaded('pdo_mysql') ? array_filter([
                PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
            ]) : [],

接続の文字コードで入力を解釈でき、保存先カラムの文字コードへ変換できるか確認します。接続とカラムの照合順序が完全一致しなければ必ずこのエラーになる、という意味ではありません。

以下のconfig:clearは、旧記事の設定キャッシュを削除するコマンドとして残します。本番でこれだけを実行して作業を終えないでください。正式なデプロイ手順で設定キャッシュを再生成し、常駐プロセスがあればその更新手順にも従います。

php artisan config:clear

 

Laravelから有効な設定を確認する

学習用環境のtinkerで確認する例です。mysql以外の接続を使うモデルや、明示的な接続名がある場合はその接続へ合わせます。passwordや接続URL全体は出力しません。

config('database.default');
config('database.connections.mysql.charset');
config('database.connections.mysql.collation');
DB::connection('mysql')->select('SELECT @@session.character_set_client AS client_charset, @@session.character_set_connection AS connection_charset, @@session.collation_connection AS connection_collation');

LaravelのMySqlConnectorは設定のcharset / collationでSET NAMESを行います。別のDBクライアントでSET NAMESを実行しても、既に動いているアプリの接続設定は変更されません。Laravel 13で環境変数を参照する項目の例は次のとおりです。既存接続の該当2項目へ組み込む断片であり、接続設定全体ではありません。

'charset' => env('DB_CHARSET', 'utf8mb4'),
'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),

診断結果ごとの判断

状況次に確認すること
接続utf8mb3 / 保存先utf8mb4アプリの接続設定・キャッシュ・再接続。カラム変換だけでは接続を直せない
接続utf8mb4 / 保存先utf8mb3対象カラムの変換計画。DB・テーブルのデフォルト変更だけで既存カラムが変わるとは限らない
両方utf8mb4実際の接続先、入力バイト列、別カラムやトリガー経由の保存先などを確認

絵文字を除去したりstrictモードを無効化したりしてエラーを隠すと、データの欠落・置換を見逃すおそれがあります。特定の照合順序を万能な解決策にせず、比較・一意性の要件も確認します。テーブル全体のCONVERTは既存カラムや型に影響するため、ここでは無条件に実行するDDLを掲載しません。

修正後に確認すること

隔離した検証環境で同じ文字を保存・再取得し、元の値と一致するか確認してください。今回はMySQL 8.0.46で、接続とカラムそれぞれのutf8mb3が1366を起こすこと、utf8mb4カラムへの保存でHEX=F09F9880、CHAR_LENGTH=1、LENGTH=4となることと上の診断SQLを確認しました。本番DBの文字コード・スキーマ・業務データは変更していません。

公式資料: MySQL utf8mb4、接続の文字コード、テーブルの既定値、カラムの変換、Laravelの設定キャッシュ(2026年10月確認)。

子ページ

子ページはありません

同階層のページ
  1. 1071 Specified key was too long; max key length is 767 bytes
  2. ERROR 1063 (42000): Incorrect column specifier for column '~'
  3. mysqld: Can't change dir to '...\MySQL\MySQL Server X.X\data\' (OS errno 2 - No such file or directory)
  4. Install/Remove of the Service Denied!
  5. Datetime 型が NULL に見える
  6. Warning: World-writable config file '/etc/mysql/my.cnf' is ignored
  7. ERROR 1698 (28000): Access denied for user 'root'@'localhost'
  8. Exception: Wrong MySQL configuration
  9. [Warning] TIMESTAMP with implicit DEFAULT value is deprecated.
  10. ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.
  11. ERROR 1819 (HY000): Your password does not satisfy the current policy requirements
  12. Incorrect column specifier for column 'カラム名'
  13. BLOB/TEXT column 'description' used in key specification without a key length
  14. ERROR: /bin/sh: mysql_config: コマンドが見つかりません
  15. Host '...' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'
  16. CSVエクスポート時に「ERROR 1045 (28000): Access denied for user 'username'@'localhost'」エラーが表示される
  17. Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT
  18. SQLSTATE[22007]: Invalid datetime format: 1366 Incorrect string value: ~