SQLite不支持AUTO_INCREMENT等引擎专属语法,仅认INTEGER PRIMARY KEY自增;需手动修正建表语句、NULL写法、索引语法、时间格式及类型隐式转换。
导出的 SQL 在 SQLite 里报 near "AUTO_INCREMENT": syntax error
mysql 或 postgresql 导出的 sql 常含 auto_increment、serial、identity 这类引擎专属语法,sqlite 不认。它只认 integer primary key 自增语义,且必须是整型主键字段本身——不能加额外修饰。
实操建议:
- 用
mysqldump --no-create-info --skip-extended-insert导出纯数据(避免建表语句污染),再手动补 SQLite 兼容的CREATE TABLE - PostgreSQL 用户优先用
pg_dump --inserts --column-inserts --no-owner --no-privileges,但要删掉所有GENERATED ALWAYS AS IDENTITY和DEFAULT nextval(...) - 别依赖图形工具“导出为 SQL”按钮,它们默认按源库语法生成,几乎必报错
INSERT 语句里字符串 NULL 被写成 NULL 还是 'NULL'?
这是跨库导入最隐蔽的数据错乱点:源库把空字符串或缺失值存为 NULL(SQL 关键字),而导出脚本误写成字符串 'NULL',结果 SQLite 插入的是 4 字符文本,不是空值。
实操建议:
- 检查导出文件中前几条
INSERT,确认NULL是否裸写(无引号)、是否与字段类型匹配(比如数字列允许NULL,文本列也允许) - 用
sed -i 's/,\s*''NULL''\s*,/, NULL ,/g'批量修正被引号包裹的NULL(注意逗号和空格边界,避免误伤正常字符串) - 如果源数据含单引号字符串(如
O'Reilly),导出时必须转义为两个单引号O''Reilly,SQLite 认这个,不认反斜杠
SQLite 不支持 CREATE INDEX IF NOT EXISTS 以外的条件建索引语法
很多导出工具会把 MySQL 的 CREATE FULLTEXT INDEX、PostgreSQL 的 CREATE INDEX CONCURRENTLY 直接扔进来,SQLite 遇到就停在那行,后续所有 INSERT 都不执行。
实操建议:
- 导出后先用
grep '^CREATE INDEX' your.sql扫一遍,删掉所有带FULLTEXT、CONCURRENTLY、USING btree的行 - 只保留形如
CREATE INDEX IF NOT EXISTS idx_name ON table(col);的语句——SQLite 80% 场景下只需要这个 - 如果原库有函数索引(如
UPPER(name)),SQLite 3.30+ 支持,但得手写,不能靠导出工具生成
时间字段导出成 '2023-10-05 14:22:33.123456',SQLite 加载时报错
SQLite 没有原生 datetime 类型,全靠文本、整数或浮点数模拟。它只接受 ISO8601 格式(YYYY-MM-DD HH:MM:SS)或 Unix 时间戳。微秒级精度、时区后缀(+0800)、毫秒字段名(created_at_ms)都会让 sqlite3 命令行工具静默跳过该行。
实操建议:
- 用
date -d '2023-10-05 14:22:33.123456' '+%Y-%m-%d %H:%M:%S'截断微秒(Linux/macOS),Windows 用户可用 PowerShell 的[datetime]::ParseExact() - 时区信息必须剥离,SQLite 不解析
+08:00,也不推荐存为 UTC 时间戳整数——除非你确定所有查询都用datetime(col, 'unixepoch') - 别信导出工具标称的 “SQLite mode”,实际测试发现
mysqldump --compatible=sqlite仍会输出TIMESTAMP DEFAULT CURRENT_TIMESTAMP,这语法 SQLite 完全不认
真正麻烦的不是语法转换,而是导出时没意识到 SQLite 把一切当字符串或整数处理——日期、布尔、JSON 都得按它的隐式规则对齐,否则数据看着进了,查出来全是空或 0。










