mysql如何修改字段类型_mysql alter table修改字段类型

14次阅读

ALTER TABLE MODIFY COLUMN 可能丢失数据,取决于新旧类型兼容性:缩容、降精度或跨大类转换易导致截断、报错或边界值;扩容安全;改名须用 CHANGE COLUMN;含 TEXT/BLOB 需先设 ROW_FORMAT=DYNAMIC;大表修改建议用 pt-online-schema-change。

mysql 如何修改字段类型_mysql alter table 修改字段类型

ALTER TABLE MODIFY COLUMN 会丢失数据吗

直接用 MODIFY COLUMN 改字段类型,是否丢数据,取决于新旧类型的兼容性。比如从 VARCHAR(255) 缩成 VARCHAR(10),超长值会被截断;从 INT 改成 TINYINT,超出 -128~127 范围的值会变成边界值或报错(取决于 SQL mode)。 不是所有修改都安全,尤其涉及长度缩减、精度降低或类型跨大类(如字符串→数字)时

  • 改宽不丢数据(VARCHAR(10) → VARCHAR(200)
  • 改窄大概率丢数据(TEXT → VARCHAR(100),超长部分被截)
  • DECIMAL(10,2) → DECIMAL(5,2):整数位不够时,插入会报错或四舍五入(看版本和 sql_mode)
  • 必须先查当前数据分布:SELECT MIN(col), MAX(col), COUNT(*) FROM tbl WHERE col IS NOT NULL;

用 CHANGE COLUMN 还是 MODIFY COLUMN

CHANGE COLUMNMODIFY COLUMN 都能改类型,但语义不同:CHANGE 必须写两次字段名(旧名 新名),哪怕不改名也得重复;MODIFY 只写一次,更简洁。两者在纯类型变更时行为一致,但 CHANGE 允许同时改名 + 改类型,MODIFY 不允许改名。

  • 只改类型、不改名 → 优先用 MODIFY COLUMN(少写、不易错)
  • 要改名又改类型 → 必须用 CHANGE COLUMN old_name new_name new_type
  • 误写 CHANGE col col INT 是合法的,但多打一个 col 容易手滑漏掉,引发语法错误

修改 TEXT/BLOB 字段类型要加 ROW_FORMAT=DYNAMIC

MySQL 5.7+ 中,如果表用的是 COMPACTREDUNDANT 行格式,直接对含 TEXTBLOB 的字段执行 MODIFY,可能报错:ERROR 1118 (42000): Row size too large。这是因为老行格式对单行总长有限制,而 TEXT 实际存储在行外,但元信息仍占空间。

  • 先确认当前行格式:SHOW TABLE STATUS LIKE 'tbl_name';Row_format
  • 若为 Compact,建议先改行格式:ALTER TABLE tbl_name ROW_FORMAT=DYNAMIC;
  • 再执行字段修改,否则可能卡住或失败
  • DYNAMIC 是 InnoDB 默认(8.0+),但老表迁移后未必自动更新

在线修改字段类型真的“在线”吗

MySQL 5.6+ 支持部分 ALTER TABLE 操作的“在线”能力(即不锁表),但改字段类型是否真正不锁,要看具体操作和版本。例如 MODIFY COLUMNVARCHAR 长度,在 5.7+ 中如果是扩大且字符集不变,通常可 ALGORITHM=INPLACE;但缩容、改类型(如 VARCHAR → TEXT)、或涉及全文索引时,大概率触发 COPY 算法,锁表 + 全量复制。

  • ALGORITHM=INPLACE, LOCK=NONE 强制指定,但 MySQL 会校验是否支持,不支持则报错
  • 生产环境务必先在从库或测试库验证耗时与锁表现:SHOW PROCESSLIST; 观察状态
  • 大表(千万级 +)改类型前,用 pt-online-schema-change 更稳妥

实际执行前,别跳过 SELECT …… LIMIT 5 看真实数据样例,还有那个容易被忽略的 sql_mode 设置——它会影响截断、零日期等行为的报错 / 警告策略。

text=ZqhQzanResources