不会静默截断;缩小长度会报错(ERROR 1406),扩大长度不截断旧数据,但需注意字符集变更可能导致行大小超限或隐式截断。

ALTER TABLE MODIFY 会静默截断数据吗?
不会自动截断,但如果你用 MODIFY 或 CHANGE 缩小字段长度(比如从 VARCHAR(200) 改成 VARCHAR(50)),MySQL 会直接报错(ERROR 1406: Data too long for column),除非 SQL mode 关掉了严格模式。而“扩大长度”本身是安全操作——只是要注意:它不修复已存在的超长数据。
扩大 VARCHAR 长度后,旧数据会被截断吗?
不会。只要新长度 ≥ 原始数据最大字节数,所有现有值都完整保留。但这里有个关键陷阱:VARCHAR(N) 的 N 是字符数,不是字节数;如果用了 utf8mb4,一个 emoji 占 4 字节,但只算 1 个字符。所以:
-
ALTER TABLE t MODIFY c VARCHAR(100) CHARSET utf8mb4能存下 100 个中文或 emoji,但最多占用 400 字节 - 如果原来字段是
VARCHAR(100) CHARSET latin1,改完 utf8mb4 后,同样 100 字符可能超出行大小限制(InnoDB 单行上限约 65535 字节) - 某些老版本 MySQL(如 5.6)在修改 charset + length 时,会先尝试转换再校验,可能触发隐式截断(尤其开启
STRICT_TRANS_TABLES以外的 mode)
ALTER TABLE CHANGE 和 MODIFY 有什么实际区别?
对长度调整来说,行为一致;区别只在是否重命名字段:
- 用
CHANGE必须写两次字段名:CHANGE old_col old_col VARCHAR(255)(即使不改名也要重复写) - 用
MODIFY更简洁:MODIFY col VARCHAR(255),且不涉及重命名逻辑 - 两者在 DDL 执行时都会重建表(除非用
ALGORITHM=INSTANT,仅限 8.0.12+ 且满足条件:仅改长度、不改类型、不改 charset)
为什么 ALTER 后 SELECT 还看到旧长度?
不是没生效,而是你查错了地方。常见原因:
- 没刷新表结构缓存:执行
SHOW COLUMNS FROM table_name或DESCRIBE table_name,别只看建表语句(SHOW CREATE TABLE可能因输出截断显示不全) - 客户端缓存了元数据(比如某些 ORM 或 GUI 工具),重启连接或执行
FLUSH TABLES - 误操作了其他同名表(比如测试库和生产库连混了)
- 执行成功但被回滚了(比如在事务里执行 DDL —— MySQL 不支持 DDL 在事务中回滚,但有些客户端会自动加 BEGIN/COMMIT 包裹)
最稳的验证方式:直接插入一条超原长度的测试值,再 SELECT LENGTH(col), col 看是否存进去了。










