SQLite作为一款轻量级的嵌入式数据库,经常被用来做数据分析、原型验证或者小型应用的数据存储。而实际工作中有大量的数据是以CSV、JSON、Excel这些格式存在的,比如导出的报表、接口返回的数据、同事整理的表格等。要把这些数据装进SQLite,不同格式对应的处理方式差别不小:CSV可以直接用sqlite3自带的.import命令,JSON需要借助json1扩展函数解析,Excel则要先转格式或借助图形化工具。这篇文章就分别讲清楚这三种格式的导入方法,以及每种方式需要注意的坑。

一、导入CSV文件:命令行.import是最快的方式
CSV是纯文本格式,SQLite对它的支持最直接。打开命令行,进入sqlite3交互环境后,只需要三步:先建表,再设置分隔模式,最后执行导入命令。
-- 打开或创建数据库
sqlite3 mydata.db
-- 第一步:创建目标表,字段类型要和CSV内容匹配
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT,
age INTEGER,
email TEXT
);
-- 第二步:设置导入格式为csv
.mode csv
-- 第三步:执行导入,第一个参数是文件路径,第二个参数是表名
.import users.csv users
这里有个非常容易踩的坑:如果CSV文件第一行是表头(比如id,name,age,email),直接执行上面的命令会把表头也当成一条数据插进去。解决办法是在导入前执行.headers off并不能解决问题,正确做法是先跳过表头行。新版本的sqlite3提供了.import --csv --skip 1 users.csv users这样的写法,其中--skip 1表示跳过第一行;如果你的sqlite3版本较老不支持这个参数,可以先用文本编辑器把表头行删掉再导入。
另一个常见问题是中文乱码。SQLite要求CSV文件使用UTF-8编码,如果文件是GBK或者带BOM的UTF-8,导入后中文会变成乱码或者字段开头出现不可见字符。建议先用编辑器把文件另存为无BOM的UTF-8格式。此外,如果表已经存在数据,导入时会直接追加,重复执行命令会导致数据翻倍,导入前最好确认表是空的或者先删掉旧数据。
如果不想手工建表,也可以让SQLite根据CSV内容自动推断表结构:先执行.import --csv users.csv newtable --schema(需要较新版本支持),它会读取文件前若干行自动生成CREATE TABLE语句。不过自动推断的类型不一定准确,比如手机号可能被认成整数,生产环境还是建议手动建表更稳妥。
二、导入JSON文件:利用json1扩展逐条解析插入
JSON格式比CSV复杂,因为它可能是对象数组、嵌套结构甚至不规则字段。SQLite从3.9版本开始内置了json1扩展,提供json_extract、json_each等函数,可以直接在SQL中解析JSON字符串。假设有一个data.json文件,内容是一个对象数组:
[
{"id": 1, "name": "张三", "age": 28, "city": "北京"},
{"id": 2, "name": "李四", "age": 35, "city": "上海"}
]
由于sqlite3命令行的.import不直接支持JSON,最灵活的做法是用Python脚本读取文件再批量插入。Python标准库自带sqlite3和json模块,不需要额外安装任何依赖:
import json
import sqlite3
# 读取JSON文件
with open('data.json', 'r', encoding='utf-8') as f:
rows = json.load(f)
# 连接数据库并建表
conn = sqlite3.connect('mydata.db')
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS persons (
id INTEGER PRIMARY KEY,
name TEXT,
age INTEGER,
city TEXT
)
''')
# 使用executemany批量插入,效率远高于逐条execute
cursor.executemany(
'INSERT INTO persons (id, name, age, city) VALUES (:id, :name, :age, :city)',
rows
)
conn.commit()
conn.close()
print(f'成功导入 {len(rows)} 条数据')
这里有两个细节值得注意。第一,executemany配合字典参数的写法,字段名和JSON的key自动对应,JSON里字段顺序变了也不影响;如果用元组传参,就必须严格保证顺序一致。第二,如果JSON数据是嵌套结构,比如每条记录里还有一个address对象,可以先把嵌套部分取出来再插入,或者干脆把整个嵌套对象用json.dumps转成字符串存进TEXT字段,需要时再用json_extract在SQL里查询:
-- 假设info字段存的是JSON字符串,可以直接查询内部key SELECT json_extract(info, '$.city') AS city, COUNT(*) FROM persons GROUP BY city;
这种把JSON整串存进TEXT列的方式是SQLite官方推荐的半结构化数据存储方案,比拆成多个关联表要省事得多,适合字段不固定、结构经常变化的场景。
三、导入Excel文件:先转换再用图形化工具最省事
Excel的xlsx格式本质上是压缩的XML包,sqlite3命令行完全无法直接识别,所以必须走转换路线。第一种方案是用Excel本身把文件另存为CSV(逗号分隔),然后按第一节的.import流程操作。这种方式简单,但要注意Excel另存CSV时会丢失多工作表信息(一个文件只能存当前工作表),日期格式也可能被转成Excel默认的显示格式。
第二种方案是使用图形化工具DB Browser for SQLite,它是免费开源的,操作直观:打开目标数据库后,在菜单里选择导入CSV或直接执行导入向导,工具会自动识别表头、推断字段类型,并且提供预览界面让你确认。对于Excel文件,可以先用工具的导入向导选择从剪贴板粘贴数据,或者直接把Excel中的数据区域复制粘贴进DB Browser的数据浏览页,这种方式不需要中间文件,适合数据量不大的一次性导入。
第三种方案适合需要自动化处理的场景:用Python的openpyxl库读Excel,再写入SQLite:
import sqlite3
from openpyxl import load_workbook
# 打开Excel文件,read_only模式占用内存更少
wb = load_workbook('data.xlsx', read_only=True)
sheet = wb.active
conn = sqlite3.connect('mydata.db')
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS records (
id INTEGER, name TEXT, score REAL
)
''')
# iter_rows跳过第一行表头
rows = [(r[0], r[1], r[2]) for r in sheet.iter_rows(min_row=2, values_only=True)]
cursor.executemany('INSERT INTO records VALUES (?, ?, ?)', rows)
conn.commit()
conn.close()
print('Excel数据导入完成')
用脚本方式的好处是可以处理多个工作表、做多字段清洗,比如去掉空行、统一日期格式、过滤非法值等。Excel里的数字单元格读出来可能是float类型,整数会带小数点,插入前可以按需做类型转换。
四、导入后的校验与常见问题排查
数据导入完成后不要急着用,先做几项基础校验:用SELECT COUNT(*) FROM 表名对比源文件行数,检查是否有遗漏;抽查几条记录看中文字段是否正常;用PRAGMA table_info(表名)确认字段类型是否符合预期。
常见问题主要集中在三方面。一是分隔符问题,有些CSV是用制表符或分号分隔的(欧洲地区导出的常见),需要先执行.separator ";"再导入,或者改用.mode tabs。二是数据量大的导入速度慢,命令行导入本身很快,但脚本逐条插入会慢,一定要用executemany批量提交,几万条数据秒级就能完成。三是主键冲突,如果源数据中有重复的id,插入会报错,可以在INSERT语句改用INSERT OR IGNORE跳过重复项,或用INSERT OR REPLACE让新数据覆盖旧数据,按业务需要选择即可。
总的来说,CSV走命令行最快,JSON适合用脚本解析以保留结构信息,Excel要么转CSV要么借助工具或openpyxl。掌握这三种路径,日常遇到的各种外部数据基本都能顺畅地装进SQLite里做后续分析。
SQLite导入数据CSV导入SQLiteExcel导入SQLite修改时间:2026-09-06 12:20:41