MySQL:Data too long与Data truncated错误差异及数据完整性疑问
我在表doctor_offline_review中有一个name列,原本定义为varchar(255),但实际存储的最长字符串远不到255字符。考虑到该列存的是真实姓名,我认为最长不会超过50字符,于是执行了以下SQL语句修改列长度:
alter table doctor_offline_review modify name varchar(50);
结果抛出异常,提示部分姓名过长:
ERROR 1406 (22001): Data too long for column 'name' at row 1229425
之后我把目标长度改成80,执行:
alter table doctor_offline_review modify name varchar(80);
这次的异常和之前不一样:
ERROR 1265 (01000): Data truncated for column 'name' at row 5476907
最终我把列长度改成100才成功,但还有两个疑问:
- 为什么SQL语句类似但错误不同?
ERROR 1406 (22001)和ERROR 1265 (01000)有什么区别? Data truncated是不是意味着可能存在数据完整性损失?(这次操作没出现数据受损的情况)
补充信息
- 行1229425的姓名内容为:
匿名患者[�Ϻ� �ɽ�]
通过以下语句查询得到:
select name from doctor_offline_review limit 1229424,1;
行5476907的姓名内容和它相近。
2. MySQL版本:Ver 8.0.36-0ubuntu0.22.04.1 for Linux on x86_64 ((Ubuntu)),操作系统:Ubuntu 22.04.4 LTS
3. 表结构:
mysql> desc doctor_offline_review; +------------------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +------------------+--------------+------+-----+---------+-------+ | review_id | bigint | NO | PRI | NULL | | | agree | int | YES | | NULL | | | attitude | varchar(4) | YES | | NULL | | | content | varchar(40) | YES | | NULL | | | cost | int | YES | | NULL | | | disease | varchar(255) | YES | | NULL | | | doctor_id | bigint | YES | MUL | NULL | | | effect | varchar(4) | YES | | NULL | | | ill_condition | varchar(50) | YES | | NULL | | | name | varchar(100) | YES | | NULL | | | patient_city | varchar(50) | YES | | NULL | | | patient_province | varchar(20) | YES | | NULL | | | real_time | datetime(6) | YES | | NULL | | | reason | varchar(150) | YES | | NULL | | | remedy | varchar(255) | YES | | NULL | | | skill | varchar(255) | YES | | NULL | | | status | int | YES | | NULL | | | tag | varchar(255) | YES | | NULL | | | type_description | varchar(255) | YES | | NULL | | +------------------+--------------+------+-----+---------+-------+ 19 rows in set (0.00 sec)
1. 两个错误码的区别
- ERROR 1406 (22001):属于严格模式下的数据校验错误。当你的MySQL开启了严格模式(
sql_mode包含STRICT_TRANS_TABLES或STRICT_ALL_TABLES),它会提前检测现有数据是否能适配新的列长度,一旦发现数据长度超过目标值,就直接终止修改操作,不会对数据做任何改动,目的是避免潜在的数据丢失。 - ERROR 1265 (01000):属于截断操作异常错误。当目标长度80接近该行数据的实际字节长度时,MySQL尝试执行截断,但遇到了特殊字符(比如你看到的
�这类乱码多字节字符),截断过程中无法正常处理这些字符,导致操作失败并抛出该错误。简单说,1406是"发现数据太长,直接拒绝操作",1265是"尝试截断但处理失败,报错终止"。
2. Data truncated与数据完整性损失
Data truncated字面意思是"数据被截断",正常情况下意味着MySQL会删除超出列长度的部分数据,这必然会造成数据完整性损失。但你这次操作没出现数据受损,是因为这个错误直接终止了修改操作——MySQL在尝试截断时失败,整个ALTER TABLE操作被回滚,所以数据没有被改动。
如果是在非严格模式下,MySQL可能不会报错,仅返回警告,此时过长的数据会被强制截断,就会导致数据完整性损失。你的场景中错误触发,操作未执行,所以数据不受影响。
内容的提问来源于stack exchange,提问作者Xuan Chen

