SQLite 命令行 Shell 完整指南

1. 入门

SQLite 项目提供名为 sqlite3 的命令行程序(Windows 为 sqlite3.exe),让用户以交互方式对 SQLite 数据库运行 SQL 语句。本文简要介绍该程序的使用方法。

1.1. 命令行程序与 SQLite 库

SQLite 库实现 SQL 数据库引擎。sqlite3 命令行程序(CLI)是接受用户输入并交给该库求值的应用。两者不同:谈到 SQLite 或 sqlite3 时,可能指库,也可能指提供人机接口的 CLI。

通常要结合上下文判断所指对象。

本文介绍 CLI,而非底层 SQLite 库。

1.2. CLI 的图形界面替代方案

sqlite3 由 SQLite 核心开发者为自身需求编写,也是官方支持的交互访问数据库文件的方法。喜欢图形界面的用户,可以使用第三方提供的若干 GUI 程序。

1.3. 启动 CLI

在命令提示符输入 sqlite3,后面可跟数据库文件名或 ZIP 归档名。文件不存在时,程序会自动创建该名称的新数据库。不指定文件时使用临时内存数据库,程序退出后删除。

启动时程序显示简短说明,随后提示输入 SQL。输入以分号结束的 SQL 语句,按 Enter 即可执行。

例如,创建 ex1.db 数据库及其中的 tbl1 表:

$ sqlite3 ex1.db
SQLite version 3.36.0 2021-06-18 18:36:39
Enter ".help" for usage hints.
sqlite> create table tbl1(one text, two int);
sqlite> insert into tbl1 values('hello!',10),('goodbye',20);
sqlite> select * from tbl1;
┌───────────┬─────┐
│    one    │ two │
├───────────┼─────┤
│ 'hello!'  │ 10  │
│ 'goodbye' │ 20  │
└───────────┴─────┘
sqlite>

输入系统的文件结束字符(通常为 Ctrl-D)退出。中断字符(通常为 Ctrl-C)可停止运行时间较长的 SQL 语句。

每条 SQL 命令末尾务必输入分号!sqlite3 据此判断命令完整。缺少分号时会显示续行提示,等待补全,因此可以输入跨行 SQL,例如:

sqlite> CREATE TABLE tbl2 (
   ...>   f1 varchar(30) primary key,
   ...>   f2 text,
   ...>   f3 real
   ...> );
sqlite>

1.4. Windows 双击启动

Windows 用户可双击 sqlite3.exe 图标,打开运行 SQLite 的终端。这样启动不带命令行参数,也未指定数据库文件,因此使用退出后删除的临时内存数据库。要使用持久化磁盘数据库,启动终端后立即输入 .open:

SQLite version 3.36.0 2021-06-18 18:36:39
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite> .open ex1.db
sqlite>

上例打开并使用 ex1.db;若不存在则创建。可使用完整路径确保目录正确,目录分隔符用正斜杠,即 c:/work/ex1.db,而不是 c:\work\ex1.db。

也可以先以默认临时存储创建数据库,再用 .save 保存到磁盘:

SQLite version 3.36.0 2021-06-18 18:36:39
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite> ... many SQL commands omitted ...
sqlite> .save ex1.db
sqlite>

注意:.save 会覆盖同名现有数据库,不要求确认。与 .open 一样,建议使用正斜杠分隔的完整路径,避免歧义。

1.5. 在浏览器中运行 CLI

可以用 Emscripten 编译 CLI,使其在浏览器内运行。可到 SQLite Fiddle 试用近期版本。浏览器标签页并非通用计算机,因此 Fiddle 不提供全部功能,但适合用作尝试 SQL 的沙箱。

2. 特殊命令(点命令)

通常 sqlite3 读取 SQL 输入并交给 SQLite 库求值。以点号 . 开头的输入行会由程序自身截获并解释。这些点命令常用于改变查询输出格式,或执行预先封装的查询。最初只有几条,经过多年扩展,现在已超过 60 条。

输入不带参数的 .help 查看可用命令,或用 .help TOPIC 查看指定主题的详细说明。SQLite 3.52.0 的点命令清单如下:

sqlite> .help
.archive ...             Manage SQL archives
.auth ON|OFF             Show authorizer callbacks
.backup ?DB? FILE        Backup DB (default "main") to FILE
.bail on|off             Stop after hitting an error.  Default OFF
.cd DIRECTORY            Change the working directory to DIRECTORY
.changes on|off          Show number of rows changed by SQL
.check GLOB              Fail if output since .testcase does not match
.clone NEWDB             Clone data into NEWDB from the existing database
.connection [close] [#]  Open or close an auxiliary database connection
.crlf ?on|off?           Whether or not to use \r\n line endings
.databases               List names and files of attached databases
.dbconfig ?op? ?val?     List or change sqlite3_db_config() options
.dbinfo ?DB?             Show status information about the database
.dbtotxt                 Hex dump of the database file
.dump ?OBJECTS?          Render database content as SQL
.echo on|off             Turn command echo on or off
.eqp on|off|full|...     Enable or disable automatic EXPLAIN QUERY PLAN
.excel                   Display the output of next command in spreadsheet
.exit ?CODE?             Exit this program with return-code CODE
.expert                  EXPERIMENTAL. Suggest indexes for queries
.explain ?on|off|auto?   Change the EXPLAIN formatting mode.  Default: auto
.filectrl CMD ...        Run various sqlite3_file_control() operations
.fullschema ?--indent?   Show schema and the content of sqlite_stat tables
.help ?-all? ?PATTERN?   Show help text for PATTERN
.import FILE TABLE       Import data from FILE into TABLE
.imposter INDEX TABLE    Create imposter table TABLE on index INDEX
.indexes ?TABLE?         Show names of indexes
.intck ?STEPS_PER_UNLOCK?  Run an incremental integrity check on the db
.limit ?LIMIT? ?VAL?     Display or change the value of an SQLITE_LIMIT
.lint OPTIONS            Report potential schema issues.
.load FILE ?ENTRY?       Load an extension library
.log FILE|on|off         Turn logging on or off.  FILE can be stderr/stdout
.mode ?MODE? ?OPTIONS?   Set output mode
.nonce STRING            Suspend safe mode for one command if nonce matches
.nullvalue STRING        Use STRING in place of NULL values
.once ?OPTIONS? ?FILE?   Output for the next SQL command only to FILE
.open ?OPTIONS? ?FILE?   Close existing database and reopen FILE
.output ?FILE?           Send output to FILE or stdout if FILE is omitted
.parameter CMD ...       Manage SQL parameter bindings
.print STRING...         Print literal STRING
.progress N              Invoke progress handler after every N opcodes
.prompt MAIN CONTINUE    Replace the standard prompts
.quit                    Stop interpreting input stream, exit if primary.
.read FILE               Read input from FILE or command output
.recover                 Recover as much data as possible from corrupt db.
.restore ?DB? FILE       Restore content of DB (default "main") from FILE
.save ?OPTIONS? FILE     Write database to FILE (an alias for .backup ...)
.scanstats on|off|est    Turn sqlite3_stmt_scanstatus() metrics on or off
.schema ?PATTERN?        Show the CREATE statements matching PATTERN
.session ?NAME? CMD ...  Create or control sessions
.sha3sum ...             Compute a SHA3 hash of database content
.shell CMD ARGS...       Run CMD ARGS... in a system shell
.stats ?ARG?             Show stats or turn stats on or off
.system CMD ARGS...      Run CMD ARGS... in a system shell
.tables ?TABLE?          List names of tables matching LIKE pattern TABLE
.timeout MS              Try opening locked tables for MS milliseconds
.timer on|off            Turn SQL timer on or off
.trace ?OPTIONS?         Output each SQL statement as it is run
.unmodule NAME ...       Unregister virtual table modules
.version                 Show source, library and compiler versions
.vfsinfo ?AUX?           Information about the top-level VFS
.vfslist                 List all available VFSes
.vfsname ?AUX?           Print the name of the VFS stack
.www                     Display output of the next command in web browser
sqlite>

除了 .help 展示的命令,还有未记录的测试命令,以及为向后兼容保留的废弃命令。

大多数点命令可以缩写,例如 .q 常用作 .quit 的缩写。

3. 点命令、SQL 与其他输入的规则

3.1. 行结构

CLI 输入可以混合包含:

– SQL 语句。

– 点命令。

– CLI 注释。

SQL 语句格式自由,可以跨多行,任意位置可包含空白和 SQL 注释。输入行末尾的 ;、单独一行的 / 或 go 均可结束语句。位于行中间的分号用于分隔 SQL 语句。判定结束时忽略行尾空白。

点命令有专门语法:

– 必须在最左侧以 . 开头,前面不能有空白。

– 必须全部放在一行内。

– 不能出现在普通 SQL 语句中间,即不能用于续行提示处。

– 没有注释语法。

– 从版本 3.52.0 起,末尾未加引号的分号会被忽略。

CLI 也接受以 # 开头、延伸至行尾的整行注释,# 之前不能有空白。

3.2. 点命令参数

点命令后可跟零个或多个由空格分隔的参数。解析规则如下:

1. 去掉末尾空白及最后的 ;(如果有)。

2. 参数之间、参数与点命令之间以空白分隔。

3. '...' 中的文本作为单个参数,移除引号,即使文本含空白也如此。

4. "..." 中的文本作为单个参数,移除双引号。

5. C 风格反斜杠转义,例如 \\、\n、\r、\"、\033,只在双引号参数中生效。

3.3. 点命令单独求值

点命令由 sqlite3.exe 程序解释,而非 SQLite 库。因此它们不能作为 sqlite3_prepare() 或 sqlite3_exec() 等核心库接口的参数。

4. 输出格式

CLI 可用多种格式展示查询结果,使用 .mode 控制。该命令的细节很多,官方在独立文档中介绍。

下面先给出几个简短示例:

命令 效果
.mode box 用 Unicode 框线组成的网格显示查询结果。
.mode quote 每行结果对应一行逗号分隔的 SQL 字面量。
.mode csv 输出逗号分隔值(CSV)。
.mode --list 列出可用输出模式。
.mode 显示当前输出模式。
.mode --once box 下一条 SQL 使用 box 模式,随后自动恢复当前模式。

5. 查询数据库模式

sqlite3 提供若干便捷命令查看数据库结构。它们的功能都能通过其他方法实现,提供这些命令只是为了方便。

例如输入 .tables 查看表名列表:

sqlite> .tables
tbl1 tbl2
sqlite>

.tables 类似于设为 list 模式后执行:

SELECT name FROM sqlite_schema
WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%'
ORDER BY 1

但 .tables 还会查询所有已附加数据库的 sqlite_schema 表,不仅是主数据库,并把结果排列成整齐的列。

.indexes 类似地列出索引。传入表名作为参数时,只显示该表的索引。

.schema 显示完整数据库结构;提供可选表名时只显示该表:

sqlite> .schema
create table tbl1(one varchar(10), two smallint)
CREATE TABLE tbl2 (
  f1 varchar(30) primary key,
  f2 text,
  f3 real
);
sqlite> .schema tbl2
CREATE TABLE tbl2 (
  f1 varchar(30) primary key,
  f2 text,
  f3 real
);
sqlite>

.schema 大致相当于设为 list 模式后执行:

SELECT sql FROM sqlite_schema
ORDER BY tbl_name, type DESC, name

与 .tables 一样,.schema 显示所有已附加数据库的结构。只想查看某个数据库(例如 main)时,可加参数限制输出:

sqlite> .schema main.*

加上 --indent 时,.schema 会尝试重新排版各条 CREATE 语句,提高可读性。

.databases 列出当前连接打开的所有数据库,至少有两个:main 是最初打开的数据库,temp 用于临时表;ATTACH 可能附加其他数据库。输出第一列为附加名称,第二列为外部文件名。

第三列若存在,使用 r/o 或 r/w 表示只读或读写;第四列若存在,展示该数据库的 sqlite3_txn_state() 结果。

sqlite> .databases

.fullschema 类似 .schema,显示全部数据库结构,还包含 sqlite_stat1、sqlite_stat3、sqlite_stat4(若存在)的数据。通常这足以准确重现特定查询的执行计划。

向 SQLite 开发团队报告疑似查询规划器问题时,应提供完整 .fullschema 输出。注意 sqlite_stat3 和 sqlite_stat4 含索引条目样本,可能有敏感数据,不要在公开渠道发送私有数据库的输出。

6. 打开数据库文件

.open 先关闭原连接,再打开新连接。最简单的形式是对参数文件调用 sqlite3_open()。使用 :memory: 打开内存数据库,它在 CLI 退出或再次 .open 时消失。不指定名称则打开私有临时磁盘数据库,同样在退出或再次 .open 时删除。

.open --new 会在打开前重置数据库,销毁全部旧数据。这是破坏性覆盖且不要求确认,须谨慎使用。

--ifexists 只允许打开已经存在的文件,防止创建新空数据库。

--readonly 以只读模式打开,禁止写入。

--deserialize 将磁盘文件全部读入内存,通过 sqlite3_deserialize() 打开为内存数据库。大数据库会消耗大量内存,修改也不会自动保存回磁盘,必须显式使用 .save 或 .backup。

--append 让数据库附加在现有文件后,而不是独立文件;详见 appendvfs 扩展。

--zip 将输入文件视为 ZIP 归档而非 SQLite 数据库。

--hexdb 从后续输入行以十六进制格式读取数据库内容,不读取另一个磁盘文件。.dbtotxt 或 dbtotxt 工具可生成相应文本。该选项用于 SQLite 内部测试,开发者目前不知道内部测试、开发以外的用途。

7. 重定向输入与输出

7.1. 写入结果文件

查询结果默认写到标准输出。.output 后跟文件名,把此后所有查询结果写入文件;.once 只重定向下一条命令,随后恢复控制台。不带参数的 .output 恢复标准输出。例如:

sqlite> .mode list --colsep "|"
sqlite> .output test_file_1.txt
sqlite> select * from tbl1;
sqlite> .exit
$ cat test_file_1.txt
hello|10
goodbye|20
$

若 .output 或 .once 的文件名以 | 开头,余下文本视为命令,结果传给该命令。这让查询结果容易传入其他进程。例如 Mac 的 open -f 打开文本编辑器显示标准输入内容,因此可以这样查看结果:

sqlite> .once | open -f
sqlite> SELECT * FROM bigTable;

参数为 -e 时,结果先收集到临时文件,再调用系统文本编辑器。因此 .once -e 与 .once '|open -f' 效果相同,但可跨系统使用。

参数为 -x 时,结果以 CSV 写入临时文件,再调用系统默认 CSV 查看工具,通常为电子表格程序。这是把结果送入电子表格快速查看的方法:

sqlite> .once -x
sqlite> SELECT * FROM bigTable;

.excel 是 .once -x 的别名,行为完全相同。

-w 会在浏览器中显示输出。.www 是 .once -w 的别名。默认以 HTML 表格展示,加入 --plain 可改为纯文本。

sqlite> .www
sqlite> SELECT * FROM users WHERE email LIKE '%@aol.com';

7.2. 从文件读取 SQL

交互模式从键盘读取 SQL 或点命令。启动时也可从文件重定向输入,但这样无法继续交互。有时需要在交互输入其他命令的同时运行文件中的 SQL 脚本,.read 就用于此。

.read 接受一个参数,通常是要读取的文件名。

sqlite> .read myscript.sql

它暂时停止读取键盘,转而从文件读取;文件结束后恢复键盘。脚本中也可以包含点命令。

若参数以 | 开头,.read 不打开文件,而是执行去掉首个 | 后的命令,把该命令输出作为输入。生成 SQL 的脚本可直接这样执行:

sqlite> .read |myscript.bat

7.3. 文件输入输出函数

CLI 增加两个应用定义 SQL 函数,分别把文件内容读入列、把列内容写入文件。

readfile(X) 读取名为 X 的文件全部内容,作为 BLOB 返回,可用于把内容载入表:

sqlite> CREATE TABLE images(name TEXT, type TEXT, img BLOB);
sqlite> INSERT INTO images(name,type,img)
   ...>   VALUES('icon','jpeg',readfile('icon.jpg'));

writefile(X,Y) 把 BLOB Y 写到文件 X,返回写入字节数,可把单列内容提取到文件:

sqlite> SELECT writefile('icon.jpg',img) FROM images WHERE name='icon';

这两个函数属于扩展,并非核心 SQLite 库内置功能。源代码仓库中的 ext/misc/fileio.c 提供它们的可加载扩展。

7.4. edit() SQL 函数

CLI 的另一个内置函数为 edit(),接受一或两个参数。第一个是要编辑的值,常为多行长字符串;第二个是文本编辑器的调用命令,可带选项。省略第二个参数时,使用 VISUAL 环境变量。

edit 将第一个参数写入临时文件,调用编辑器,编辑结束后重新读回内存,再返回修改后的文本。

它可以修改很长的文本值,例如:

sqlite> UPDATE docs SET body=edit(body) WHERE name='report-15';

本例把 docs.name 为 report-15 的记录中 docs.body 的内容送给编辑器,返回后写回该字段。

edit 默认调用文本编辑器。第二个参数也可以指定其他编辑程序,修改图像或非文本资源。例如编辑表字段中存储的 JPEG:

sqlite> UPDATE pics SET img=edit(img,'gimp') WHERE id='pic-1542';

忽略返回值时,也可只把程序当作查看器,例如仅查看上述图像:

sqlite> SELECT length(edit(img,'gimp')) WHERE id='pic-1542';

7.5. 导入 CSV 或其他格式

.import 把 CSV 或类似分隔数据导入表。它接受输入来源和目标表名两个参数。输入来源通常是文件名;以 | 开头时,是生成输入数据的命令。

导入前可能需要先设定 mode,以防 CLI 按错误格式解释文件。指定 --csv 或 --ascii 时,它们控制输入分隔符;否则使用当前输出模式的分隔符。

目标不在 main 模式时,可用 --schema 指定其他模式,适合导入已 ATTACH 的数据库或 TEMP 表。

首行处理取决于目标表是否存在。不存在时会自动创建表,把首行作为列名,第二行及以后作为数据。表已存在时,包括首行在内的全部行都视为数据。

文件首行为列标签时,可用 --skip 1 跳过。

下面把首行含列名的 CSV 导入预先存在的临时表:

sqlite> .import --csv --skip 1 --schema temp C:/work/somedata.csv tab1

除 ascii 模式外,.import 按 RFC 4180 的字段规则解释记录,但记录与字段分隔符由 .mode 的 --rowsep、--colsep 决定。除 --ascii 外,总会去除引号,逆转 RFC 4180 引用。

要用任意分隔符导入且不处理引号,使用 --ascii 配合 --colsep 与 --rowsep。

7.6. 导出 CSV

设 mode 为 csv,再查询所需行,即可把表或部分表导出为遵循 RFC 4180 的 CSV。

sqlite> .mode csv --titles on
sqlite> .once c:/work/dataout.csv
sqlite> SELECT * FROM tab1;
sqlite> .system c:/work/dataout.csv

上例中 --titles on 把列名打印为首行,因此 CSV 首行包含列标签。不需要列名时使用 --titles off,这是默认值;如果此前未打开表头,也可省略。

.once FILENAME 让查询结果写入指定文件而非控制台。上例写入 C:/work/dataout.csv。

最后的 .system c:/work/dataout.csv 相当于 Windows 双击该文件,通常会启动电子表格程序显示 CSV。

该写法仅适用 Windows。Mac 对应为:

sqlite> .system open dataout.csv

Linux 及其他 Unix 系统使用类似:

sqlite> .system xdg-open dataout.csv

7.6.1. 导出到 Excel

.excel 可捕获一次查询的输出并送入宿主机默认电子表格程序,用法如下:

sqlite> .excel
sqlite> SELECT * FROM tab;

查询结果以 CSV 写入临时文件,调用默认 CSV 程序(通常是 Excel 或 LibreOffice),随后删除临时文件。这是前述 .csv、.once、.system 操作序列的简写。

.excel 实为 .once -x 的别名。-x 写入以 .csv 结尾的临时文件,并调用系统默认 CSV 程序。

.once -e 类似,但临时文件扩展名为 .txt,调用默认文本编辑器而非电子表格。

7.6.2. 导出 TSV(制表符分隔值)

查询前设 .mode tabs 可导出不引用字段的纯 TSV。但包含双引号时,.import 的 tabs 模式无法正确读取。若要得到按 RFC 4180 引用、可被 tabs 模式导入的 TSV,执行:

.mode csv -colsep "\t"

8. 把 ZIP 归档作为数据库访问

sqlite3 除了读写数据库,也能读写 ZIP 归档。在启动参数或 .open 中指定 ZIP 文件,它会自动识别并按 ZIP 打开,与扩展名无关。

所以 JAR、DOCX、ODP 及其他本质为 ZIP 的格式,都能这样读取。

ZIP 归档显示为含有下列模式的单表数据库:

CREATE TABLE zip(
  name,     -- Name of the file
  mode,     -- Unix-style file permissions
  mtime,    -- Timestamp, seconds since 1970
  sz,       -- File size after decompression
  rawdata,  -- Raw compressed file data
  data,     -- Uncompressed file content
  method    -- ZIP compression method code
);

例如,要查看各文件压缩效率(压缩大小相对于原始大小),按压缩效果从高到低排序:

sqlite> SELECT name, (100.0*length(rawdata))/sz FROM zip ORDER BY 2;

也可以用文件 I/O 函数提取归档内容:

sqlite> SELECT writefile(name,content) FROM zip
   ...> WHERE name LIKE 'docProps/%';

8.1. ZIP 访问的实现

CLI 使用 Zipfile 虚拟表访问 ZIP。打开归档后运行 .schema 可看到:

sqlite> .schema
CREATE VIRTUAL TABLE zip USING zipfile('document.docx')
/* zip(name,mode,mtime,sz,rawdata,data,method) */;

发现输入文件为 ZIP 时,客户端实际打开内存数据库,并创建附着于归档的 Zipfile 虚拟表实例。

这属于 CLI 的特殊处理,而非核心库功能。应用若要把 ZIP 作为数据库,必须启用 Zipfile 虚拟表模块,再执行适当的 CREATE VIRTUAL TABLE。

9. 把整个数据库转为文本

.dump 将数据库全部内容转换为单个 UTF-8 文本文件。把它经管道送回 sqlite3,就能还原数据库。

创建归档副本的实用方法:

$ sqlite3 ex1 .dump | gzip -c >ex1.dump.gz

生成的 ex1.dump.gz 包含日后或在另一台机器上重建数据库的全部内容。重建时输入:

$ zcat ex1.dump.gz | sqlite3 ex2

文本格式是纯 SQL,因此也可用 .dump 导出到其他常见 SQL 数据库引擎:

$ createdb ex2
$ sqlite3 ex1 .dump | psql ex2

10. 从损坏数据库恢复数据

.recover 与 .dump 都尝试把整个数据库转成文本。前者不通过正常数据库接口读取,而是尽可能从数据库页提取并重组数据。数据库损坏时,recover 通常可恢复未损坏部分;dump 则在首次遇到损坏迹象时停止。

无法归属到具体表的恢复行会写到输出脚本创建的 lost_and_found 表,其模式如下:

CREATE TABLE lost_and_found(
    rootpgno INTEGER,             -- root page of tree pgno is a part of
    pgno INTEGER,                 -- page number row was found on
    nfield INTEGER,               -- number of fields in row
    id INTEGER,                   -- value of rowid field, or NULL
    c0, c1, c2, c3...             -- columns for fields of row
);

每个恢复的孤立行对应一条记录,无法归属到 SQL 索引的恢复索引项也各有一条记录,因为 SQLite 索引项与 WITHOUT ROWID 表项使用相同格式。

列 内容
rootpgno 即使不能归属到表,该行仍可能属于文件中的树结构,此列记录树的根页编号。若所在页不属于树,则复制 pgno,即发现该行的页号。 许多情况下(但并非全部),rootpgno 相同的记录属于同一表。
pgno 发现该行的页号。
nfield 行的字段数。
id 若来自 WITHOUT ROWID 表则为 NULL;否则为 64 位整数 rowid。
c0、c1、c2… 各字段的值。recover 按最长孤立行的需要创建足够多的列。

若已有 lost_and_found 表,recover 改用 lost_and_found0;被占用则使用 lost_and_found1,依此类推。--lost-and-found 可覆盖默认名称,例如改为 orphaned_rows:

sqlite> .recover --lost-and-found orphaned_rows

11. 加载扩展

运行时用 .load 可添加自定义 SQL 函数、排序规则、虚拟表和 VFS。先按运行时可加载扩展文档将其构建为 DLL 或共享库,再输入:

sqlite> .load /path/to/my_extension

SQLite 自动添加相应扩展名:Windows 为 .dll、Mac 为 .dylib、其他多数 Unix 为 .so。通常建议指定完整路径。

扩展入口根据文件名推导。要覆盖该选择,在 .load 后增加入口名称作为第二个参数。

源码树的 ext/misc 子目录有多种实用扩展。可直接使用,也可据此创建自定义扩展。

12. 数据库内容的加密散列

.sha3sum 计算数据库**内容**的 SHA3,而非磁盘表示的散列。因此 VACUUM 等保留数据的转换不会改变散列。

选项 --sha3-224、--sha3-256、--sha3-384、--sha3-512 选择变体,默认 SHA3-256。

通常不包含 sqlite_schema 中的结构,可加 --schema 纳入。

可选参数为 LIKE 模式。指定后只计算表名匹配的表。

该命令使用 CLI 自带的 sha3_query() 扩展函数实现。

13. 数据库内容自检

.selftest 尝试验证数据库是否完整、未损坏,查找名为 selftest 的表,定义如下:

CREATE TABLE selftest(
  tno INTEGER PRIMARY KEY,  -- Test number
  op TEXT,                  -- 'run' or 'memo'
  cmd TEXT,                 -- SQL command to run, or text of "memo"
  ans TEXT                  -- Expected result of the SQL command
);

按 tno 顺序读取记录。op 为 memo 时打印 cmd 内容;op 为 run 时把 cmd 当作 SQL 执行,与 ans 比较,不同则报错。

没有 selftest 表时执行 PRAGMA integrity_check。

.selftest --init 在需要时创建表,并添加全部表内容的 SHA3 检查项。以后运行 selftest 即可验证数据库未改变。只检查部分表时,运行 init 后 DELETE 掉非恒定表对应的行。

14. SQLite 归档支持

.archive 和命令行 -A 内置支持 SQLite Archive 格式,接口类似 Unix 的 tar。每次 .ar 必须指定一个命令选项:

选项 长选项 用途
-c –create 创建包含指定文件的新归档。
-x –extract 提取指定文件。
-i –insert 向现有归档添加文件。
-r –remove 从归档删除文件。
-t –list 列出归档文件。
-u –update 文件变更后更新到现有归档。

除命令选项外,每次 .ar 可指定若干修饰选项。有些需要参数,有些不需要:

选项 长选项 用途
-v –verbose 打印处理的每个文件。
-f FILE –file FILE 指定归档文件;否则使用当前 main 数据库。
-a FILE –append FILE 类似 –file,但用 apndvfs VFS 把归档附加在现有文件末尾。
-C DIR –directory DIR 相对路径以 DIR 而非当前目录为基准。
-g –glob 用 glob(Y,X) 匹配归档内名称。
-n –dryrun 显示将执行的 SQL,不修改数据。
— — 后面的词均视为命令参数,而非选项。

命令行使用时,短选项紧跟 -A,中间不留空格。后续参数都属于归档命令。下面两条等价:

sqlite3 new_archive.db -Acv file1 file2 file3
sqlite3 new_archive.db ".ar -cv file1 file2 file3"

长短选项可以混用,例如:

-- Two ways to create a new archive named "new_archive.db" containing
-- files "file1", "file2" and "file3".
.ar -c --file new_archive.db file1 file2 file3
.ar -f new_archive.db --create file1 file2 file3

也可将所需短选项拼接作为 .ar 第一个参数,不加减号。需要的选项参数从后续词中读取,剩余词作为命令参数:

-- Create a new archive "new_archive.db" containing files "file1" and
-- "file2" from directory "dir1".
.ar cCf dir1 new_archive.db file1 file2 file3

14.1. 创建归档

创建新归档并覆盖现有归档(当前 main 数据库,或 –file 指定文件)。选项后各参数为加入的文件,目录递归导入。示例见前文。

14.2. 提取归档

提取到当前工作目录或 –directory 指定目录。提取参数所匹配的文件、目录,匹配受 –glob 影响。没有参数时提取全部。目录递归提取;任何指定名称或模式未找到时都报错。

-- Extract all files from the archive in the current "main" db to the
-- current working directory. List files as they are extracted.
.ar --extract --verbose

-- Extract file "file1" from archive "ar.db" to directory "dir1".
.ar fCx ar.db dir1 file1

-- Extract files with ".h" extension to directory "headers".
.ar -gCx headers *.h

14.3. 列出归档

不指定参数则列出全部,否则只列出匹配参数的文件。目前 –verbose 不改变此命令行为,未来可能变化。

-- List contents of archive in current "main" db..
.ar --list

14.4. 插入与更新

–update 和 –insert 类似 –create,但不会先删除现有归档。新版本静默替换同名文件,其余内容保留。

insert 插入列出的全部文件。update 只插入不存在的文件,或 mtime、mode 与归档版本不同的文件。

兼容性说明:SQLite 3.28.0(2019-04-16)以前只支持 update,但行为相当于现今 insert,总会重新插入文件,无论是否变化。

14.5. 删除归档内容

删除参数匹配的文件与目录,受 –glob 影响。模式或名称没有匹配项时报错。

14.6. ZIP 归档操作

FILE 是 ZIP 而非 SQLite Archive 时,.archive 与 -A 仍可使用,由 zipfile 扩展实现。以下命令大致等价,只是输出格式不同:

传统命令 sqlite3.exe 等价命令
unzip archive.zip sqlite3 -Axf archive.zip
unzip -l archive.zip sqlite3 -Atvf archive.zip
zip -r archive2.zip dir sqlite3 -Acf archive2.zip dir

14.7. 实现归档操作的 SQL

各种归档命令由 SQL 实现。应用开发者运行相应 SQL,即可添加读写 SQLite Archive 的支持。

加入 –dryrun 或 -n,显示实现归档操作的 SQL,但不执行。

相关 SQL 使用若干可加载扩展,均位于 SQLite 源码树 ext/misc 子目录。完整归档支持需要:

1. **fileio.c:**添加 readfile()、writefile() 读写文件;fsdir() 表值函数列出目录;lsmode() 将 stat 的数字 st_mode 转为类似 ls -l 的可读格式。

2. **sqlar.c:**添加 sqlar_compress()、sqlar_uncompress(),在插入和提取归档时压缩与解压内容。

3. **zipfile.c:**实现 zipfile(FILE) 表值函数,读取 ZIP。仅读取 ZIP 而非 SQLite Archive 时需要。

4. **appendvfs.c:**实现新 VFS,可把数据库附加到其他文件(如可执行文件)后。仅 .archive 使用 –append 时需要。

15. SQL 参数

SQL 语句中任何允许字面值的位置都可使用绑定参数,由 sqlite3_bind_...() API 设置其值。

参数可以有名或无名。无名参数是单个 ?;有名参数是 ? 紧跟数字,例如 ?15、?123,或 $、:、@ 紧跟字母数字名称,例如 $var1、:xyz、@bingo。

CLI 不绑定无名参数,因此它们为 SQL NULL。有名参数则可赋值:如果存在如下 TEMP 表 sqlite_parameters:

CREATE TEMP TABLE sqlite_parameters(
  key TEXT PRIMARY KEY,
  value
) WITHOUT ROWID;

若表中 key 与参数名完全相同,包括 ?、$、:、@ 前缀,参数取 value 列的值。找不到记录则为 NULL。

.parameter 简化表管理。.parameter init(常缩为 .param init)按需创建 temp.sqlite_parameters;list 列出全部记录;clear 删除表;set KEY VALUE 和 unset KEY 创建或删除记录。

set 的 VALUE 可以是 SQL 字面量、表达式或可求值查询,因此支持不同类型。求值失败时会加引号并作为文本插入。能否求值取决于内容,可靠设置文本值的方法是使用单引号,再保护这些引号不被前述命令尾部解析器处理。

例如,除非想得到 -1365:

.parameter init
.parameter set @phoneNumber "'202-456-1111'"

双引号保护内部单引号,确保整个文本作为一个参数解析。

temp.sqlite_parameters 仅向 CLI 提供参数值,不影响直接通过 SQLite C API 执行的查询。应用需自行实现绑定。可在 CLI 源码搜索 sqlite_parameters,参考其实现。

16. 索引建议(SQLite Expert)

注意:该命令是实验功能,未来可能删除或不兼容地修改接口。

对多数非平凡数据库,性能关键在于正确索引,即能加速应用需要优化的查询的索引。.expert 可建议哪些索引有助于特定查询。

先输入 .expert,再在另一行输入查询。例如:

sqlite> CREATE TABLE x1(a, b, c);                  -- Create table in database
sqlite> .expert
sqlite> SELECT * FROM x1 WHERE a=? AND b>?;        -- Analyze this SELECT
CREATE INDEX x1_idx_000123a7 ON x1(a, b);

0|0|0|SEARCH TABLE x1 USING INDEX x1_idx_000123a7 (a=? AND b>?)
sqlite> CREATE INDEX x1ab ON x1(a, b);             -- Create the recommended index
sqlite> .expert
sqlite> SELECT * FROM x1 WHERE a=? AND b>?;        -- Re-analyze the same SELECT
(no new indexes)

0|0|0|SEARCH TABLE x1 USING INDEX x1ab (a=? AND b>?)

上例先创建 x1 表,再用 expert 分析 SELECT * FROM x1 WHERE a=? AND b>?。工具建议创建 x1_idx_000123a7,并以 EXPLAIN QUERY PLAN 格式显示预期计划。用户建立等价索引后再次分析。

此时不再建议新索引,而是展示使用现有索引的计划。

expert 接受以下选项:

选项 用途
–verbose 对每个查询输出更详细报告。
–sample PERCENT 默认 0,仅依据查询与结构推荐索引,类似未运行 ANALYZE 时的规划器。

非零时根据每张表现有行的 PERCENT 百分比样本,为所有考虑的索引生成分布统计。数据分布特殊时可能改善建议,尤其是应用会运行 ANALYZE 的情况。对于小数据库和现代 CPU,通常没有理由不用 –sample 100。

大表采集分布统计可能耗时。太慢时降低 sample 参数。

此功能可通过 SQLite expert 扩展代码集成到其他应用。

数据库结构使用扩展提供的自定义函数时,expert 可能需要额外配置。它使用额外连接,因此这些连接也必须获得函数;详见自动加载静态链接扩展及持久可加载扩展。

17. 多数据库连接

从 3.37.0(2021-11-27)开始,CLI 能同时保持多个连接,任一时刻只有一个活动,其余打开但空闲。

用 .connection(常缩为 .conn)列出连接与活动标记。连接编号 0 至 9,最多同时十个。输入 .conn 加编号切换;不存在时创建。

.conn close N 关闭编号 N 的连接。

底层连接独立,但输出格式等许多 CLI 设置共享,所以一个连接改变输出模式会影响全部连接。.open 等点命令则只影响当前连接。

18. 其他扩展功能

CLI 包含若干库本身没有的扩展,下列功能前文未介绍:

– UINT 排序规则:对文本内的无符号整数按数值排序,并结合其他文本。

– decimal 扩展提供十进制运算。

– generate_series() 表值函数。

– base64()、base85():BLOB 与对应文本格式的双向转换。

– REGEXP 运算符绑定的 POSIX 扩展正则表达式支持。

19. 其他点命令

还有许多点命令,可用 .help 查看特定版本和构建的完整列表。

20. 在 shell 脚本中使用 sqlite3

一种方式是用 echo 或 cat 生成命令文件,再将其重定向给 sqlite3。这适合许多场景。为方便使用,sqlite3 还允许在数据库名后的第二个参数中传入一条 SQL。

带两个参数启动时,第二个参数交给 SQLite 库处理,结果以 list 模式写入标准输出,然后退出,便于结合 awk 等程序。例如:

$ sqlite3 ex1 'select * from tbl1' \
>  | awk '{printf "<tr><td>%s<td>%s\n",$1,$2 }'
<tr><td>hello<td>10
<tr><td>goodbye<td>20
$

21. 标记 SQL 语句结束

SQLite 通常以分号结束命令。CLI 也接受单独一行的 GO(不区分大小写)或 /,分别兼容 SQL Server 和 Oracle。这些不能直接用于 sqlite3_exec(),因为 CLI 会先转换为分号再传给核心。

22. CLI 启动的更多细节

通常输入 sqlite3 后跟数据库文件名,但程序还接受许多其他参数。

22.1. 额外命令行参数

数据库名之后的参数视为输入行,每个可以是 SQL 或点命令,从左至右执行。因为常含空格,通常要用单引号或双引号包住,取决于操作系统。例如:

$ sqlite3 test.db   ".mode box"   "SELECT * FROM users;"

这样传入额外参数时,不读取标准输入,全部处理完后退出。

22.2. 命令行选项

以 – 开头的额外参数是命令行选项。用 –help 查看清单:

$ sqlite3 --help
FILENAME is the name of an SQLite database. A new database is created
if the file does not previously exist. Defaults to :memory:.
OPTIONS include:
   --                   treat no subsequent arguments as options
   -A ARGS...           run ".archive ARGS" and exit
   -append              append the database to the end of the file
   -ascii               set output mode to 'ascii'
   -bail                stop after hitting an error
   -batch               force batch I/O
   -box                 set output mode to 'box'
   -column              set output mode to 'column'
   -cmd COMMAND         run "COMMAND" before reading stdin
   -csv                 set output mode to 'csv'
   -deserialize         open the database using sqlite3_deserialize()
   -echo                print inputs before execution
   -escape T            ctrl-char escape; T is one of: symbol, ascii, off
   -init FILENAME       read/process named file
   -[no]header          turn headers on or off
   -heap SIZE           Size of heap for memsys3 or memsys5
   -help                show this message
   -html                set output mode to HTML
   -ifexists            only open if database already exists
   -interactive         force interactive I/O
   -json                set output mode to 'json'
   -line                set output mode to 'line'
   -list                set output mode to 'list'
   -lookaside SIZE N    use N entries of SZ bytes for lookaside memory
   -markdown            set output mode to 'markdown'
   -maxsize N           maximum size for a --deserialize database
   -memtrace            trace all memory allocations and deallocations
   -mmap N              default mmap size set to N
   -newline SEP         set output row separator. Default: '\n'
   -nofollow            refuse to open symbolic links to database files
   -nonce STRING        set the safe-mode escape nonce
   -no-rowid-in-view    Disable rowid-in-view using sqlite3_config()
   -nullvalue TEXT      set text string for NULL values. Default ''
   -pagecache SIZE N    use N slots of SZ bytes each for page cache memory
   -pcachetrace         trace all page cache operations
   -quote               set output mode to 'quote'
   -readonly            open the database read-only
   -safe                enable safe-mode
   -separator SEP       set output column separator. Default: '|'
   -stats               print memory stats before each finalize
   -table               set output mode to 'table'
   -tabs                set output mode to 'tabs'
   -unsafe-testing      allow unsafe commands and modes for testing
   -version             show SQLite version
   -vfs NAME            use NAME as the default VFS
   -vfstrace            enable tracing of all VFS calls
   -zip                 open the file as a ZIP Archive

选项格式允许一个或两个前导减号,例如 -box 与 –box 相同。选项从左至右处理,因此后面的 –box 会覆盖前面的 –quote。

多数选项含义明显,以下补充介绍几个。

22.3. --safe 选项

–safe 尝试禁用所有可能对命令行指定数据库文件以外的宿主机内容作出更改的功能。收到未知或不可信来源的大型 SQL 脚本时,可用它查看脚本行为,降低遭受利用的风险。它禁用的功能包括:

– .open,除非使用 –hexdb 或文件名为 :memory:,防止访问最初参数以外的数据库。

– ATTACH SQL 命令。

– 有潜在有害副作用的 SQL 函数,如 edit()、fts3_tokenizer()、load_extension()、readfile()、writefile()。

– .archive。

– .backup、.save。

– .import。

– .load。

– .log。

– .shell、.system。

– .excel、.once、.output。

– 其他可能产生有害副作用的命令。

基本上,所有读取或写入主数据库以外磁盘文件的功能都被禁用。

22.3.1. 为指定命令解除 safe 限制

如果启动时还指定 --nonce NONCE,其中 NONCE 为足够长且任意的字符串,则相同值的 .nonce NONCE 允许下一条 SQL 或点命令绕过 safe 限制。

例如可疑脚本确需 ATTACH 一个额外数据库,或加载某个扩展,可以在经过仔细审查的 ATTACH 或 .load 前加入适当 .nonce,启动时通过 –nonce 提供相同值。

这些特定命令随后可正常执行,其余不安全命令仍受限。

误用 nonce 可能使恶意脚本破坏系统,因此应谨慎、少量使用,只有没有其他 safe 运行办法时才采用。

22.4. --unsafe-testing 选项

该选项只启用内部测试功能,禁用内置防护,例如 SQLITE_DBCONFIG_DEFENSIVE、SQLITE_DBCONFIG_TRUSTED_SCHEMA。误用这些功能可能造成数据库损坏、内存错误或 CLI、库的其他问题。

例如 .testctrl assert false 会故意触发断言失败,验证断言机制。

必须使用 –unsafe-testing 才能触发的异常行为,通常不被视为缺陷。

22.5. --no-utf8 与 --utf8 选项

Windows 控制台输入输出需要在控制台字符编码与 CLI 内部 UTF-8 之间转换。旧版的这两个选项用于启用或禁用依赖 Windows 控制台功能的转换方式,使较新的系统能够处理 UTF-8。

现行 CLI(3.44.1 及以后)通过 Windows 控制台 API 读写 UTF-16,甚至可正确支持 Windows 2000,因此已不需要这两个选项。仍接受它们,但不起作用。

所有非控制台文本 I/O 都使用 UTF-8。

非 Windows 平台也忽略这两个选项。

23. 从源码编译 sqlite3

Unix 和使用 MinGW 的 Windows 可以使用通常的 configure-make:

sh configure; make

无论使用源码树的规范源码,还是 amalgamation 合并源码包,configure-make 都适用,依赖较少。规范源码构建需要可用的 tclsh;合并包已经完成通常由 tclsh 执行的预处理,只需常规构建工具。

归档命令需要可用的 zlib 压缩库。

Windows 使用 MSVC 时,通过 Makefile.msc 调用 nmake:

nmake /f Makefile.msc

要使归档命令正常工作,把 zlib 源码复制到源码树 compat/zlib 子目录,再这样编译:

nmake /f Makefile.msc USE_ZLIB=1

23.1. 自行构建

命令行接口源码集中在 shell.c,由其他源码生成。大部分原始代码位于 src/shell.c.in;在规范源码树运行 make shell.c 可重新生成。把 shell.c 与 SQLite 库源码一起编译即可生成程序,例如:

gcc -o sqlite3 shell.c sqlite3.c -ldl -lpthread -lz -lm

推荐加入以下编译选项,以获得完整功能:

* -DSQLITE_THREADSAFE=0

* -DSQLITE_ENABLE_EXPLAIN_COMMENTS

* -DSQLITE_HAVE_ZLIB

* -DSQLITE_INTROSPECTION_PRAGMAS

* -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION

* -DSQLITE_ENABLE_STMTVTAB

* -DSQLITE_ENABLE_DBPAGE_VTAB

* -DSQLITE_ENABLE_DBSTAT_VTAB

* -DSQLITE_ENABLE_OFFSET_SQL_FUNC

* -DSQLITE_ENABLE_JSON1

* -DSQLITE_ENABLE_RTREE

* -DSQLITE_ENABLE_FTS4

* -DSQLITE_ENABLE_FTS5

本页最后更新于 2026-08-14 19:21:30 UTC。

—

原文:Command Line Shell For SQLite。作者:SQLite 项目贡献者。SQLite 代码与文档属于公有领域。本文为中文翻译,保留原文的版本信息与示例。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容