MySQL报“Column cannot be null”根本原因是字段定义为NOT NULL但插入时未提供有效值,包括显式写NULL、漏写字段、空字符串类型转换为NULL或外键列强制非空。

不是你传了 NULL,而是你根本没传值,或者传了空字符串 '',却被数据库当成了 NULL 或触发了 NOT NULL 约束。
INSERT 时写 NULL 却报 “Column cannot be null”
这说明字段定义里写了 NOT NULL,但你在 SQL 里显式写了 NULL(比如 INSERT INTO t(c) VALUES (NULL))。MySQL 会直接拒绝——NOT NULL 就是禁止任何 NULL 写入,不管你是有意还是无意。
- 查字段定义:
DESC table_name或SHOW COLUMNS FROM table_name LIKE 'col_name',看Null列是否为YES - 如果显示
NO,那这个字段真不能存NULL;想改,得执行ALTER TABLE table_name MODIFY col_name TYPE NULL - 注意:有些 ORM(如 Django、MyBatis)默认不传字段时会生成
NULL值,若对应列是NOT NULL且无默认值,就会失败
没写字段,也没给值,却报错说 “cannot be null”
这是最常见的情况:SQL 中漏写了某个 NOT NULL 字段,又没设默认值,MySQL 就没法填,只能报错。
- 例如:
INSERT INTO users(name) VALUES ('Alice'),但表定义是id INT NOT NULL AUTO_INCREMENT, name VARCHAR(50) NOT NULL, email VARCHAR(100) NOT NULL——email没给值,立刻失败 - 解决方法只有三个:补上值、给字段加
DEFAULT(如DEFAULT '')、或把字段改成允许NULL - 别依赖客户端“自动补空字符串”,MySQL 不会帮你把缺失字段转成
'',它只认你写的 SQL
传了空字符串 '',结果被当成 NULL 插不进去
空字符串 '' 和 NULL 在 MySQL 里完全不是一回事。但某些场景下,'' 会因类型转换失败而变成 NULL,再撞上 NOT NULL 约束。
- 典型例子:往
INT字段插'',MySQL 在严格模式(STRICT_TRANS_TABLES)下会转换失败,最终值变为NULL,然后被NOT NULL拦住,报错信息仍是 “Column cannot be null” - 验证方式:
SELECT @@sql_mode;,如果含STRICT_TRANS_TABLES,就极可能是它 - 临时绕过(仅调试):
SET sql_mode = '';;长期方案是业务层校验并拒绝向数字列传空字符串,或改用setInt()等类型明确的方法
外键字段插 NULL 失败
外键列本身可以为 NULL,但前提是建表时明确允许——如果定义成 customer_id BIGINT NOT NULL,那插 NULL 必然失败,和外键关系无关。
- 查结构:
SELECT COLUMN_NAME, IS_NULLABLE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'orders' AND COLUMN_NAME = 'customer_id'; - 如果
IS_NULLABLE = 'NO',说明它被强制非空,必须填有效外键值,或执行ALTER TABLE orders MODIFY customer_id BIGINT NULL; - 特别注意:ORM 自动生成的迁移脚本有时会忽略历史需求,默认加
NOT NULL,导致新业务无法表示“未关联”状态
真正容易被忽略的是:错误信息里写的 “cannot be null”,未必对应你代码里写的那个值——它可能来自驱动隐式转换、字段默认行为、甚至 JDBC 的 setString() 往数字列塞空串。排查时别只盯 SQL 文本,要结合 DESC、@@sql_mode 和实际执行的字段值类型一起看。


















