not null字段能插入空字符串''是因为null与''语义不同,''是合法非null值;而插入null报错与否取决于sql_mode是否启用strict模式——严格模式下直接报错,宽松模式下可能转为默认值。

MySQL字段设了NOT NULL却还能插入空值,通常不是约束失效,而是SQL模式宽松、客户端行为或ORM层悄悄传了NULL——得逐层排查。
为什么NOT NULL字段能插入NULL或空字符串?
根本原因在于MySQL的sql_mode配置。默认开启严格模式(如STRICT_TRANS_TABLES)时,插入NULL到NOT NULL字段会直接报错;但若模式中去掉它(比如只剩NO_ENGINE_SUBSTITUTION),MySQL就会静默转成默认值(如''、0)或截断,看起来像“没拦住”。
- 检查当前模式:
SELECT @@sql_mode;,确认是否含STRICT_TRANS_TABLES或STRICT_ALL_TABLES - 临时生效(会话级):
SET sql_mode = 'STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION'; - 永久生效需改
my.ini或my.cnf,重启mysqld - 注意:MySQL 8.0.16+ 默认启用严格模式,老版本(如5.7)常被手动关掉
MyBatis插入时把NOT NULL字段写成NULL怎么办?
实体类字段为null,MyBatis用insert()生成全字段INSERT语句,把NULL明文塞进SQL——哪怕字段有DEFAULT,也会因显式赋NULL而触发NOT NULL校验失败。
- 改用
insertSelective():它只拼接非null字段,让数据库走默认值逻辑 - 实体类字段加
@TableField(fill = FieldFill.INSERT)(MyBatis-Plus)自动填充 - XML里手写
<if test="xxx != null"></if>条件包裹字段 - 别依赖
jdbcType=NULL,它不阻止NULL写入,只影响类型映射
已有数据含NULL,想加NOT NULL约束却报错
执行ALTER TABLE MODIFY COLUMN xxx VARCHAR(50) NOT NULL失败,错误通常是ERROR 1138: Invalid use of NULL value——MySQL拒绝给含NULL的列“硬加”约束。
- 必须先清理:
UPDATE table_name SET xxx = 'default' WHERE xxx IS NULL; - 再加约束:
ALTER TABLE table_name MODIFY COLUMN xxx VARCHAR(50) NOT NULL; - 最后可选设默认值:
ALTER TABLE table_name ALTER COLUMN xxx SET DEFAULT 'default'; - 大表慎操作:
UPDATE可能锁表,建议在低峰期执行并加索引加速WHERE xxx IS NULL
plugin字段为空导致ERROR 1045登录失败
这不是普通业务字段问题,而是mysql.user系统表里plugin列为NULL或空字符串,MySQL启动时直接忽略该用户记录,哪怕密码正确也进不去。
- 启动时加
--skip-grant-tables绕过权限检查 - 查问题账号:
SELECT host, user, plugin FROM mysql.user WHERE user = 'root'; - 修复必须用
ALTER USER(别UPDATE mysql.user):ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'pwd'; - 立刻执行
FLUSH PRIVILEGES;,否则不生效 - 确认插件存在:
SHOW PLUGINS;里要有mysql_native_password,否则要检查plugin_dir路径
真正麻烦的从来不是加个NOT NULL关键字,而是它背后牵扯的SQL模式、ORM行为、存量数据和系统表状态——每层漏检一点,问题就藏得更深。











