Menu

SQLite 导出数据:用命令行导出 CSV、JSON 和 SQL

如何把数据从 SQLite 中导出:带表头的 CSV、JSON、完整的 SQL 转储,以及用 sqlite3 命令行工具备份单张表。

本页包含可运行的编辑器。编辑、运行,立即查看输出。

导出是命令行的工作,不是 SQL 语句

SQLite 没有 Postgres 那样的 COPY ... TO,也没有 MySQL 那样的 SELECT INTO OUTFILE。导出数据要在 sqlite3 命令行工具中完成,靠的是点命令:.mode、.headers、.output、.dump。掌握这四个命令,你就能从任何数据库中导出 CSV、JSON、纯文本或完整的 SQL 转储。

可以这样理解:你告诉命令行工具如何格式化结果(.mode)、是否包含列名(.headers),以及把输出发到哪里(.output)。然后运行一个查询,查询结果就会写进文件。

先建一个小数据库来练习:

三行四列。我们会把它导出成几种格式。

CSV:带表头的 .mode csv

CSV 是最常用的导出格式:电子表格、数据管道和大多数其他工具都支持它。在 sqlite3 命令行中:

sqlite> .mode csv
sqlite> .headers on
sqlite> .output users.csv
sqlite> SELECT * FROM users;
sqlite> .output stdout

刚才发生了什么:

  • .mode csv 把每一行格式化为逗号分隔的值,并给包含逗号、引号或换行符的字段加上引号。
  • .headers on 会添加第一行列名。不加的话,CSV 就没有表头,这通常不是你想要的。
  • .output users.csv 把结果重定向到文件。从这时起,查询输出会写进文件,而不是显示在屏幕上。
  • SELECT 运行后,会悄悄写入文件。
  • .output stdout 把输出切换回终端,这样你就能看到下一个查询的结果。

生成的文件:

id,name,email,signup_date
1,"Ada Lovelace",ada@example.com,2025-01-15
2,"Boris Johnson",boris@example.com,2025-02-03
3,"Carmen Diaz",carmen@example.com,2025-03-22

你可以导出任意查询的结果,不只是整张表:先过滤、连接、聚合,再重定向输出:

sqlite> .output recent_users.csv
sqlite> SELECT name, email FROM users WHERE signup_date >= '2025-02-01';
sqlite> .output stdout

在系统命令行中一行搞定

你完全不必进入交互式命令行。可以在操作系统的命令行中,把点命令和 SQL 通过管道传给 sqlite3:

sqlite3 mydb.sqlite <<EOF
.headers on
.mode csv
.output users.csv
SELECT * FROM users;
EOF

写脚本和定时任务(cron)时就该用这种形式:可重复执行,无需手动输入。.output 只在本次会话中有效,所以不会把状态泄漏到别处。

JSON:.mode json

如果导出的数据要交给 Web 应用或读取 JSON 的工具,.mode json 会生成一个对象数组,每行一个对象:

sqlite> .mode json
sqlite> .output users.json
sqlite> SELECT * FROM users;
sqlite> .output stdout

文件内容:

[{"id":1,"name":"Ada Lovelace","email":"ada@example.com","signup_date":"2025-01-15"},
{"id":2,"name":"Boris Johnson","email":"boris@example.com","signup_date":"2025-02-03"},
{"id":3,"name":"Carmen Diaz","email":"carmen@example.com","signup_date":"2025-03-22"}]

在 JSON 中,表头隐含在键里,所以 .headers 在这里不起作用。如果你想要自定义结构,比如嵌套对象或重命名字段,就在查询中用 json_object() 构建:

这样每行都会得到一个 JSON 字符串,结构完全由你掌控。再配合 json_group_array(),就能把整个结果汇总成一个 JSON 文档。

完整的 SQL 转储:.dump

.dump 和 CSV、JSON 有本质上的不同。它会生成一个 .sql 文件,以 CREATE TABLE 和 INSERT 语句的形式包含表结构和全部数据,足以从空库重建整个数据库:

sqlite3 mydb.sqlite .dump > backup.sql

输出内容的一个片段:

PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE users (
    id INTEGER PRIMARY KEY,
    name TEXT NOT NULL,
    email TEXT NOT NULL,
    signup_date TEXT NOT NULL
);
INSERT INTO users VALUES(1,'Ada Lovelace','ada@example.com','2025-01-15');
INSERT INTO users VALUES(2,'Boris Johnson','boris@example.com','2025-02-03');
INSERT INTO users VALUES(3,'Carmen Diaz','carmen@example.com','2025-03-22');
COMMIT;

恢复则是反向操作:把文件通过管道导入一个新数据库:

sqlite3 restored.sqlite < backup.sql

.dump 适合用来做备份、把测试数据快照纳入版本控制,以及在机器之间迁移数据。它会保留索引、触发器、视图等表结构中的一切。

只转储一张表

.dump 可以接收一个表名(或匹配模式)来限制输出范围:

sqlite3 mydb.sqlite ".dump users" > users_only.sql

这只会转储 users 表的结构和数据行。当你只想把一张表复制到另一个数据库、不想带上其他内容时,这很有用。你也可以用模式匹配:.dump 'log_%' 会转储所有以 log_ 开头的表。

只导出表结构,不要数据

有时你只需要结构而不需要数据行,比如用来写文档、搭建干净的开发环境,或者对比不同数据库的表结构。.schema 只输出 CREATE 语句:

sqlite3 mydb.sqlite .schema > schema.sql

加上表名,就只导出那一张表:

sqlite3 mydb.sqlite ".schema users" > users_schema.sql

输出是纯 SQL,包括 CREATE TABLE、CREATE INDEX、CREATE TRIGGER,可以直接在空数据库上运行。

其他实用模式

除了 CSV 和 JSON,.mode 还有更多选项。下面几个值得了解:

.mode column        -- aligned columns, nice for reading at the terminal
.mode markdown      -- pipe-separated, GitHub-friendly tables
.mode html          -- HTML <table> output
.mode tabs          -- tab-separated values (TSV)
.mode insert users  -- emits INSERT statements for the named table
.mode quote         -- SQL-quoted values, useful for inspection

.mode markdown 非常适合把查询结果粘贴到 README 或合并请求里。.mode insert <table> 是生成种子数据的快捷方式:运行一个 SELECT,拿到 INSERT 语句,粘贴到测试数据文件中。

sqlite> .mode insert users
sqlite> .output seed.sql
sqlite> SELECT * FROM users WHERE signup_date >= '2025-02-01';
sqlite> .output stdout

几点实用提示

  • .output stdout(或不带参数的 .output)会恢复终端输出。 忘了这一步,下一个查询的结果就会悄无声息地写进文件。
  • CSV 导出不保留类型。 文件里的一切都会变成文本,重新导入时需要有目标表结构来解释它。如果需要原样导回另一个 SQLite 数据库,请用 .dump。
  • 大量数据的导出是流式进行的。 .output 会边生成边写入数据行,所以转储比内存还大的表也没问题。
  • 要对正在使用的数据库做热备份,.dump 也可以,但专门的 .backup 命令(课程后面会讲到)更快也更安全,因为它使用的是 SQLite 的在线备份 API。

下一步:查询数据

现在你已经全面了解了写入数据:INSERT、UPDATE、DELETE、UPSERT、RETURNING、从 CSV 导入,以及把数据导出。接下来是使用数据库的另一半:高效地读取数据。你的大部分时间都会花在 SELECT 语句上,这就是下一页的内容。

常见问题

怎么把 SQLite 表导出为 CSV?

在 sqlite3 命令行中切换到 CSV 模式,打开表头,把输出指向一个文件,然后运行查询:依次执行 .mode csv、.headers on、.output users.csv,再执行 SELECT * FROM users;。完成后运行 .output stdout,让结果重新显示在终端上。

.dump 和导出 CSV 有什么区别?

.dump 会生成一个 .sql 文件,里面有 CREATE TABLE 语句和 INSERT 语句,包含从零重建数据库所需的一切。CSV 只导出一个查询或一张表的行,不包含表结构。备份和迁移用 .dump;把数据交给电子表格或其他工具时用 CSV。

可以把 SQLite 查询结果导出为 JSON 吗?

可以。要么在命令行里设置 .mode json 然后运行任意 SELECT,要么在查询中用内置的 json_object() 和 json_group_array() 函数构建 JSON。临时导出用 .mode json 更简单;用函数则能完全掌控 JSON 的结构。

Coddy 编程语言插图

和 Coddy 一起学编程

开始