MySQL 8 min read

MySQLのERROR 1366「Incorrect string value」 ― 絵文字が入らない列をutf8mb4にする

※この記事にはアフィリエイト広告(プロモーション)が含まれます。

絵文字を含む文字列を入れると、次のエラーになることがあります。

ERROR 1366 (HY000): Incorrect string value: '\xF0\x9F\x8D\xA3' for column 's' at row 1

\xF0\x9F\x8D\xA3 は 🍣 の UTF-8 のバイト列です。\xF0 で始まる4バイトの文字を、3バイトまでしか扱えない utf8mb3 の列に入れようとしています。

この記事のログは MySQL 8.4.11(Ubuntu 26.04 の標準パッケージ)で採りました。8.4 のサーバー既定の文字コードは utf8mb4 なので、新しく作った表では起きません。古いバージョンから移した表や、CHARSET=utf8 を指定して作った表で起きます。

まず見る(結論)

  1. 列の文字コードを見る。utf8mb3 なら ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4
  2. 列が utf8mb4 なのに出るなら、クライアントの文字コード(SET NAMES、接続文字列)が utf8mb3 になっていないかを見る
SELECT table_name, column_name, character_set_name, collation_name
  FROM information_schema.columns WHERE table_schema = 'csdb';
+------------+-------------+--------------------+--------------------+
| TABLE_NAME | COLUMN_NAME | CHARACTER_SET_NAME | COLLATION_NAME     |
+------------+-------------+--------------------+--------------------+
| t3b        | s           | utf8mb3            | utf8mb3_general_ci |
| t4         | s           | utf8mb4            | utf8mb4_0900_ai_ci |
+------------+-------------+--------------------+--------------------+

utf8 と書くと utf8mb3 になる

8.4 でも、CHARACTER SET utf8 は utf8mb3 の別名です。表を作ると警告が出ます。

CREATE TABLE t3b (s varchar(20)) CHARACTER SET utf8;
SHOW WARNINGS;
| Warning | 3719 | 'utf8' is currently an alias for the character set UTF8MB3, but will be an alias for UTF8MB4 in a future release. Please consider using UTF8MB4 in order to be unambiguous. |

この列に日本語は入りましたが、絵文字は 1366 になりました。

非 strict モードでは ? に置き換わる

sql_mode に STRICT_TRANS_TABLES が無いと、エラーにならず、警告が出たうえで値が入ります。

SET sql_mode = '';
INSERT INTO t3b VALUES ('寿司🍣');
SHOW WARNINGS;
| Warning | 1366 | Incorrect string value: '\xF0\x9F\x8D\xA3' for column 's' at row 1 |

SELECT s, hex(s) FROM t3b;
| 寿司?     | E5AFBFE58FB83F |

絵文字が ?(0x3F)に置き換わって保存されています。後で列を utf8mb4 に変えても、この ? は元に戻りません。8.4 の既定の sql_mode には STRICT_TRANS_TABLES が入っているので、アプリや設定ファイルで外していないかを確かめます。

クライアントの文字コードが原因のとき

列が utf8mb4 でも、接続の文字コードが utf8mb3 だと同じ 1366 になりました。

SET NAMES utf8mb3;
INSERT INTO t4 VALUES ('🍣');
ERROR 1366 (HY000): Incorrect string value: '\xF0\x9F\x8D\xA3' for column 's' at row 1

アプリの接続設定(JDBC の characterEncoding、PHP の charset など)で utf8 を指定している場合は、utf8mb4 に変えます。

接続の文字コードが latin1 の場合は、エラーにも警告にもならずに文字化けして入りました。

SET NAMES latin1;
INSERT INTO t4 VALUES ('日本');
SET NAMES utf8mb4;
SELECT s, hex(s) FROM t4;
| 日本        | C3A6E28094C2A5C3A6C593C2AC |

日本(E697A5E69CAC)の各バイトを latin1 の1文字とみなして変換したため、別の文字列として保存されています。--default-character-set=latin1 で接続し直すと 日本 と表示されるので、表示だけでは気づけません。hex() で確かめます。

utf8mb4 に変換する

ALTER TABLE t3b CONVERT TO CHARACTER SET utf8mb4;

表の既定値と、文字列の列すべてが utf8mb4(照合順序は utf8mb4_0900_ai_ci)になり、絵文字が入るようになりました。表を作り直すので、大きい表では時間がかかります。

ALTER DATABASE csdb CHARACTER SET utf8mb4;
SHOW CREATE TABLE t5\G
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3

ALTER DATABASE が効くのは、この後に作る表だけです。既存の表は1つずつ CONVERT TO します。

索引の長さの上限

utf8mb4 は1文字を4バイトで見積もるので、索引の長さの上限(3,072 バイト)に早く届きます。

CREATE TABLE t6 (s varchar(1000) CHARACTER SET utf8mb4, KEY(s));
ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes

varchar(768)(768 × 4 = 3,072 バイト)なら作れました。

MySQL をもっと深く知るための本

MySQL徹底入門 第5版 MySQL 8.4 LTS対応

翔泳社・2025年6月・MySQL 8.4 LTS 対応

MySQL 8.4 に対応した入門書。日本MySQLユーザ会のメンバーが執筆している。

Amazonで見る

MySQL運用・管理[実践]入門 〜安全かつ高速にデータを扱う内部構造・動作原理を学ぶ

技術評論社・2024年5月

内部構造と動作原理から、運用・管理の考え方を学ぶ。

Amazonで見る

Amazonのアソシエイトとして、FIRE SE は適格販売により収入を得ています。