用strings.newreader包装csv字符串后交由csv.newreader流式解析,避免strings.split破坏rfc 4180规范;配合fieldsperrecord=-1处理字段数不一致,再通过预编译stmt.exec批量插入sqlite。

CSV 字符串流怎么转成 SQLite 可插入的行数据
直接用 strings.NewReader 包一层 CSV 字符串,再交给 csv.NewReader 处理即可。关键不是“读”,而是避免把整块字符串全加载进内存切片——尤其是当 CSV 行数多、字段含换行或引号时,csv.Reader 的流式解析能力必须利用起来。
常见错误是先 strings.Split 按 \n 切行,再手动拆字段:这会破坏 RFC 4180 规范里允许字段内含换行和双引号转义的语义,导致解析错位甚至 panic。
- 始终用
csv.NewReader+Read或ReadAll,别自己分隔 - 如果 CSV 第一行是 header,调用一次
reader.Read()跳过它 - 注意
csv.Reader.FieldsPerRecord = -1(默认值),否则遇到字段数不一致的行会直接报错record on line X has Y fields instead of Z
SQLite 批量插入时如何避免 prepare 语句重复编译
每条 INSERT 都 db.Prepare 一次?性能崩得比没加索引还快。正确做法是复用同一个 *sql.Stmt,在事务内循环 Exec,且参数用 ? 占位符传入,由驱动做类型绑定。
容易踩的坑是把 CSV 字段直接拼进 SQL 字符串里(比如 "INSERT INTO t VALUES ('" + field + "')" ):这既不安全(SQL 注入),又让 SQLite 无法复用执行计划,还可能因单引号、NUL 字节等触发语法错误。
- 提前
db.Prepare("INSERT INTO table_name (col1, col2) VALUES (?, ?)") - 在
for循环里对每行调用stmt.Exec(field1, field2) - 务必用
db.Begin()包裹整个导入过程,否则每条 INSERT 都是独立事务,速度慢两个数量级
怎么处理 CSV 中空字段、布尔值、时间字符串到 SQLite 类型的映射
SQLite 本身无严格类型,但 Go 的 database/sql 驱动在 Exec 时仍会对 interface{} 参数做隐式转换。空字符串、"NULL"、"null" 不会自动变成 SQL NULL——你得显式传 nil。
使用 qbo-mileage CLI 及用户凭证,从 Airtable、Outlook 或 Google Calendar 记录生成 QuickBooks Online 里程 CSV 文件。
时间字段如 "2024-03-15T14:22:03Z" 不能直接塞给 Exec,否则 SQLite 存的是字符串而非时间戳,后续 datetime() 函数失效;布尔字段如 "true"/"false" 同理,需转成 int64(1) 或 int64(0)。
- 空字段判断:用
if field == "" { args = append(args, nil) } - 时间解析:用
time.Parse(time.RFC3339, field),成功则传t.Unix()或t.Format("2006-01-02 15:04:05")(取决于表定义) - 布尔值:用
strings.EqualFold(field, "true")判定,传int64(1)或int64(0)
为什么用 github.com/mattn/go-sqlite3 而不是标准库
Go 标准库没有 SQLite 驱动,database/sql 只是接口层。真正干活的是第三方驱动,目前最稳定、更新最勤、支持 WAL 和扩展函数的是 mattn/go-sqlite3。
容易忽略的一点是 CGO:这个驱动依赖 C 编译器,启用时要加 CGO_ENABLED=1,且 Windows 用户若没装 MinGW 或 Visual Studio Build Tools,go build 会直接失败——不是代码问题,是环境缺 C 工具链。
- 导入写
import _ "github.com/mattn/go-sqlite3"(下划线触发 init) - 连接字符串示例:
"file:my.db?_journal=WAL&_synchronous=NORMAL",开启 WAL 提升并发写入性能 - 交叉编译时若不想带 CGO,只能换纯 Go 驱动(如
modernc.org/sqlite),但功能较弱、兼容性差,不推荐生产用
最麻烦的其实是 CSV 字段里的双引号转义和嵌套换行——csv.Reader 能处理,但前提是你的源字符串末尾没丢掉换行符,且没在读取中途被其他 goroutine 并发修改。流式导入看着简单,实际边界 case 全藏在数据细节里。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










