ALTER TABLE MODIFY 添加 NOT NULL 失败的根本原因是字段存在 NULL 值,必须先用 UPDATE 填充(如字符串设为''、数字设为0),再执行 MODIFY;MODIFY 与 CHANGE 均可加约束但语义不同,且均会锁表。

ALTER TABLE MODIFY 时字段含 NULL 值直接报错
直接执行 ALTER TABLE t MODIFY name VARCHAR(50) NOT NULL 会失败,错误通常是 ERROR 1265 (01000): Data truncated for column 'name' at row X 或 ERROR 1138: Invalid use of NULL value。根本原因不是语法错,而是该列已有 NULL 值,MySQL 拒绝在存在空值的前提下强加 NOT NULL。
必须先清理数据:
- 用
UPDATE填充空值,注意类型匹配:比如字符串列用UPDATE t SET name = '' WHERE name IS NULL,数字列用UPDATE t SET age = 0 WHERE age IS NULL - 确认清理干净:
SELECT COUNT(*) FROM t WHERE name IS NULL返回0才能继续 - 若列有默认值(如
DEFAULT 'unknown'),填充时可复用,但默认值本身不解决已有NULL的问题
MODIFY 和 CHANGE 都能加 NOT NULL,但风险不同
MODIFY 和 CHANGE 都支持添加 NOT NULL,但语义和出错点差异明显:
-
MODIFY只改类型和约束,不改列名,语法简洁:ALTER TABLE t MODIFY name VARCHAR(50) NOT NULL -
CHANGE必须重复写两次列名(旧名、新名),适合重命名同时加约束:ALTER TABLE t CHANGE old_name new_name VARCHAR(50) NOT NULL - 误用
CHANGE:漏写新列名 →ERROR 1064;漏写NOT NULL→ 表面成功,实际没加约束 - 两者都会锁全表(尤其大表),线上操作前务必在从库或低峰期验证
加完 NOT NULL 后应用 INSERT/UPDATE 报错怎么办
约束生效后,所有写入必须显式提供非 NULL 值。常见踩坑点:
-
INSERT INTO t() VALUES()或INSERT INTO t SELECT ...中漏掉该列 → 报错ERROR 1364: Field 'xxx' doesn't have a default value -
UPDATE语句中设为NULL,例如SET status = NULL→ 直接拒绝 - ORM 自动生成 SQL 时可能忽略该列,需检查实体映射或手动指定字段列表
- 补救方式:要么补全
INSERT字段,要么加DEFAULT(如DEFAULT ''),注意DEFAULT和NOT NULL是正交的,可共存
INT 列加 NOT NULL 后出现 0 值?小心隐式转换
对已有 INT 列加 NOT NULL 后,如果原数据含空字符串 '' 或非法字符(如 'abc'),MySQL 5.7+ 严格模式下会报错;但在兼容模式下可能静默转成 0,导致数据失真。
执行前必须检查异常值:
-
SELECT * FROM t WHERE age = ''(字符串型脏数据) -
SELECT * FROM t WHERE age REGEXP '[^0-9-]'(含非数字字符) - 更稳妥的做法是先用
CAST或正则清洗,再加约束
真正麻烦的不是加约束这一步,而是你不知道表里已经混了多少 NULL、''、0 和乱码——它们在加约束前看起来都“没事”,加完就集体暴露。


















