不能靠“关外键”一招鲜,必须分三步走——导出前禁用检查、导入时保留约束、导入后重新启用;Navicat默认不自动处理SET FOREIGN_KEY_CHECKS,需手动勾选转储选项或在SQL首尾显式添加该语句,并关闭“遇到错误继续执行”以避免静默失败。
直接结论:不能靠“关外键”一招鲜,必须分三步走——导出前禁用检查、导入时保留约束、导入后重新启用。navicat 默认不自动处理 set foreign_key_checks,手动漏掉这一步,100% 导入失败。
导出结构时为什么必须显式加 SET FOREIGN_KEY_CHECKS=0?
Navicat 的「转储 SQL 文件」默认只生成 CREATE TABLE 语句,不带任何会话级设置。而外键依赖顺序(比如先建 orders 表再建 customers 表)会导致导入中途报错 ERROR 1215: Cannot add foreign key constraint。这不是表本身有问题,是 MySQL 在建第二个表时发现第一个还没建好,且外键校验开着,直接拒绝。
- 必须勾选「转储 SQL 文件」里的 “添加 SET FOREIGN_KEY_CHECKS=0” 选项(在高级设置里)
- 若用命令行或脚本导出,需手动在 SQL 文件开头加
SET FOREIGN_KEY_CHECKS=0;,结尾加SET FOREIGN_KEY_CHECKS=1; - 不加这句,哪怕你把所有表按依赖顺序手动排序,Navicat 导入时仍可能因并行或缓存打乱执行顺序而失败
导入 SQL 文件时,“忽略错误继续执行”是最大陷阱
Navicat 默认启用「遇到错误继续执行」,看起来很友好,实则埋雷:ERROR 1050 (42S01): Table 'xxx' already exists 或 ERROR 1215 被静默吞掉,最后你以为成功了,其实关键表根本没建出来,外键全丢。
- 导入前务必取消勾选「遇到错误继续执行」(在运行 SQL 文件对话框右下角)
- 导入窗口底部状态栏显示「执行完成」≠ 全部成功,要看是否有红色 ERROR 行;有就停,别点重试
- 若已有同名表,先手动
DROP TABLE或改用CREATE TABLE IF NOT EXISTS,但注意后者不兼容外键重建逻辑
跨实例迁移时,FOREIGN_KEY_CHECKS 不会自动同步
源库可能长期开着 SET FOREIGN_KEY_CHECKS=0(比如为批量导入临时关闭),但 Navicat 数据传输或结构同步功能不会把这个会话设置带到目标库。目标库默认是 1,所以一建带外键的表就崩。
- 数据传输任务里,进「高级选项」→ 勾选「忽略外键检查」,这个选项本质就是在目标端执行
SET FOREIGN_KEY_CHECKS=0再导入 - 结构同步任务中,同样要手动勾选「外键约束」同步项,否则它会删掉目标库已有的外键(不是忽略,是主动 DROP)
- 如果目标库是只读账户,
SET FOREIGN_KEY_CHECKS会被拒绝,此时只能让 DBA 开临时权限,或改用 root 账户操作
真正容易被忽略的是字符集和存储引擎的一致性——哪怕 FOREIGN_KEY_CHECKS 关了,若主表字段是 utf8mb4_bin 而从表是 utf8mb4_general_ci,或者一个是 InnoDB 一个是 MyISAM,外键照样建不起来,且报错极隐蔽(ERROR 1005 后只跟一堆系统路径,不提字符集问题)。











