结论:该错误是MySQL拒绝将NULL插入NOT NULL字段,真正原因常为隐式转换、驱动行为或SQL模式(如STRICT_TRANS_TABLES)导致值变为NULL后触发约束;需查字段定义、历史数据、SQL mode及应用层传值逻辑。
直接说结论:这个错误不是“你没传值”,而是MySQL明确拒绝把NULL塞进一个定义为NOT NULL的字段——但真正卡住你的,往往是隐式转换、驱动行为或SQL模式在背后捣鬼。
错误提示里那个字段名,先去确认它是不是真被设成了NOT NULL:
DESCRIBE table_name; 或 SHOW COLUMNS FROM table_name LIKE 'col_name';,看Null列是否显示NO
NO,再查历史数据:SELECT COUNT(*) FROM table_name WHERE col_name IS NULL; —— 如果有结果,说明表里已有NULL,但你又想加NOT NULL约束,这一步就会失败DEFAULT,又NOT NULL,那没传值就等于传了NULL,直接撞墙STRICT_TRANS_TABLES 是最常背锅的配置。它会让MySQL在类型转换失败(比如往INT插'abc')后不静默转成0,而是把值变成NULL,再触发NOT NULL报错。
SELECT @@sql_mode;,如果返回里含 STRICT_TRANS_TABLES,基本就是它SET sql_mode = '';,再重试插入;成功了就坐实问题my.cnf(Linux)或my.ini(Windows),在[mysqld]段写 sql-mode="NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION",然后重启MySQLexplicit_defaults_for_timestamp —— MySQL 5.6+ 默认ON,会导致无默认值的TIMESTAMP列被当成NOT NULL,加一行 explicit_defaults_for_timestamp=OFF 更稳代码里看似没传值,其实可能悄悄塞了个NULL或空字符串'':
PreparedStatement.setString(1, "") 往INT列插,某些驱动会转成NULL再撞NOT NULL;应改用setInt()等类型匹配方法bindValue(':name', $_POST['name']) —— 如果$_POST['name']未提交或为空,实际传的是NULL;得加判断:!empty($_POST['name']) ? $_POST['name'] : null,并确保数据库字段允许NULL或提供默认值@param语法在较老版本可能解析异常,优先换用?占位符;或连接串加oldsyntax=true
''当NULL,MySQL不等价——如果你的代码是跨库写的,传""到Oracle会直接触发ORA-01400
这两类字段出错时,表现一样,原因完全不同:
NULL,但前提是建表时没写NOT NULL;查 INFORMATION_SCHEMA.COLUMNS 确认 IS_NULLABLE 是YES还是NO;如果是NO但业务需要留空,就得 ALTER TABLE tbl ALTER COLUMN fk_col INT NULL;
AUTO_INCREMENT)列如果报Column 'id' cannot be null,大概率是INSERT语句里显式写了id = NULL,或者用了INSERT INTO t(id) VALUES (NULL);正确做法是省略该字段,或写DEFAULT
ALTER TABLE t AUTO_INCREMENT = 100),而新插入ID刚好卡在间隙里,某些场景下也会误报这个错——用SHOW CREATE TABLE核对AUTO_INCREMENT值最麻烦的不是报错本身,而是错误掩盖了真实问题:关掉strict mode能过,但可能让脏数据悄悄入库;改代码补默认值,却忘了旧数据里混着''和NULL两种“空”,它们在MySQL里完全不等价。