SQLite外键默认不生效,Navicat同步时仅保留语法但不自动执行PRAGMA foreign_keys=ON;必须手动启用且每连接生效,否则外键约束被忽略。
SQLite 不支持外键约束的自动启用
navicat 同步 sqlite 时,即使源库(如 mysql)定义了 foreign key,目标 sqlite 表结构里也会“出现”外键语法,但默认不生效——因为 sqlite 编译时可能未启用 foreign_keys pragma,且 navicat 从不自动执行 pragma foreign_keys = on。
实操建议:
- 同步前,在目标 SQLite 连接中手动执行
PRAGMA foreign_keys = ON;,并确认返回0或空结果(表示成功) - 检查是否真启用:
PRAGMA foreign_keys;应返回1;若为0,说明约束始终被忽略 - Navicat 的「结构同步」生成的 DDL 中虽含
FOREIGN KEY (...) REFERENCES ...,但这只是语法保留,不触发运行时校验 - SQLite 的外键是“可选特性”,依赖编译选项和会话级 pragma,Navicat 无法跨会话持久化该设置
Navicat 不解析或同步 CHECK / UNIQUE 约束细节
SQLite 支持 CHECK 和复合 UNIQUE 约束,但 Navicat 在读取源库 DDL 或生成目标 SQL 时,常丢失表达式内容或简化为无效语法。例如:源库 MySQL 的 CHECK (status IN ('active', 'inactive')) 可能变成 SQLite 中无意义的 CHECK (1),或直接被跳过。
实操建议:
- 同步后立刻查目标表定义:
PRAGMA table_info('table_name');和PRAGMA index_list('table_name');,确认约束是否以索引形式存在(SQLite 把 UNIQUE 当索引实现) - 人工验证
CHECK:运行SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'table_name';,看原始 DDL 是否含完整 CHECK 表达式 - Navicat 旧版本(≤16.0)对含函数、子查询的 CHECK 表达式完全静默丢弃,升级到 v17+ 可缓解但不保证 100% 兼容
主键自增与 INTEGER PRIMARY KEY 的语义差异
MySQL 的 INT AUTO_INCREMENT 和 SQLite 的 INTEGER PRIMARY KEY 表面相似,但 Navicat 同步时可能错误映射为普通 INT PRIMARY KEY,导致失去 rowid 别名和自增行为——插入 NULL 不触发新 ID,后续 INSERT 报错 NOT NULL constraint failed。
实操建议:
- 同步后检查主键声明:
PRAGMA table_info('table_name');中主键字段的pk列应为1,且类型必须是INTEGER(全大写),小写int或带长度如INTEGER(11)均无效 - 避免在 Navicat 同步设置中勾选 “Ignore AUTO_INCREMENT value”,它会强制抹掉 SQLite 所需的
INTEGER PRIMARY KEY语义 - 若已同步出错,手动
ALTER TABLE不可行(SQLite 不支持改列类型),只能导出数据 → 重建表(显式用INTEGER PRIMARY KEY)→ 导入
Navicat 对 WAL 模式和连接参数无感知
SQLite 启用 WAL 模式(PRAGMA journal_mode = WAL;)后,多个连接可并发读写,但 Navicat 默认以传统 DELETE 模式打开文件。若目标库已处于 WAL 模式,Navicat 可能读取到 stale schema,导致约束“看似存在却不起作用”,尤其在其他进程刚建完外键后。
实操建议:
- 同步前统一模式:在目标库执行
PRAGMA journal_mode = DELETE;,再让 Navicat 连接同步(完成后可切回 WAL) - Navicat 连接字符串不支持传参如
?journal_mode=WAL,所有 pragma 必须手动执行 - WAL 模式下,
sqlite_master表变更可能延迟可见,Navicat 同步脚本若依赖即时元数据(如外键依赖判断),容易误判缺失约束











