先理解这个报错的含义:error: 在字段 'xxx' 中空值违反了非空约束。通俗解释就是,目标字段设置了 NOT NULL,但Navicat在导入数据时却试图插入一个 NULL 值。
许多人的第一反应是去Excel中查找是否包含 null 字样的单元格,但实际情况往往更复杂。这个 NULL 值可能并非源文件中明确写着“空”,而更可能是完全空白的单元格、肉眼不可见的空白字符,或者你的SQL文件中直接写了一个 NULL 字面量——数据库忠实地执行,随即触发报错。

关键是要区分三类“空”的行为差异:
- Excel中真正空白的单元格 → Navicat默认会将其映射为
NULL数据。 - Excel中看似空字符串
''的内容(例如输入了两个双引号但中间无任何字符)→ 在某些编码环境下或文件带有BOM头时,Navicat可能错误地将其解析为NULL。 - SQL文件中直接写明的
VALUES (1, NULL, 'abc')→ 这是一个明确的NULL字面量,MySQL会严格校验该字段是否允许空值。
建议不要急于修改Navicat的导入设置。最直接的方式是用纯文本编辑器打开源文件(尤其是CSV和SQL文件),全局搜索 NULL 单词和连续逗号 ,,,以此确认数据源中的空值究竟是如何产生的。
字段映射页中的“空值处理”选项必须手动调整
Navicat 12及以上版本的导入向导中,有一个关键的“字段映射”页面。每个字段的右侧都有一个名为“空值处理”的下拉框,其默认选项为 插入NULL。对于设置了 NOT NULL 的字段来说,这一默认行为正是导致报错的直接原因。
正确的做法如下:
- 逐个点开目标字段,将该下拉框的值从
插入NULL改为插入空字符串。此选项主要适用于VARCHAR字段,且业务允许存储空字符串的场景。 - 或者改为
使用默认值。前提是表结构中该字段已预先定义了DEFAULT ''或DEFAULT 0,否则系统无法确定填充什么。 - 特别要注意:如果字段是
INT NOT NULL且没有设置默认值,选择插入空字符串同样会报错,系统会提示Incorrect integer value: ''。针对这种情况,要么预先补全数据,要么直接修改表结构。
这里有一个容易忽略的陷阱:那个名为“空字符串转为NULL”的全局勾选选项,仅对本身允许接收 NULL 的字段有效。如果勾选上,反而会导致那些本应走默认值的字段跳过默认逻辑,直接变为 NULL。
使用 N 显式表示NULL更可靠,不要写NULL或留空
如果某列确实需要在SQL中明确插入 NULL,最稳妥的方法是在CSV或TXT源文件中统一写一个 N 字符,然后在Navicat的“高级设置”中,启用“NULL值表示为”选项,并填入 N。这样Navicat就会识别:看到 N 时,向数据库发送一个 NULL 字面量。
其他任何写法都不够可靠:
- 写入字母
NULL→ Navicat会将其作为普通字符串插入,最终数据库中存储的将是字符串'NULL'。 - 直接留空(例如
张三,,上海)→ Navicat会认为列数不足,自动补上NULL。但遇到NOT NULL字段时,直接拒绝接收。 - 写入
''空字符串 → 在INT等非字符串类型上会引发类型转换错误。
这个机制本身与字段是否允许 NULL 无关,它只是告诉Navicat“此处需要发送一个 NULL 字面量”。至于数据库是否接受,则取决于表结构的定义。
真正省事的办法:建表时就添加DEFAULT,而非依赖导入设置
从长远来看,最不容易出错的做法是在建表时,对业务上允许“没有值”的字段主动添加默认值。这能从根源上规避导入过程中所有与空值相关的麻烦。
name VARCHAR(50) DEFAULT ''status TINYINT DEFAULT 0updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
有了这些默认值作为保底,即使导入时字段缺失、数据留空甚至映射失败,MySQL也会自动填充默认值,整个导入流程得以顺利执行,不会中途中断。反之,每次都依赖Navicat向导手动修改设置,不仅操作繁琐易遗漏,而且不同环境的配置难以统一,一旦更换机器就容易失效。
棘手之处在于,你需要先判断这个 NULL 究竟属于哪种情形:是脏数据(需要补充值)、设计缺陷(当初不应设置 NOT NULL),还是工具之间对空值的理解不一致(源文件、Excel与Navicat之间的语义偏差)。这三者混杂在一起,处理起来会越来越复杂,也越来越难以追踪。
