必须先用UPDATE填充NULL值,再用ALTER TABLE MODIFY COLUMN添加NOT NULL约束,最后可选设置DEFAULT;否则因存在NULL值直接报错。

ALTER TABLE MODIFY COLUMN 报错 “Invalid default value”
MySQL 在给已有数据的字段加 NOT NULL 约束时,如果该字段存在 NULL 值,会直接报错:ERROR 1138: Invalid use of NULL value(5.7+)或更常见的 ERROR 1138: Invalid default value for 'xxx'(尤其开启严格模式后)。这不是语法写错了,而是 MySQL 拒绝让含空值的列“突然变硬”。
- 必须先清理或填充现有
NULL值,再加约束;不能跳过这步 - 如果字段类型是
VARCHAR、TEXT等,用UPDATE填默认值比改类型更安全 - 执行前务必确认表大小——大表
UPDATE可能锁表、耗时长,建议在低峰期操作
正确加 NOT NULL 的三步顺序
顺序错了就失败。不是先 MODIFY 再填数据,而是反过来:清空 → 改约束 →(可选)加默认值。
UPDATE table_name SET column_name = 'default_value' WHERE column_name IS NULL;-
ALTER TABLE table_name MODIFY COLUMN column_name VARCHAR(255) NOT NULL;(注意保留原类型和长度) - 如果想后续插入不填也自动补值,再加:
ALTER TABLE table_name ALTER COLUMN column_name SET DEFAULT 'default_value';
漏掉第一步,第二步必报错;改类型时没写全定义(比如漏了 CHARACTER SET utf8mb4),可能意外改变字符集或排序规则。
INT 类型字段加 NOT NULL 的特殊坑
INT 字段常被误以为“默认是 0”,其实不是。MySQL 不会自动把 NULL 转成 0,除非你显式指定 DEFAULT 0 并且关掉严格模式——但这种行为不可靠,也不推荐。
- 执行
UPDATE时别写SET column_name = 0就完事,要确认业务上0是否真代表“无值”或“未设置” - 如果字段本意是“必须有正整数”,那填
0反而引入脏数据 - 某些 ORM 或迁移工具会自动生成
DEFAULT 0,但 MySQL 8.0+ 默认启用严格模式后,INSERT不带该字段仍会报错,得配合DEFAULT显式声明
为什么不能用 CHANGE COLUMN 替代 MODIFY COLUMN
两者都能改约束,但 CHANGE COLUMN 要求重写整个字段定义(包括名字),稍不留神就改错名或丢属性。而 MODIFY COLUMN 只改类型和约束,语义更清晰、出错率更低。
- 写
CHANGE COLUMN old_name old_name VARCHAR(255) NOT NULL看似一样,但多一次字段名比对,容易手抖写成old_name new_name -
MODIFY COLUMN不检查字段名变更,所以更稳;只要类型定义写对,就不会误 rename - 线上 DDL 工具(如 pt-online-schema-change)内部也优先用
MODIFY,因为它触发的元数据变更更轻量
真正麻烦的从来不是语法,而是字段里那些没人记得清、不敢删、又不能留的 NULL 值——它们藏在历史数据里,等你一执行 NOT NULL 就跳出来拦路。










