MySQL · 错误码速查
MySQL 错误 1366:看「Incorrect 后面那个词」——integer/decimal 是数据格式问题,string 是字符集问题
ERROR 1366 (HY000): Incorrect integer value: 'abc' for column 'n' at row 1 表示这一行里有个值不能存进该列。Incorrect integer/decimal/datetime value 多半是程序把空串、带千分位或逗号小数的字符串直接塞进数值列;Incorrect string value: '\xF0\x9F…' 几乎都是 4 字节字符(emoji、部分生僻字)写进了 utf8mb3 列。严格模式(默认)下报错拒绝写入;关掉严格模式或用 INSERT IGNORE 时会变成警告,并写入 0 或 '?' 这样的「调整值」。
官方原文
Error number: 1366; Symbol: ER_TRUNCATED_WRONG_VALUE_FOR_FIELD; SQLSTATE: HY000
Message: Incorrect %s value: '%s' for column '%s' at row %ld第一个 %s 是目标类型(integer、decimal、string、datetime 等),第二个是被拒的值(字符串类会以 \x 十六进制显示无法转换的字节),最后是列名和第几行。
出处:MySQL 8.4 Error Reference:Server Error Message Reference 最后核对:
| 错误号 / 符号 | 1366 / ER_TRUNCATED_WRONG_VALUE_FOR_FIELD(服务端错误) | 出处 |
|---|---|---|
| SQLSTATE | HY000 | 出处 |
| 是否报错取决于 | sql_mode 是否含 STRICT_TRANS_TABLES / STRICT_ALL_TABLES(MySQL 8.0 默认含前者);非严格模式下写入调整后的值并产生警告 | 出处 |
| utf8mb3 | 每个字符最多 3 字节,存不下 emoji;官方已标为弃用,建议改用 utf8mb4 | 出处 |
| 相邻错误 | 1265 WARN_DATA_TRUNCATED(01000);1292 ER_TRUNCATED_WRONG_VALUE(22007);1406 ER_DATA_TOO_LONG(22001);1300 ER_INVALID_CHARACTER_STRING | 出处 |
先看 Incorrect 后面的词:integer / decimal 和 string 是两类问题
| 报错里看到的 | 本机复现的写法(MySQL 8.0.46,默认严格模式) | 常见来源 |
|---|---|---|
Incorrect integer value: 'abc' | INSERT INTO t (n) VALUES ('abc'),n 为 INT | 表单字段没校验、CSV 列错位 |
Incorrect integer value: '' | INSERT INTO t (n) VALUES ('') | 前端传空串当「没填」,应传 NULL |
Incorrect decimal value: '12,5' | INSERT INTO t (d) VALUES ('12,5'),d 为 DECIMAL(10,2) | 逗号作小数点或千分位的导出文件 |
Incorrect string value: '\xF0\x9F\x98\x80' | INSERT INTO t (s3) VALUES ('笑😀'),s3 为 utf8mb3 | emoji、部分生僻字(4 字节 UTF-8) |
同样是「不是纯数字」,'12abc' 写 INT 列报的是 1265 Data truncated,不是 1366:MySQL 能截出前缀 12,所以算「截断」;'abc' 一个数字都截不出来,才算「值不正确」。查日志时两个号都要搜。
同一条 SQL,有的库报错有的库不报:sql_mode 和 INSERT IGNORE
官方在 Server SQL Modes 一节说明:严格模式下无效值会被拒绝;不在严格模式时,MySQL 会插入调整后的值并产生警告。本机复现把会话 sql_mode 设成空串后,'abc' 写 INT 列成功,存成 0,只留一条 1366 Warning;emoji 写 utf8mb3 列也成功,存成 笑?(HEX E7AC913F)——emoji 永久变成了问号。
严格模式下用 INSERT IGNORE,效果和关严格模式类似:本机复现 INSERT IGNORE … VALUES ('xyz') 返回 1 row affected、1 warning,写进去的是 0。所以「迁到新库后开始报 1366」往往不是新库有问题,而是老库一直在静默写脏数据。
SELECT @@GLOBAL.sql_mode, @@SESSION.sql_mode;
SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE, CHARACTER_SET_NAME, COLLATION_NAME
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 't';Incorrect string value '\xF0\x9F…':把列和连接都换成 utf8mb4
\xF0 开头的 4 个字节是一个 4 字节 UTF-8 字符。utf8mb3(老写法 utf8)每个字符最多存 3 字节,所以存不下;同一张表里 utf8mb4 的 s4 列写同样的值正常。官方已把 utf8mb3 标为弃用并建议用 utf8mb4。
- 先用上面的 information_schema.COLUMNS 查询找出所有
CHARACTER_SET_NAME = 'utf8mb3'的列,按表评估改造。 - 改列字符集是表结构变更(会重建表),而且 utf8mb4 下 VARCHAR 索引的字节长度上限按 4 字节/字符计算,长 VARCHAR 上的索引可能需要调整;先在测试库演练,确认耗时和索引长度。
- 连接也要是 utf8mb4:客户端或驱动用 utf8mb3 连接时,4 字节字符在传输阶段就会出问题。
怎么找出以前静默写进去的脏数据
如果库曾经运行在非严格模式或大量用 INSERT IGNORE,表里可能已经有被改成 0 或 '?' 的值。注意:用 WHERE n = 'abc' 这类字符串去比数值列不会报错,本机复现它把存成 0 的两行都匹配出来了,同时给出 Warning 1292 Truncated incorrect DOUBLE value: 'abc'——比较时字符串被转成了数字 0。
-- 数值列里异常多的 0
SELECT COUNT(*) AS zero_rows FROM t WHERE n = 0;
-- 字符串列里出现的问号(可能是 4 字节字符被替换)
SELECT id, s3 FROM t WHERE s3 LIKE '%?%' LIMIT 50;这两条只是线索:业务上本来就可能有 0 和问号。要确认是否脏数据,需要对照原始文件或上游系统。
和 1265、1292、1406 怎么分
| 错误 | 官方消息 | 和 1366 的区别 |
|---|---|---|
1265 WARN_DATA_TRUNCATED | Data truncated for column '%s' at row %ld | 能截出一部分(如 '12abc' → 12),1366 是完全不能转换 |
1292 ER_TRUNCATED_WRONG_VALUE | Truncated incorrect %s value: '%s' | 常见于比较或函数里的隐式转换(如 WHERE n='abc'),以及日期时间值不合法 |
1406 ER_DATA_TOO_LONG | Data too long for column '%s' at row %ld | 类型对但长度超了(如 VARCHAR(20) 写 30 个字符) |
UPDATE 也会报 1366:本机复现 UPDATE t SET n = 'abc' … 报 Incorrect integer value: 'abc' for column 'n' at row 2,这里的 row 是语句处理到的第几行,不是主键值。
常见问题
Incorrect integer value: '' for column 是什么原因?
把空字符串写进了整数列。严格模式下空串不能转换成整数,报 1366。程序应在「没填」时传 NULL(列允许为空)或明确的默认值,而不是空串。
Incorrect string value: '\xF0\x9F\x98\x80' 怎么解决?
这是 emoji 等 4 字节字符写进了 utf8mb3 列。把列(以及表默认字符集、连接字符集)改为 utf8mb4;改列会重建表,先在测试库演练并检查索引长度。
为什么老库不报 1366,迁到新库就报了?
多半是老库 sql_mode 不含严格模式,或者应用用了 INSERT IGNORE。非严格模式下无效值会被写成调整值(如 0、'?')并只给警告;新库默认严格模式就直接报错。
能不能把 sql_mode 改成非严格来消除 1366?
能消除报错,但等于允许静默写入 0 或问号等错误数据。更稳的做法是在应用侧校验和转换(空串转 NULL、统一小数点、改 utf8mb4)。
1366 和 1265 Data truncated 有什么区别?
1265 表示值能截出一部分(如 '12abc' 写 INT 截成 12);1366 表示完全不能转换(如 'abc')。严格模式下两者都会拒绝写入。
下一步
价格以对应页面当前标价为准。
出处(最后核对 2026-11-01)
- MySQL 8.4 Error Reference:Server Error Message Reference
- MySQL 8.4 Reference Manual:Server SQL Modes(Strict SQL Mode)
- MySQL 8.4 Reference Manual:The utf8mb3 Character Set
- MySQL 8.4 Reference Manual:INSERT Statement(IGNORE 修饰符)
本页摘录并解读上面列出的官方文档,不是官方页面;官方文档更新后以官方为准。本页内容都来自官方文档,没有我们自己的测试结果。