NOT NULL字段插入空字符串''完全合法,因NOT NULL仅禁止NULL值,而''是长度为0的合法字符串;数值型字段插入''会隐式转为0(严格模式下报错),字符串类型则直接存储''。

NOT NULL 字段插入 '' 是完全合法的
因为 NOT NULL 约束只禁止 NULL,不禁止空字符串 ''。两者在 MySQL 中是截然不同的值:NULL 表示“未知/缺失”,'' 是一个长度为 0 的合法字符串值。
常见错误现象:执行 INSERT INTO t(col) VALUES (''); 成功,但误以为“这违反了 NOT NULL”——其实恰恰相反,它正是 NOT NULL 允许的行为。
-
NOT NULL字段必须有值,而''就是值(非 NULL 值) -
INT NOT NULL插入''会触发隐式转换(如转成0),并可能报 warning;但VARCHAR NOT NULL插入''默认完全合法 - 若想禁止空字符串,需额外加
CHECK (col != '')(MySQL 8.0.16+)或应用层校验,NOT NULL本身做不到
为什么插入 '' 后查出来变成 0?
这是类型不匹配导致的隐式转换,典型发生在数值型字段上。MySQL 试图把空字符串解释为数字时,结果就是 0。
例如:CREATE TABLE t(id INT NOT NULL); INSERT INTO t VALUES (''); 不会报错(除非启用了严格模式),而是静默转成 0 并存入。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
- 触发条件:字段类型为
TINYINT/INT/FLOAT等数值类型,且插入了''或其他非数字字符串 - 是否报错取决于 SQL mode:若启用
STRICT_TRANS_TABLES,该操作会直接失败;否则仅发 warning,值被强制转为0 -
VARCHAR/TEXT类型不会发生这种转换,''就存为''
如何真正阻止空字符串写入?
NOT NULL 无法做到这点,必须叠加其他机制。
- MySQL 8.0.16+:用
CHECK (col IS NOT NULL AND col != ''),但注意 CHECK 约束对已存在数据不生效,只约束新写入 - 低版本 MySQL:靠应用层校验,或在 INSERT/UPDATE 前用触发器拦截
'' - 避免陷阱:别指望
DEFAULT ''+NOT NULL能“兜底空值”——它只是让不传字段时自动填'',而非拒绝'' - ORM 用户特别注意:某些框架(如 Django、MyBatis)默认把空表单字段映射为空字符串而非
NULL,容易绕过你本意的业务校验
NULL 和 '' 在索引与查询中表现完全不同
混淆二者会导致查询逻辑出错,尤其在 WHERE 和 COUNT 场景下。
-
WHERE col IS NOT NULL匹配所有非NULL值,包括''、'0'、' ' -
WHERE col != ''匹配所有非空字符串,但会漏掉NULL(因NULL != ''永远为UNKNOWN) -
COUNT(col)统计非NULL行数,''会被计入;COUNT(*)统计所有行 - B-tree 索引不存储
NULL,但存储''—— 所以WHERE col = ''可走索引,WHERE col IS NULL则不能(除非用 IS NULL 专用优化)
真正难处理的不是语法,而是团队里有人把 '' 当 NULL 用、有人当有效值用——这种语义分歧一旦进入 where 条件或统计口径,排查成本远高于建表时多写一行 CHECK。

















