SQLite 的命令行 Shell

1.开始

SQLite 项目提供了一个名为sqlite3(或Windows 上的sqlite3.exe )的简单命令行程序 ,允许用户针对 SQLite 数据库或 ZIP 存档手动输入和执行 SQL 语句。本文档简要介绍如何使用sqlite3程序。

通过在命令提示符下键入“sqlite3”来启动sqlite3程序,可以选择后跟保存 SQLite 数据库(或ZIP 存档)的文件的名称。如果命名文件不存在,将自动创建一个具有给定名称的新数据库文件。如果在命令行中没有指定数据库文件,则会创建一个临时数据库,并在“sqlite3”程序退出时自动删除。

启动时,sqlite3程序会显示一条简短的横幅消息,然后提示您输入 SQL。输入 SQL 语句(以分号结尾),按“Enter”键,SQL 将被执行。

例如,要使用名为“tbl1”的单个表创建一个名为“ex1”的新 SQLite 数据库,您可以这样做:

$ sqlite3 ex1
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);
sqlite> insert into tbl1 values('goodbye', 20);
sqlite> select * from tbl1;
hello!|10
goodbye|20
sqlite>

通过键入系统文件结束字符(通常是 Control-D)来终止 sqlite3 程序。使用中断字符(通常是 Control-C)来停止长时间运行的 SQL 语句。

请确保在每个 SQL 命令的末尾键入一个分号!sqlite3 程序查找分号以了解您的 SQL 命令何时完成。如果省略分号,sqlite3 会给你一个继续提示,等待你输入更多的文本来完成 SQL 命令。此功能允许您输入跨越多行的 SQL 命令。例如:

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

2.双击 Windows 上的启动

Windows 用户可以双击sqlite3.exe图标,使命令行 shell 弹出运行 SQLite 的终端窗口。但是,因为双击启动的 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”的数据库文件。如果以前不存在“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”命令一样,您可能希望使用带正斜杠目录分隔符的完整路径名以避免歧义。

3. sqlite3 的特殊命令(点命令)

大多数时候,sqlite3 只是读取输入行并将它们传递给 SQLite 库以供执行。但是以点 (.) 开头的输入行会被 sqlite3 程序本身拦截和解释。这些“点命令”通常用于更改查询的输出格式,或执行某些预先打包的查询语句。最初只有几个点命令,但多年来积累了许多新功能,因此今天有 60 多个。

要获得可用点命令的列表,您可以输入不带参数的“.help”。或输入“.help TOPIC”获取有关TOPIC的详细信息。可用的点命令列表如下:

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
.binary on|off           Turn binary output on or off.  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
.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
.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
.headers on|off          Turn display of headers on or off
.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
.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|off            Turn logging on or off.  FILE can be stderr/stdout
.mode MODE ?TABLE?       Set output mode
.nonce STRING            Disable safe mode for one command if the 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                    Exit this program
.read FILE               Read input from FILE
.recover                 Recover as much data as possible from corrupt db.
.restore ?DB? FILE       Restore content of DB (default "main") from FILE
.save FILE               Write in-memory database into FILE
.scanstats on|off        Turn sqlite3_stmt_scanstatus() metrics on or off
.schema ?PATTERN?        Show the CREATE statements matching PATTERN
.selftest ?OPTIONS?      Run tests defined in the SELFTEST table
.separator COL ?ROW?     Change the column and row separators
.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
.show                    Show the current values for various settings
.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
.testcase NAME           Begin redirecting output to 'testcase-out.txt'
.testctrl CMD ...        Run various sqlite3_test_control() operations
.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
.vfsinfo ?AUX?           Information about the top-level VFS
.vfslist                 List all available VFSes
.vfsname ?AUX?           Print the name of the VFS stack
.width NUM1 NUM2 ...     Set minimum column widths for columnar output
sqlite>

4. “点命令”、SQL 等规则

4.1. 线路结构

CLI 的输入被解析为一个序列,包括:

  • SQL语句;
  • 点命令;或者
  • CLI 评论

SQL 语句是自由形式的,可以分布在多行中,可以在任何地方嵌入空格或 SQL 注释。它们以“;”结尾 输入行末尾的字符,或单独一行的“/”字符或单词“go”。当不在输入行的末尾时,';' 字符用于分隔 SQL 语句。出于终止目的,忽略尾随空格。

点命令具有更严格的结构:

  • 它必须以“.”开头。在左边距,前面没有空格。
  • 它必须完全包含在单个输入行中。
  • 它不能出现在普通 SQL 语句的中间。换句话说,它不能出现在继续提示中。
  • 点命令没有注释语法。

CLI 还接受以“#”字符开头并延伸到行尾的整行注释。在“#”之前不能有空格。

4.2. 点命令参数

根据以下规则,传递给点命令的参数从命令尾部解析:

  1. 丢弃尾随换行符和任何其他尾随空格;
  2. 紧跟在点命令名称之后的空格,或任何参数输入结束边界被丢弃;
  3. 参数输入以任何非空白字符开头;
  4. 一个参数输入以一个字符结尾,这个字符依赖于它的前导字符:
    • 对于前导单引号 ('),单引号充当结束分隔符;
    • 对于前导双引号 ("),未转义的双引号充当结束定界符;
    • 对于任何其他前导字符,结束定界符是任何空格;
    • 命令 tail end 充当任何参数的结束定界符;
  5. 在双引号参数输入中,反斜杠转义的双引号是参数的一部分,而不是其终止引号;
  6. 在双引号参数中,完成了传统的 C 字符串文字、反斜杠转义序列转换;
  7. 参数输入定界符(边界引号或空格)被丢弃以产生传递的参数。

4.3. 点命令执行

点命令由 sqlite3.exe 命令行程序解释,而不是由 SQLite 本身解释。因此,没有一个点命令可以作为 SQLite 接口(例如sqlite3_prepare()sqlite3_exec() )的参数。

5.改变输出格式

sqlite3 程序能够以 14 种不同的输出格式显示查询结果:

  • ascii
  • box
  • csv
  • column
  • html
  • insert
  • json
  • line
  • list
  • markdown
  • quote
  • table
  • tabs
  • tcl

您可以使用“.mode”点命令在这些输出格式之间切换。默认输出模式是“列表”。在列表模式下,查询结果的每一行都写在输出的一行上,并且该行中的每一列都由特定的分隔符字符串分隔。默认分隔符是管道符号(“|”)。当您要将查询的输出发送到另一个程序(例如 AWK)以进行额外处理时,列表模式特别有用。

sqlite> .mode list
sqlite> select * from tbl1;
hello!|10
goodbye|20
sqlite>

键入不带参数的“.mode”以显示当前模式:

sqlite> .mode
current output mode: list
sqlite>

使用“.separator”点命令更改分隔符。例如,要将分隔符更改为逗号和空格,您可以这样做:

sqlite> .separator ", "
sqlite> select * from tbl1;
hello!, 10
goodbye, 20
sqlite>

下一个“.mode”命令可能会将“.separator”重置为某个默认值(取决于它的参数)。因此,如果您想继续使用非标准分隔符,则无论何时更改模式,您都可能需要重复“.separator”命令。

在“引用”模式下,输出被格式化为 SQL 文字。字符串用单引号括起来,内部单引号通过加倍转义。Blob 以十六进制 blob 文字表示法显示(例如:x'abcd')。数字显示为 ASCII 文本,NULL 值显示为“NULL”。所有列都用逗号(或使用“.separator”选择的任何替代字符)彼此分隔。

sqlite> .mode quote
sqlite> select * from tbl1;
'hello!',10
'goodbye',20
sqlite>

在“行”模式下,数据库一行中的每一列都单独显示在一行中。每行由列名、等号和列数据组成。连续的记录由空行分隔。这是行模式输出的示例:

sqlite> .mode line
sqlite> select * from tbl1;
one = hello!
two = 10

one = goodbye
two = 20
sqlite>

在列模式下,每条记录显示在单独的行中,数据按列对齐。例如:

sqlite> .mode column
sqlite> select * from tbl1;
one       two       
--------  ---
hello!    10        
goodbye   20        
sqlite>

在“列”模式(以及“框”、“表格”和“降价”模式)中,列的宽度会自动调整。但是您可以覆盖它,使用“.width”命令为每列提供指定的宽度。".width" 的参数是整数,表示每列的字符数。负数表示右对齐。因此:

sqlite> .width 12 -6
sqlite> select * from tbl1;
one              two
------------  ------
hello!            10
goodbye           20
sqlite>

宽度为 0 表示自动选择列宽。未指定的列宽变为零。因此,不带参数的命令“.width”会将所有列宽重置为零,从而导致自动确定所有列宽。

“列”模式是一种表格输出格式。其他表格输出格式是“box”、“markdown”和“table”:

sqlite> .width
sqlite> .mode markdown
sqlite> select * from tbl1;
|   one   | two |
|---------|-----|
| hello!  | 10  |
| goodbye | 20  |
sqlite> .mode table
sqlite> select * from tbl1;
+---------+-----+
|   one   | two |
+---------+-----+
| hello!  | 10  |
| goodbye | 20  |
+---------+-----+
sqlite> .mode box
sqlite> select * from tbl1;
┌─────────┬─────┐
│   one   │ two │
├─────────┼─────┤
│ hello!  │ 10  │
│ goodbye │ 20  │
└─────────┴─────┘
sqlite>

柱状模式接受一些附加选项来控制格式。“--wrap N ”选项(其中N是一个整数)会导致列将长度超过 N 个字符的文本换行。如果 N 为零,则禁用环绕。

sqlite> insert into tbl1 values('The quick fox jumps over a lazy brown dog.',99);
sqlite> .mode box --wrap 30
sqlite> select * from tbl1 where two>50;
┌────────────────────────────────┬─────┐
│              one               │ two │
├────────────────────────────────┼─────┤
│ The quick fox jumps over a laz │ 90  │
│ y brown dog.                   │     │
└────────────────────────────────┴─────┘
sqlite>

换行恰好发生在N个字符之后,这些字符可能位于单词的中间。要在单词边界换行,请添加“--wordwrap on”选项(或简称为“-ww”):

sqlite> .mode box --wrap 30 -ww
sqlite> select * from tbl1 where two>50;
┌─────────────────────────────┬─────┐
│             one             │ two │
├─────────────────────────────┼─────┤
│ The quick fox jumps over a  │ 90  │
│ lazy brown dog.             │     │
└─────────────────────────────┴─────┘
sqlite>

"--quote" 选项导致每列中的结果像 SQL 文字一样被引用,就像在 "quote" 模式中一样。有关其他选项,请参阅联机帮助。

命令“.mode box --wrap 60 --quote”对于通用数据库查询非常有用,它被赋予了自己的别名。您无需输入整个 27 个字符的命令,只需说“.mode qbox”即可。

另一种有用的输出模式是“插入”。在插入模式下,输出的格式看起来像 SQL INSERT 语句。使用插入模式生成稍后可用于将数据输入到不同数据库中的文本。

指定插入模式时,您必须提供一个额外的参数,即要插入的表的名称。例如:

sqlite> .mode insert new_table
sqlite> select * from tbl1 where two<50;
INSERT INTO "new_table" VALUES('hello',10);
INSERT INTO "new_table" VALUES('goodbye',20);
sqlite>

其他输出模式包括“csv”、“json”和“tcl”。自己尝试一下,看看它们的作用。

6.查询数据库模式

sqlite3 程序提供了几个方便的命令,可用于查看数据库的模式。这些命令所做的一切都是通过其他方式无法完成的。这些命令纯粹作为快捷方式提供。

例如,要查看数据库中表的列表,您可以输入“.tables”。

sqlite> .tables
tbl1 tbl2
sqlite>

“.tables”命令类似于设置列表模式然后执行以下查询:

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

但是“.tables”命令做的更多。它查询所有附加数据库的sqlite_schema,而不仅仅是主数据库。并将其输出排列成整齐的列。

“.indexes”命令以类似的方式工作以列出所有索引。如果给“.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”命令与设置列表模式大致相同,然后输入以下查询:

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

与“.tables”一样,“.schema”命令显示所有附加数据库的模式。如果您只想查看单个数据库(可能是“main”)的模式,那么您可以向“.schema”添加一个参数来限制其输出:

sqlite> .schema main.*

“.schema”命令可以使用“--indent”选项进行扩充,在这种情况下,它会尝试重新格式化模式的各种 CREATE 语句,以便它们更容易被人类阅读。

“.databases”命令显示当前连接中打开的所有数据库的列表。总会有至少 2 个。第一个是“main”,打开的原始数据库。第二个是“temp”,用于临时表的数据库。对于使用 ATTACH 语句附加的数据库,可能会列出其他数据库。第一个输出列是数据库附加的名称,第二个结果列是外部文件的文件名。可能会有第三个结果列,它是“'r/o'”或“'r/w'”,具体取决于数据库文件是只读的还是读写的。并且可能有第四个结果列显示该 数据库文件 的sqlite3_txn_state()结果。

sqlite> .databases

“.fullschema”点命令与“.schema”命令类似,因为它显示整个数据库模式。但是“.fullschema”还包括统计表“sqlite_stat1”、“sqlite_stat3”和“sqlite_stat4”的转储,如果它们存在的话。“.fullschema”命令通常提供为特定查询准确地重新创建查询计划所需的所有信息。当向 SQLite 开发团队报告 SQLite 查询规划器的可疑问题时,要求开发人员提供完整的“.fullschema”输出作为故障报告的一部分。请注意,sqlite_stat3 和 sqlite_stat4 表包含索引条目的样本,因此可能包含敏感数据,因此不要发送“.fullschema”

7.打开数据库文件

“.open”命令在首先关闭先前打开的数据库命令后打开一个新的数据库连接。在其最简单的形式中,“.open”命令仅在作为其参数命名的文件上调用sqlite3_open()使用名称“:memory:”打开一个新的内存数据库,该数据库在 CLI 退出或再次运行“.open”命令时消失。

如果 --new 选项包含在“.open”中,则数据库在打开之前被重置。任何先前的数据都会被销毁。这是对先前数据的破坏性覆盖,不需要确认,因此请谨慎使用此选项。

--readonly 选项以只读模式打开数据库。写入将被禁止。

--deserialize 选项导致磁盘文件的全部内容被读入内存,然后使用 sqlite3_deserialize()接口作为内存数据库打开。当然,如果您有一个大型数据库,这将需要大量内存。此外,您对数据库所做的任何更改都不会保存回磁盘,除非您使用“.save”或“.backup”命令明确保存它们。

--append 选项使 SQLite 数据库附加到现有文件而不是作为独立文件工作。有关详细信息,请参阅 appendvfs 扩展

--zip 选项使指定的输入文件被解释为 ZIP 存档而不是 SQLite 数据库文件。

--hexdb 选项导致数据库内容以十六进制格式从后续输入行读取,而不是从磁盘上的单独文件读取。“dbtotxt”命令行工具可用于为数据库生成适当的文本。--hexdb 选项旨在供 SQLite 开发人员用于测试目的。除了内部 SQLite 测试和开发之外,我们不知道此选项的任何用例。

8.重定向 I/O

8.1. 将结果写入文件

默认情况下,sqlite3 将查询结果发送到标准输出。您可以使用“.output”和“.once”命令更改它。只需将输出文件的名称作为 .output 的参数,所有后续查询结果都将写入该文件。或者使用 .once 命令而不是 .output 并且在恢复到控制台之前,输出只会被重定向到下一个命令。使用不带参数的 .output 再次开始写入标准输出。例如:

sqlite> .mode list
sqlite> .separator |
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;

如果“.output”或“.once”命令有一个参数“-e”,那么输出会被收集到一个临时文件中,系统文本编辑器会在该文本文件上调用。因此,命令“.once -e”实现与“.once '|open -f'”相同的结果,但具有跨所有系统可移植的优势。

如果“.output”或“.once”命令有一个“-x”参数,这会导致它们在临时文件中以逗号分隔值 (CSV) 的形式累积输出,然后调用默认系统实用程序来查看 CSV 文件(通常是电子表格程序)在结果上。这是将查询结果发送到电子表格以便于查看的快速方法:

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

“.excel”命令是“.once -x”的别名。它做完全一样的事情。

8.2. 从文件中读取 SQL

在交互模式下,sqlite3从键盘读取输入文本(SQL 语句或点命令)。当然,您也可以在启动 sqlite3 时重定向来自文件的输入,但是您无法与该程序交互。有时从命令行输入其他命令来运行包含在文件中的 SQL 脚本很有用。为此,提供了“.read”点命令。

“.read”命令采用单个参数,该参数(通常)是要从中读取输入文本的文件的名称。

sqlite> .read myscript.sql

“.read”命令暂时停止从键盘读取,而是从名为的文件中获取输入。到达文件末尾后,输入恢复为键盘。脚本文件可能包含点命令,就像普通的交互式输入一样。

如果“.read”的参数以“|”开头 字符,那么它不会将参数作为文件打开,而是将参数(不带前导“|”)作为命令运行,然后使用该命令的输出作为其输入。因此,如果您有生成 SQL 的脚本,则可以使用类似于以下的命令直接执行该 SQL:

sqlite> .read |myscript.bat

8.3. 文件 I/O 函数

命令行 shell 添加了两个应用程序定义的 SQL 函数,它们分别有助于将文件中的内容读入表列,以及将列的内容写入文件。

readfile(X) SQL 函数读取名为 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) SQL 函数将 blob Y 写入名为 X 的文件并返回写入的字节数。使用此函数将单个表列的内容提取到文件中。例如:

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

请注意,readfile(X) 和 writefile(X,Y) 函数是扩展函数,并未内置到核心 SQLite 库中。这些例程在SQLite 源代码存储库ext/misc/fileio.c 源文件中作为可加载扩展提供。

8.4. edit() SQL 函数

CLI 有另一个名为 edit() 的内置 SQL 函数。Edit() 接受一个或两个参数。第一个参数是一个值——通常是一个要编辑的大的多行字符串。第二个参数是对文本编辑器的调用。(它可能包括影响编辑器行为的选项。)如果省略第二个参数,则使用 VISUAL 环境变量。edit() 函数将其第一个参数写入临时文件,在临时文件上调用编辑器,在编辑器完成后将文件重新读回内存,然后返回编辑后的文本。

edit() 函数可用于更改大文本值。例如:

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

在此示例中,docs.name 为“report-15”的条目的 docs.body 字段的内容将发送给编辑器。编辑器返回后,将结果写回 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';

8.5. 将文件导入为 CSV 或其他格式

使用“.import”命令将 CSV(逗号分隔值)或类似分隔的数据导入到 SQLite 表中。“.import”命令有两个参数,一个是要从中读取数据的源,另一个是要插入数据的 SQLite 表的名称。source 参数是要读取的文件的名称,或者如果它以“|”开头 字符,它指定将运行以生成输入数据的命令。

请注意,在运行“.import”命令之前设置“模式”可能很重要。这是为了防止命令行 shell 尝试将输入文件文本解释为某种格式而不是文件的结构。如果使用 --csv 或 --ascii 选项,它们控制导入输入分隔符。否则,定界符是对当前输出模式有效的定界符。

要导入不在“主”模式中的表,可以使用 --schema 选项指定该表在其他模式中。这对于 ATTACH 数据库或导入 TEMP 表很有用。

运行 .import 时,它对第一个输入行的处理取决于目标表是否已经存在。如果不存在,则自动创建表,并使用第一个输入行的内容设置表中所有列的名称。在这种情况下,表格数据内容取自第二个和后续输入行。如果目标表已经存在,则输入的每一行(包括第一行)都被视为实际数据内容。如果输入文件包含列标签的初始行,您可以使用“--skip 1”选项使 .import 命令跳过该初始行。

这是一个示例用法,从 CSV 文件加载预先存在的临时表,该文件的第一行有列名:

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

8.6. 导出为 CSV

要将 SQLite 表(或表的一部分)导出为 CSV,只需将“模式”设置为“csv”,然后运行查询以提取表中所需的行。

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

在上面的示例中,“.headers on”行导致列标签打印为输出的第一行。这意味着生成的 CSV 文件的第一行将包含列标签。如果不需要列标签,请改为设置“.headers off”。(“.headers off”设置是默认设置,如果之前未打开标题,则可以省略。)

“.once FILENAME ”行导致所有查询输出进入命名文件而不是打印在控制台上。在上面的示例中,该行导致将 CSV 内容写入名为“C:/work/dataout.csv”的文件中。

该示例的最后一行(“.system c:/work/dataout.csv”)与在 Windows 中双击 c:/work/dataout.csv 文件具有相同的效果。这通常会调出一个电子表格程序来显示 CSV 文件。

该命令仅适用于在 Windows 上编写的内容。Mac 上的等效行是:

sqlite> .system open dataout.csv

在 Linux 和其他 unix 系统上,您需要输入如下内容:

sqlite> .system xdg-open dataout.csv

8.6.1. 导出到 Excel

为了简化电子表格的导出,CLI 提供了“.excel”命令,它捕获单个查询的输出并将该输出发送到主机上的默认电子表格程序。像这样使用它:

sqlite> .excel
sqlite> SELECT * FROM tab;

上面的命令将查询的输出作为 CSV 写入临时文件,调用 CSV 文件的默认处理程序(通常是首选的电子表格程序,如 Excel 或 LibreOffice),然后删除临时文件。这本质上是一种执行上述“.csv”、“.once”和“.system”命令序列的速记方法。

“.excel”命令实际上是“.once -x”的别名。.once 的 -x 选项导致它将结果作为 CSV 写入一个以“.csv”后缀命名的临时文件,然后调用 CSV 文件的系统默认处理程序。

还有一个“.once -e”命令,其工作方式类似,只是它用“.txt”后缀命名临时文件,以便调用系统的默认文本编辑器,而不是默认电子表格。

9.将 ZIP 存档作为数据库文件访问

除了读写 SQLite 数据库文件外,sqlite3程序还将读写 ZIP 档案。只需在初始命令行或“.open”命令中指定 ZIP 存档文件名代替 SQLite 数据库文件名,sqlite3将自动检测该文件是 ZIP 存档而不是 SQLite 数据库并将其打开为这样的。无论文件后缀如何,这都有效。所以你可以打开 JAR、DOCX 和 ODP 文件以及任何其他真正是 ZIP 存档的文件格式,SQLite 会为你读取它。

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
);

因此,例如,如果您想查看 ZIP 存档中所有文件的压缩效率(表示为压缩内容相对于原始未压缩文件大小的大小),从压缩程度最高到压缩程度最低,您可以运行像这样查询:

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

或者使用文件 I/O 函数,您可以提取 ZIP 存档的元素:

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

9.1. ZIP 存档访问是如何实现的

命令行 shell 使用Zipfile 虚拟表来访问 ZIP 档案。当 ZIP 存档打开时,您可以通过运行“.schema”命令来查看:

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

打开文件时,如果命令行客户端发现该文件是 ZIP 存档而不是 SQLite 数据库,它实际上会打开一个内存数据库,然后在该内存数据库中创建Zipfile 虚拟表的实例附在 ZIP 存档中。

打开 ZIP 档案的特殊处理是命令行 shell 的技巧,而不是核心 SQLite 库。因此,如果您想在应用程序中将 ZIP 存档作为数据库打开,则需要激活Zipfile 虚拟表模块,然后运行适当的 CREATE VIRTUAL TABLE语句。

10.将整个数据库转换为文本文件

使用“.dump”命令将数据库的全部内容转换为单个 UTF-8 文本文件。这个文件可以通过管道返回到sqlite3来转换回数据库

制作数据库存档副本的一个好方法是:

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

这会生成一个名为ex1.dump.gz的文件,其中包含您稍后或在另一台机器上重建数据库所需的一切。要重建数据库,只需键入:

$ zcat ex1.dump.gz | sqlite3 ex2

文本格式是纯 SQL,因此您还可以使用 .dump 命令将 SQLite 数据库导出到其他流行的 SQL 数据库引擎中。像这样:

$ createdb ex2
$ sqlite3 ex1 .dump | psql ex2

11.从损坏的数据库中恢复数据

与“.dump”命令一样,“.recover”试图将数据库文件的全部内容转换为文本。不同之处在于,“.recover”不是使用普通的 SQL 数据库接口读取数据,而是尝试根据直接从尽可能多的数据库页面中提取的数据重新组装数据库。如果数据库损坏,“.recover”通常能够从数据库所有未损坏的部分恢复数据,而“.dump”在遇到第一个损坏迹象时停止。

如果“.recover”命令恢复了一个或多个不能归因于任何数据库表的行,则输出脚本会创建一个“lost_and_found”表来存储孤立的行。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
);

“lost_and_found”表包含一行,用于从数据库中恢复的每个孤立行。此外,每个恢复的索引条目都有一行不能归因于任何 SQL 索引。这是因为,在 SQLite 数据库中,相同的格式用于存储 SQL 索引条目和 WITHOUT ROWID 表条目。

Column内容
rootpgno尽管可能无法将该行归因于特定的数据库表,但它可能是数据库文件中树结构的一部分。在这种情况下,该树结构的根页码存储在该列中。或者,如果找到该行的页面不是树结构的一部分,则此列存储“pgno”列中值的副本 - 找到该行的页面的页码。在许多情况下(虽然不是全部),lost_and_found 表中此列中具有相同值的所有行都属于同一个表。
pgno找到此行的页面的页码。
nfield此行中的字段数。
id如果该行来自 WITHOUT ROWID 表,则此列包含 NULL。否则,它包含该行的 64 位整数 rowid 值。
c0, c1, c2...该行每一列的值都存储在这些列中。“.recover”命令创建 lost_and_found 表,其中包含最长孤立行所需的列数。

如果恢复的数据库模式已经包含名为“lost_and_found”的表,则“.recover”命令使用名称“lost_and_found0”。如果名称“lost_and_found0”也已被占用,则为“lost_and_found1”,依此类推。默认名称“lost_and_found”可以通过使用 --lost-and-found 开关调用“.recover”来覆盖。例如,要让输出脚本调用表“orphaned_rows”:

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

12.加载扩展

您可以在运行时使用“.load”命令将新的自定义应用程序定义的 SQL 函数整理序列虚拟表VFS 添加到命令行 shell。首先,将扩展构建为 DLL 或共享库(如 运行时可加载扩展文档中所述),然后键入:

sqlite> .load /path/to/my_extension

请注意,SQLite 会自动将适当的扩展后缀(在 Windows 上为“.dll”,在 Mac 上为“.dylib”,在大多数其他 unix 上为“.so”)添加到扩展文件名。指定扩展的完整路径名通常是个好主意。

SQLite 根据扩展文件名计算扩展的入口点。要覆盖此选择,只需将扩展名作为第二个参数添加到“.load”命令。

可以在 SQLite 源代码树的ext/misc子目录中找到几个有用扩展的源代码。您可以按原样使用这些扩展,或作为创建您自己的自定义扩展以满足您自己的特定需求的基础。

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

“.sha3sum”点命令计算 数据库内容的SHA3散列需要明确的是,哈希是根据数据库内容计算的,而不是它在磁盘上的表示。这意味着,例如,VACUUM 或类似的数据保留转换不会更改散列。

“.sha3sum”命令支持选项“--sha3-224”、“--sha3-256”、“--sha3-384”和“--sha3-512”来定义使用哪种 SHA3哈希。默认为 SHA3-256。

数据库模式(在sqlite_schema表中)通常不包含在哈希中,但可以通过“--schema”选项添加。

“.sha3sum”命令采用一个可选参数,它是一个 LIKE模式。如果存在此选项,则仅对名称与LIKE模式匹配的表进行哈希处理。

“.sha3sum”命令是 在命令行 shell 中包含 的扩展函数“sha3_query()”的帮助下实现的。

14.数据库内容自检

“.selftest”命令尝试验证数据库是否完好无损且未损坏。.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
);

.selftest 命令以 selftest.tno 顺序读取 selftest 表的行。对于每个“备忘录”行,它​​将“cmd”中的文本写入输出。对于每个“运行”行,它将“cmd”文本作为 SQL 运行,并将结果与​​“ans”中的值进行比较,如果结果不同,则显示错误消息。

如果没有自测试表,“.selftest”命令运行 PRAGMA integrity_check

“.selftest --init”命令创建自测试表(如果尚不存在),然后附加检查所有表内容的 SHA3 散列的条目。“.selftest”的后续运行将验证数据库没有以任何方式更改。要生成测试以验证表的子集是否未更改,只需运行“.selftest --init”,然后删除引用非常量表的自测试行。

15. SQLite 存档支持

“.archive”点命令和“-A”命令行选项提供对SQLite Archive 格式的内置支持 该界面类似于 unix 系统上的“tar”命令。每次调用“.ar”命令都必须指定一个命令选项。以下命令可用于“.archive”:

OptionLong OptionPurpose
-c--createCreate a new archive containing specified files.
-x--extractExtract specified files from archive.
-i--insertAdd files to existing archive.
-r--removeRemove files from the archive.
-t--listList the files in the archive.
-u--updateAdd files to existing archive if they have changed.

与命令选项一样,每次调用“.ar”都可以指定一个或多个修饰符选项。有些修饰符选项需要参数,有些则不需要。以下修饰符选项可用:

OptionLong OptionPurpose
-v--verboseList each file as it is processed.
-f FILE--file FILEIf specified, use file FILE as the archive. Otherwise, assume that the current "main" database is the archive to be operated on.
-a FILE--append FILELike --file, use file FILE as the archive, but open the file using the apndvfs VFS so that the archive will be appended to the end of FILE if FILE already exists.
-C DIR--directory DIRIf specified, interpret all relative paths as relative to DIR, instead of the current working directory.
-g--globUse glob(Y,X) to match arguments against names in the archive.
-n--dryrunShow the SQL that would be run to carry out the archive operation, but do not actually change anything.
----All subsequent command line words are command arguments, not options.

对于命令行用法,请在“-A”之后立即添加短样式命令行选项,中间不要有空格。所有后续参数都被视为 .archive 命令的一部分。例如,以下命令是等效的:

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

15.1. SQLite 存档创建命令

创建一个新存档,覆盖任何现有存档(在当前“主”数据库中或在 --file 选项指定的文件中)。选项后面的每个参数都是一个要添加到存档中的文件。目录是递归导入的。有关示例,请参见上文。

15.2. SQLite 归档提取命令

从存档中提取文件(到当前工作目录或到 --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

15.3. SQLite 归档列表命令

列出存档的内容。如果未指定参数,则列出所有文件。否则,仅列出那些受 --glob 选项影响的参数匹配的参数。目前,--verbose 选项不会更改此命令的行为。这在未来可能会改变。

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

15.4. SQLite 存档插入和更新命令

--update 和 --insert 命令的工作方式类似于 --create 命令,只是它们在开始之前不会删除当前存档。新版本的文件会自动替换现有的同名文件,但存档的初始内容(如果有)保持不变。

对于 --insert 命令,列出的所有文件都被插入到存档中。对于 --update 命令,仅当文件以前不存在于存档中,或者它们的“mtime”或“mode”与存档中的当前内容不同时,才会插入文件。

兼容性节点:在 SQLite 版本 3.28.0 (2019-04-16) 之前,仅支持 --update 选项,但该选项与 --insert 一样工作,因为它总是重新插入每个文件,无论它是否已更改。

15.5。SQLite 存档删除命令

--remove 命令删除与受 --glob 选项影响的提供的参数(如果有)匹配的文件和目录。提供与存档中任何内容都不匹配的参数是错误的。

15.6. 对 ZIP 档案的操作

如果 FILE 是 ZIP 存档而不是 SQLite 存档,“.archive”命令和“-A”命令行选项仍然有效。这是使用zipfile扩展名完成的。因此,以下命令大致相同,仅输出格式不同:

Traditional CommandEquivalent sqlite3.exe Command
unzip archive.zipsqlite3 -Axf archive.zip
unzip -l archive.zipsqlite3 -Atvf archive.zip
zip -r archive2.zip dirsqlite3 -Acf archive2.zip dir

15.7。SQL 用于实现 SQLite 归档操作

各种 SQLite Archive Archive 命令是使用 SQL 语句实现的。应用程序开发人员可以通过运行适当的 SQL 轻松地为自己的项目添加 SQLite Archive Archive 读写支持。

要查看哪些 SQL 语句用于实现 SQLite 存档操作,请添加 --dryrun 或 -n 选项。这会导致显示 SQL 但禁止执行 SQL。

用于实现 SQLite Archive 操作的 SQL 语句使用了各种可加载的扩展这些扩展都ext/misc/ 子文件夹中的SQLite 源代码树中可用。完整的 SQLite Archive 支持所需的扩展包括:

  1. fileio.c — 此扩展添加了 SQL 函数 readfile() 和 writefile() 以从磁盘上的文件读取和写入内容。fileio.c 扩展还包括用于列出目录内容的 fsdir() 表值函数和用于将来自 stat() 系统调用的数字 st_mode 整数转换为人类可读字符串的 lsmode() 函数ls -l”命令。

  2. sqlar.c — 此扩展添加了 sqlar_compress() 和 sqlar_uncompress() 函数,这些函数在将文件内容插入 SQLite 存档和从中提取时需要这些函数来压缩和解压缩文件内容。

  3. zipfile.c — 此扩展实现了用于读取 ZIP 档案的“zipfile(FILE)”表值函数。只有在读取 ZIP 存档而不是 SQLite 存档时才需要此扩展。

  4. appendvfs.c — 此扩展实现了一个新的VFS,它允许将 SQLite 数据库附加到其他文件,例如可执行文件。仅当使用 .archive 命令的 --append 选项时才需要此扩展。

16.SQL参数

SQLite 允许绑定参数出现在 SQL 语句中任何允许文字值的地方。这些参数的值是使用sqlite3_bind_...()系列 API 设置的。

参数可以是命名的或未命名的。未命名的参数是一个问号(“?”)。命名参数是一个“?” 紧跟数字(例如:“?15”或“?123”)或字符“$”、“:”或“@”之一,后跟字母数字名称(例如:“$var1”、“: xyz", "@bingo").

此命令行 shell 未绑定未命名参数,这意味着它们将具有 SQL NULL 值,但命名参数可能会被分配值。如果存在一个名为“sqlite_parameters”的 TEMP 表,其架构如下:

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

如果该表中有一个条目,其中键列与参数名称(包括初始“?”、“$”、“:”或“@”字符)完全匹配,则为该参数分配值值列。如果不存在条目,则参数默认为 NULL。

“.parameter”命令的存在是为了简化该表的管理。“.parameter init”命令(通常缩写为“.param init”)创建 temp.sqlite_parameters 表(如果它尚不存在)。“.param list”命令显示 temp.sqlite_parameters 表中的所有条目。“.param clear”命令删除 temp.sqlite_parameters 表。“.param set KEY VALUE”和“.param unset KEY”命令创建或删除 temp.sqlite_parameters 表中的条目。

传递给“.param set KEY VALUE”的 VALUE 可以是 SQL 文字或任何其他 SQL 表达式或查询,它们可以被评估以产生一个值。这允许设置不同类型的值。如果此类评估失败,则提供的 VALUE 将被引用并作为文本插入。由于此类初始评估可能会或可能不会失败,具体取决于 VALUE 内容,因此获取文本值的可靠方法是用单引号将其括起来,以防止上述命令尾部解析。例如,(除非有人想要 -1365 的值):

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

请注意,双引号用于保护单引号并确保将引用的文本作为一个参数进行解析。

temp.sqlite_parameters 表仅提供命令行 shell 中的参数值。temp.sqlite_parameter 表对直接使用 SQLite C 语言 API 运行的查询没有影响。各个应用程序应实现自己的参数绑定。您可以在命令行 shell 源代码中搜索“sqlite_parameters” 以查看命令行 shell 如何进行参数绑定,并以此作为如何自己实现它的提示。

17.索引推荐(SQLite专家)

注意:此命令是实验性的。它可能会在将来的某个时候被删除或以不兼容的方式修改接口。

对于大多数重要的 SQL 数据库,性能的关键是创建正确的 SQL 索引。在此上下文中,“正确的 SQL 索引”是指那些导致应用程序需要优化的查询快速运行的索引。“.expert”命令可以通过提出可能有助于特定查询的索引来帮助实现这一点,前提是它们存在于数据库中。

首先发出“.expert”命令,然后在单独的一行上执行 SQL 查询。例如,考虑以下会话:

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>? ”。shell 工具建议用户创建一个新索引(索引“x1_idx_000123a7”)并以EXPLAIN QUERY PLAN格式输出查询将使用的计划。然后用户创建一个具有等效模式的索引,并再次对同一查询运行分析。这次 shell 工具不推荐任何新的索引,并输出 SQLite 将用于给定现有索引的查询的计划。

“.expert”命令接受以下选项:

Option Purpose
‑‑verbose If present, output a more verbose report for each query analyzed.
‑‑sample PERCENT This parameter defaults to 0, causing the ".expert" command to recommend indexes based on the query and database schema alone. This is similar to the way the SQLite query planner selects indexes for queries if the user has not run the ANALYZE command on the database to generate data distribution statistics.
If this option is passed a non-zero argument, the ".expert" command generates similar data distribution statistics for all indexes considered based on PERCENT percent of the rows currently stored in each database table. For databases with unusual data distributions, this may lead to better index recommendations, particularly if the application intends to run ANALYZE.
For small databases and modern CPUs, there is usually no reason not to pass "--sample 100". However, gathering data distribution statistics can be expensive for large database tables. If the operation is too slow, try passing a smaller value for the --sample option.

本节中描述的功能可以使用 SQLite 专家扩展代码集成到其他应用程序或工具中。

包含通过扩展加载机制提供的 SQL 自定义函数的数据库模式可能需要特殊规定才能与 .expert 功能一起使用。由于该功能使用附加连接来实现其功能,因此必须使这些自定义功能对这些附加连接可用。这可以通过 自动加载静态链接扩展 持久可加载扩展中描述的扩展加载/使用选项来完成。

18.使用多个数据库连接

从版本 3.37.0 (2021-11-27) 开始,CLI 能够同时保持多个数据库连接打开。一次只有一个数据库连接处于活动状态。非活动连接仍处于打开状态但处于空闲状态。

使用“.connection”点命令(通常缩写为“.conn”)来查看数据库连接列表以及当前处于活动状态的指示。每个数据库连接由 0 到 9 之间的整数标识。(最多可以同时打开 10 个连接。)更改为另一个数据库连接,如果不存在则创建它,方法是键入“.conn”命令,然后它的号码。通过键入“.conn close N”关闭数据库连接,其中 N 是连接号。

尽管底层 SQLite 数据库连接彼此完全独立,但许多 CLI 设置(例如输出格式)在所有数据库连接之间共享。因此,更改一个连接中的输出模式将更改所有连接中的输出模式。另一方面,一些 点命令,如.open只影响当前连接。

19.其他扩展功能

CLI 是使用 SQLite 库中未包含的多个 SQLite 扩展构建的。前面几节中未描述的一些添加功能,即:

  • UINT 整理序列,根据它们的值处理嵌入文本中的无符号整数,以及其他文本,以便排序;
  • 十进制扩展提供的十进制算术
  • generate_series ()表值函数;
  • 支持绑定到REGEXP运算符的 POSIX 扩展正则表达式。

20.其他点命令

命令行 shell 中还有许多其他可用的点命令。有关任何特定版本和构建的 SQLite 的完整列表,请参阅“.help”命令。

21.在 shell 脚本中使用 sqlite3

在 shell 脚本中使用 sqlite3 的一种方法是使用“echo”或“cat”在文件中生成一系列命令,然后在从生成的命令文件重定向输入的同时调用 sqlite3。这很好用,适用于许多情况。但作为一种额外的便利,sqlite3 允许在命令行上输入单个 SQL 命令作为数据库名称后的第二个参数。当带有两个参数的sqlite3程序启动时,第二个参数被传递给SQLite库进行处理,查询结果以列表方式打印在标准输出上,然后程序退出。这种机制旨在使 sqlite3 易于与“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
$

22.标记 SQL 语句的结束

SQLite 命令通常以分号结束。在 CLI 中,您还可以在一行中单独使用单词“GO”(不区分大小写)或斜杠字符“/”来结束命令。它们分别由 SQL Server 和 Oracle 使用,并且由 SQLite CLI 支持以实现兼容性。这些在sqlite3_exec()中不起作用,因为 CLI 在将这些输入传递到 SQLite 核心之前将它们转换为分号。

23.命令行选项

CLI 有许多可用的命令行选项。使用 --help 命令行选项查看列表:

$ sqlite3 --help
Usage: ./sqlite3 [OPTIONS] FILENAME [SQL]
FILENAME is the name of an SQLite database. A new database is created
if the file does not previously exist.
OPTIONS include:
   -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 commands before execution
   -init FILENAME       read/process named file
   -[no]header          turn headers on or off
   -help                show this message
   -html                set output mode to HTML
   -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
   -nullvalue TEXT      set text string for NULL values. Default ''
   -pagecache SIZE N    use N slots of SZ bytes each for page cache memory
   -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'
   -version             show SQLite version
   -vfs NAME            use NAME as the default VFS
   -zip                 open the file as a ZIP Archive

CLI 在命令行选项格式化方面很灵活。允许使用一个或两个前导“-”字符。因此“-box”和“--box”的意思是一样的。命令行选项从左到右处理。因此,“--box”选项将覆盖先前的“--quote”选项。

大多数命令行选项都是不言自明的,但有一些值得在下面进行额外讨论。

23.1. --safe 命令行选项

--safe 命令行选项试图禁用 CLI 的所有功能,这些功能可能会导致主机发生任何更改,而不是对命令行上指定的特定数据库文件进行更改。这个想法是,如果您从未知或不受信任的来源收到一个大型 SQL 脚本,您可以运行该脚本以查看它的作用,而无需使用 --safe 选项来冒被利用的风险。--safe 选项禁用(除其他外):

  • .open命令,除非使用了 --hexdb 选项或文件名为“:memory:”。这可以防止脚本读取或写入任何未在原始命令行中命名的数据库文件。
  • 附加SQL 命令
  • 具有潜在有害副作用的 SQL 函数,例如 edit()、fts3_tokenizer()、load_extension()、readfile() 和 writefile()。
  • .archive命令
  • .backup 和 .save 命令。
  • .import命令
  • .load命令
  • .log 命令。
  • .shell 和 .system 命令。
  • .excel、.once 和 .output 命令。
  • 其他可能产生有害副作用的命令。

基本上,CLI 的任何从磁盘上的文件而不是主数据库文件读取或写入的功能都被禁用。

23.1.1. 绕过特定命令的 --safe 限制

如果“--nonce NONCE”选项也包含在命令行中,对于一些大的和任意的 NONCE 字符串,那么“.nonce NONCE”命令(具有相同的大 nonce 字符串)将允许下一个 SQL 语句或点-命令绕过--safe 限制。

假设您要运行一个可疑的脚本,并且该脚本需要 --safe 通常禁用的一两个功能。例如,假设它需要附加一个额外的数据库。或者假设脚本需要加载特定的扩展。这可以通过在(仔细审核的)ATTACH 语句或“.load”命令前加上适当的“.nonce”命令并使用“--nonce”命令行选项提供相同的随机数值来实现。这些特定的命令将被允许正常执行,但所有其他不安全的命令仍将受到限制。

使用“.nonce”是危险的,因为错误可能会导致恶意脚本损坏您的系统。因此,当没有其他方法让脚本在 --safe 模式下运行时,请谨慎、谨慎地使用“.nonce”,并作为最后的手段。

24.从源代码编译sqlite3程序

要使用 MinGW 在 unix 系统和 Windows 上编译命令行 shell,通常使用 configure-make 命令:

sh configure; make

无论您是从源代码树的规范源还是从合并的包构建,configure-make 都可以工作。几乎没有依赖关系。从规范来源构建时,需要一个有效的 tclsh如果使用合并包,通常由 tclsh 完成的所有预处理工作都已经完成,只需要普通的构建工具。

为了运行.archive 命令,需要 一个有效的zlib 压缩库

在带有 MSVC 的 Windows 上,将 nmake 与 Makefile.msc 一起使用:

nmake /f Makefile.msc

为了正确运行.archive 命令,将 zlib 源代码复制到源代码树的 compat/zlib 子目录中,并按以下方式编译:

nmake /f Makefile.msc USE_ZLIB=1

24.1. 自己动手构建

sqlite3 命令行界面的源代码在一个名为“shell.c”的文件中。shell.c 源文件是从其他来源生成的,但是 shell.c 的大部分代码都可以在 src/shell.c.in中找到。(通过从规范源代码树中键入“make shell.c”重新生成 shell.c。) 编译shell.c 文件(连同sqlite3 库源代码)以生成可执行文件。例如:

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

建议使用以下附加编译时选项,以提供功能齐全的命令行 shell: