小巧、快速、可靠。
任選三項。
SQLite 命令列殼層

1. 入門

SQLite 專案提供一個名為 sqlite3 (或 Windows 上的 sqlite3.exe) 的簡單命令列程式,讓使用者可以手動輸入和執行 SQL 陳述式,針對 SQLite 資料庫或 ZIP 檔案。本文件簡要說明如何使用 sqlite3 程式。

在命令提示字元輸入「sqlite3」啟動 sqlite3 程式,也可以選擇後接包含 SQLite 資料庫 (或 ZIP 檔案) 的檔案名稱。如果指定的檔案不存在,將自動建立一個具有指定名稱的新資料庫檔案。如果命令列中未指定資料庫檔案,將建立一個暫時資料庫,並在「sqlite3」程式結束時自動刪除。

啟動時,sqlite3 程式將顯示簡短的標語訊息,然後提示您輸入 SQL。輸入 SQL 陳述式 (以分號結尾),按「Enter」,SQL 將會執行。

例如,若要建立一個名為「ex1」的新 SQLite 資料庫,其中有一個名為「tbl1」的表格,您可以執行以下操作

$ 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 圖示,讓命令列外殼程式彈出執行 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 個。

如需取得可用 dot 指令清單,您可以輸入「.help」,而無需任何引數。或輸入「.help TOPIC」以取得有關 TOPIC 的詳細資訊。可用 dot 指令清單如下

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
.crnl on|off             Translate \n to \r\n.  Default ON
.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
.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|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
.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
.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
.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
.width NUM1 NUM2 ...     Set minimum column widths for columnar output
sqlite>

4. 「dot 指令」、SQL 及其他規則

4.1. 列結構

CLI 的輸入會解析成由下列組成的順序

SQL 陳述式為自由格式,且可以跨多行,並在任何地方嵌入空白或 SQL 註解。它們會以輸入行尾的「;」字元、或「/」字元,或單獨一行上的「go」字詞作為終止符號。當不在輸入行尾時,「;」字元會用來分隔 SQL 陳述式。尾隨空白會在終止符號的目的下被忽略。

dot 指令有更嚴格的結構

CLI 也接受整行註解,它從「#」字元開始,並延伸到該行的結尾。在「#」之前不能有空白。

4.2. Dot 指令引數

傳遞給 dot 指令的引數會根據下列規則從指令尾端進行解析

  1. 尾隨換行符號和任何其他尾隨空白會被捨棄;
  2. 緊接在 dot 指令名稱或任何引數輸入結束界線之後的空白會被捨棄;
  3. 引數輸入會從任何非空白字元開始;
  4. 引數輸入以一個字元結束,該字元取決於其前導字元,如下所示
  5. 在雙引號引數輸入中,反斜線跳脫的雙引號是引數的一部分,而不是其終止引號;
  6. 在雙引號引數中,傳統 C 字串文字、反斜線跳脫序列轉換已完成;且
  7. 引數輸入分隔符號(邊界引號或空白)會被捨棄以產生傳遞的引數。

4.3. 點命令執行

點命令由 sqlite3.exe 命令列程式碼解釋,而非由 SQLite 本身解釋。因此,沒有任何點命令會作為 SQLite 介面的引數,例如 sqlite3_prepare()sqlite3_exec()

5. 變更輸出格式

sqlite3 程式碼能夠以 14 種不同的輸出格式顯示查詢結果

您可以使用「.mode」點命令在這些輸出格式之間切換。預設輸出模式為「list」。在 list 模式中,查詢結果的每一列寫在輸出的一行上,且該列中的每一欄位都由特定的分隔符號字串分隔。預設分隔符號為直線符號(「|」)。當您要將查詢輸出傳送至另一個程式碼(例如 AWK)進行額外處理時,list 模式特別有用。

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」命令。

在「quote」模式中,輸出會以 SQL 文字格式化。字串會用單引號括起來,而內部單引號會透過加倍來跳脫。二進位大型物件會以十六進位二進位大型物件文字符號(例如:x'abcd')顯示。數字會以 ASCII 文字顯示,而 NULL 值會顯示為「NULL」。所有欄位會以逗號(或使用「.separator」選取的任何替代字元)彼此分隔。

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

在「line」模式中,資料庫中每一列的每一欄會顯示在單獨一行中。每一行包含欄位名稱、等號和欄位資料。連續記錄會以空白行分隔。以下是 line 模式輸出的範例

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

one = goodbye
two = 20
sqlite>

在 column 模式中,每一筆記錄會顯示在單獨一行中,資料會對齊在欄位中。例如

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

在「column」模式(以及「box」、「table」和「markdown」模式)中,欄位的寬度會自動調整。但是,您可以覆寫此設定,使用「.width」命令提供每個欄位的指定寬度。「.width」的引數是整數,表示要分配給每個欄位的字元數。負數表示右對齊。因此

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

寬度為 0 表示欄位寬度會自動選取。未指定的欄位寬度會變成零。因此,不帶引數的「.width」命令會將所有欄位寬度重設為零,並因此導致所有欄位寬度自動決定。

「column」模式是表格輸出格式。其他表格輸出格式包括「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.',90);
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」即可。

另一種有用的輸出模式是「insert」。在插入模式中,輸出會格式化成類似 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」指令,在於它會顯示整個資料庫結構。但是,如果存在「sqlite_stat1」、「sqlite_stat3」和「sqlite_stat4」統計資料表,「.fullschema」也會包含這些資料表的傾印。通常,「.fullschema」指令會提供所有資訊,以便為特定查詢精確地重新建立查詢計畫。當向 SQLite 開發團隊報告 SQLite 查詢計畫的疑似問題時,開發人員會要求提供完整的「.fullschema」輸出作為問題報告的一部分。請注意,sqlite_stat3 和 sqlite_stat4 資料表包含索引條目的範例,因此可能包含敏感資料,因此請勿透過公開頻道傳送專有資料庫的「.fullschema」輸出。

7. 開啟資料庫檔案

「.open」指令會開啟一個新的資料庫連線,並先關閉先前開啟的資料庫指令。在最簡單的形式中,「.open」指令僅對其引數所指定的名稱呼叫 sqlite3_open()。使用名稱「:memory:」開啟一個新的記憶體中資料庫,當 CLI 退出或再次執行「.open」指令時,該資料庫就會消失。或者不使用任何名稱開啟一個私密的、暫時的磁碟資料庫,該資料庫也會在退出或使用「.open」時消失。

如果「.open」包含 --new 選項,則資料庫會在開啟前重設。任何先前資料都會被銷毀。這是對先前資料的破壞性覆寫,且不會要求確認,因此請小心使用此選項。

--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 函數

命令列外殼新增了兩個 應用程式定義的 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 函式庫中。這些常式在 可載入擴充 中提供,位於 ext/misc/fileio.c 原始碼檔案中,在 SQLite 原始碼儲存庫 中。

8.4. edit() SQL 函數

CLI 有另一個內建 SQL 函數,稱為 edit()。Edit() 會使用一個或兩個引數。第一個引數是一個值,通常是多行字串,用於編輯。第二個引數是文字編輯器的呼叫。(它可能包含影響編輯器行為的選項。)如果省略第二個引數,則會使用 VISUAL 環境變數。edit() 函數會將其第一個引數寫入暫存檔案中,在編輯器處理完畢後呼叫暫存檔案的編輯器,然後重新將檔案讀回記憶體中,再傳回已編輯的文字。

edit() 函數可用於變更大型文字值。例如

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

在此範例中,docs.body 欄位中 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';

8.5. 將檔案匯入為 CSV 或其他格式

使用「.import」指令將 CSV(逗號分隔值)或類似分隔資料匯入 SQLite 資料表中。「.import」指令採用兩個引數,分別是讀取資料的來源和要將資料插入其中的 SQLite 資料表名稱。來源引數是待讀取檔案的名稱,或者,如果它以「|」字元開頭,則指定將執行以產生輸入資料的指令。

請注意,在執行「.import」指令之前設定「模式」可能很重要。這對於防止命令列外殼程式嘗試將輸入檔案文字詮釋為檔案結構以外的其他格式非常有幫助。如果使用 --csv 或 --ascii 選項,它們會控制匯入輸入分隔符號。否則,分隔符號會是目前輸出模式中有效的那些分隔符號。

要匯入不在「main」架構中的資料表,可以使用 --schema 選項來指定資料表位於其他架構中。這對於 ATTACH 的資料庫或匯入 TEMP 資料表很有用。

執行 .import 時,它對第一列輸入列的處理方式取決於目標表格是否已存在。如果不存在,表格會自動建立,而第一列輸入列的內容會用於設定表格中所有欄位的名稱。在此情況下,表格資料內容會從第二列及後續的輸入列取得。如果目標表格已存在,輸入的每一列,包括第一列,都會視為實際資料內容。如果輸入檔案包含一列初始的欄位標籤,您可以使用「--skip 1」選項讓 .import 指令略過該初始列。

以下是一個範例用法,從 CSV 檔案載入一個已存在的暫時表格,該檔案的第一列包含欄位名稱

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

在以「ascii」以外的模式讀取輸入資料時,「.import」會根據 RFC 4180 規格將輸入解譯為由欄位組成的記錄,但例外情況是:輸入記錄和欄位分隔符號是由模式或使用 .separator 指令設定的。欄位總是會移除引號,以反轉根據 RFC 4180 進行的引號處理,但 ascii 模式除外。

若要匯入具有任意分隔符號且沒有引號的資料,請先設定 ascii 模式(「.mode ascii」),然後使用「.separator」指令設定欄位和記錄分隔符號。這會抑制取消引號。在「.import」之後,資料會根據如此指定的分隔符號拆分為欄位和記錄。

8.6. 匯出至 CSV

若要將 SQLite 資料表(或資料表的部份)匯出為 CSV,只需將「模式」設為「csv」,然後執行查詢以擷取資料表的所需列。輸出將根據 RFC 4180 格式化為 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」字尾為暫時檔案命名,因此會呼叫系統的預設文字編輯器,而不是預設的試算表。

8.6.2. 匯出至 TSV(以 tab 分隔的值)

若要在執行查詢之前輸入「.mode tabs」,則可以匯出至純粹的 TSV,而不會引用任何欄位。但是,如果「.import」指令包含雙引號字元,則無法在 tab 模式中正確讀取輸出。若要取得符合 RFC 4180 規範的 TSV,以便可以在 tab 模式中使用「.import」輸入,請先輸入「.mode csv」,然後在執行查詢之前輸入「.separator "\t"」。

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 檔案存取的實作方式

命令列殼層使用 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 檔案的特殊處理是命令列殼層的技巧,而非 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 表格項目。

欄位內容
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 新增至命令列殼層。首先,將擴充功能建置為 DLL 或共用函式庫(如 執行時期可載入擴充功能 文件中所述),然後輸入

sqlite> .load /path/to/my_extension

請注意,SQLite 會自動將適當的擴充功能字尾(Windows 上為 ".dll",Mac 上為 ".dylib",大多數其他 Unix 系統上為 ".so")新增至擴充功能檔名。通常建議指定擴充功能的完整路徑名稱。

SQLite 會根據擴充功能檔名計算擴充功能的進入點。若要覆寫此選項,只需將擴充功能名稱新增為 ".load" 指令的第二個引數即可。

可以在 SQLite 原始碼樹的 ext/misc 子目錄中找到多個有用擴充功能的原始碼。您可以將這些擴充功能視為現有擴充功能,或作為建立您自己的自訂擴充功能的基礎,以滿足您自己的特定需求。

13. 資料庫內容的加密雜湊

「.sha3sum」點指令會計算資料庫內容SHA3 hash。說清楚一點,hash 是計算資料庫內容,而不是它在磁碟上的表示。這表示,例如 VACUUM 或類似的資料保留轉換不會變更 hash。

「.sha3sum」指令支援選項「--sha3-224」、「--sha3-256」、「--sha3-384」和「--sha3-512」來定義要使用哪種 SHA3 變種來進行 hash。預設值是 SHA3-256。

資料庫架構(在 sqlite_schema 表中)通常不會包含在 hash 中,但可以使用「--schema」選項來新增。

「.sha3sum」指令會接受一個單一的選用引數,它是一個 LIKE 模式。如果這個選項存在,只有名稱符合 LIKE 模式的資料表才會進行 hash。

「.sha3sum」指令是使用 擴充函數「sha3_query()」 來實作的,這個函數包含在指令列 shell 中。

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 資料表的列。對於每個「memo」列,它會將「cmd」中的文字寫入輸出。對於每個「run」列,它會將「cmd」文字作為 SQL 執行,並將結果與「ans」中的值進行比較,如果結果不同,則會顯示錯誤訊息。

如果沒有 selftest 資料表,則「.selftest」指令會執行 PRAGMA integrity_check

「.selftest --init」指令會建立 selftest 表格(如果尚未存在),然後附加檢查所有表格內容的 SHA3 hash 的項目。後續執行「.selftest」將會驗證資料庫是否以任何方式變更。若要產生測試以驗證表格子集是否未變更,只要執行「.selftest --init」,然後 刪除 參照非恆定表格的 selftest 列即可。

15. SQLite Archive 支援

「.archive」點指令和「-A」命令列選項提供內建支援 SQLite Archive 格式。介面類似於 Unix 系統上的「tar」指令。每次呼叫「.ar」指令都必須指定一個單一指令選項。以下指令可供「.archive」使用

選項長選項用途
-c--create建立包含指定檔案的新檔案庫。
-x--extract從檔案庫中萃取指定的檔案。
-i--insert將檔案新增至現有的檔案庫。
-r--remove從檔案庫中移除檔案。
-t--list列出檔案庫中的檔案。
-u--update將檔案新增至現有的檔案庫(如果檔案已變更)。

除了指令選項之外,每次呼叫「.ar」都可以指定一個或多個修改選項。有些修改選項需要引數,有些則不需要。以下修改選項可供使用

選項長選項用途
-v--verbose在處理每個檔案時列出該檔案。
-f FILE--file FILE如果指定,使用檔案 FILE 作為檔案庫。否則,假設目前的「主要」資料庫是要操作的檔案庫。
-a FILE--append FILE如同 --file,使用檔案 FILE 作為檔案庫,但使用 apndvfs VFS 開啟檔案,以便在 FILE 已存在的情況下將檔案庫附加到 FILE 的結尾。
-C DIR--directory DIR如果指定,將所有相對路徑解釋為相對於 DIR,而不是目前的作業目錄。
-g--glob使用 glob(Y,X) 將參數與檔案庫中的名稱進行比對。
-n--dryrun顯示會執行以進行檔案庫操作的 SQL,但實際上不會變更任何內容。
----所有後續的命令列字詞都是命令參數,而非選項。

對於命令列使用,在「-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 擴充功能來完成的。因此,下列指令大致相當,僅在輸出格式上有所不同

傳統指令等效的 sqlite3.exe 指令
unzip archive.zipsqlite3 -Axf archive.zip
unzip -l archive.zipsqlite3 -Atvf archive.zip
zip -r archive2.zip dirsqlite3 -Acf archive2.zip dir

15.7. 用於實作 SQLite 檔案操作的 SQL

各種 SQLite 檔案檔案指令都是使用 SQL 陳述式來實作的。應用程式開發人員可以透過執行適當的 SQL,輕鬆地將 SQLite 檔案檔案讀寫支援新增到自己的專案中。

若要查看用於實作 SQLite 檔案操作的 SQL 陳述式,請新增 --dryrun 或 -n 選項。這會導致顯示 SQL,但會禁止執行 SQL。

用於實作 SQLite 檔案操作的 SQL 陳述式會使用各種 可載入擴充功能。這些擴充功能都可以在 SQLite 原始碼樹 中的 ext/misc/ 子資料夾 中找到。完整支援 SQLite 檔案所需的擴充功能包括

  1. fileio.c — 此擴充功能新增 SQL 函數 readfile() 和 writefile(),用於讀寫磁碟上檔案的內容。fileio.c 擴充功能還包括 fsdir() 表值函數,用於列出目錄的內容,以及 lsmode() 函數,用於將 stat() 系統呼叫中的數字 st_mode 整數轉換為人類可讀的字串,就像「ls -l」指令一樣。

  2. sqlar.c — 此擴充功能新增 sqlar_compress() 和 sqlar_uncompress() 函數,這些函數是從 SQLite 檔案插入和提取檔案內容時壓縮和解壓縮檔案內容所需要的。

  3. zipfile.c — 此擴充套件實作「zipfile(FILE)」表格值函數,用於讀取 ZIP 檔案。僅在讀取 ZIP 檔案(而非 SQLite 檔案)時才需要此擴充套件。

  4. appendvfs.c — 此擴充套件實作新的 VFS,允許將 SQLite 資料庫附加到其他檔案(例如可執行檔)。僅在使用 .archive 命令的 --append 選項時才需要此擴充套件。

16. SQL 參數

SQLite 允許 繫結參數 出現在 SQL 陳述式中,任何允許文字值的地方。這些參數的值使用 sqlite3_bind_...() API 系列設定。

參數可以命名或不命名。未命名的參數為單一問號(「?」)。命名的參數為「?」後接數字(例如:?15 或 ?123)或字元「$」、「:」或「@」後接字母數字名稱(例如:$var1、:xyz、@bingo)。

此命令列殼層會讓未命名的參數保持未繫結,表示它們的值為 SQL NULL,但命名的參數可以指定值。如果存在名為「sqlite_parameters」的 TEMP 表格,具有類似下列的架構

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

而且在該表格中有一個條目,其中 key 欄位與參數名稱完全相符(包括開頭的「?」、「$」、「:」或「@」字元),則會將該參數指定為 value 欄位的值。如果沒有條目,則參數預設為 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 表格僅提供指令列外殼中參數的值。temp.sqlite_parameter 表格對使用 SQLite C 語言 API 直接執行的查詢沒有影響。預期個別應用程式實作自己的參數繫結。您可以在 指令列外殼原始碼 中搜尋「sqlite_parameters」,以了解指令列外殼如何執行參數繫結,並將其用作如何自行實作的提示。

17. 索引建議(SQLite Expert)

注意:此指令為實驗性質。在未來某個時間點,可能會移除此指令或以不相容的方式修改介面。

對於大多數非平凡的 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」指令接受下列選項

選項 用途
‑‑verbose 如果存在,則為每個分析的查詢輸出更詳細的報告。
‑‑sample PERCENT 此參數預設為 0,導致「.expert」指令僅根據查詢和資料庫結構來建議索引。這類似於 SQLite 查詢規劃器 在使用者未對資料庫執⾏ ANALYZE 指令來產生資料分佈統計資料時,為查詢選擇索引的方式。
如果此選項傳遞非零引數,「.expert」指令會根據目前儲存在每個資料庫表格中 PERCENT 百分比的列,為所有考量的索引產生類似的資料分佈統計資料。對於具有異常資料分佈的資料庫,這可能會導致更好的索引建議,特別是如果應用程式打算執⾏ ANALYZE 的話。
對於小型資料庫和現代 CPU,通常沒有理由不傳遞「--sample 100」。不過,收集資料分佈統計資料對於大型資料庫表格來說可能很昂貴。如果作業太慢,請嘗試為 --sample 選項傳遞較小的值。

本節所述的功能可以使用 SQLite expert 擴充功能 程式碼整合到其他應用程式或工具中。

包含透過擴充功能載入機制提供的 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 擴充功能所建置的。有一些新增功能未在前面各節中說明,即

20. 其他點命令

命令列殼層中還有許多其他點命令可用。請參閱「.help」命令,以取得任何特定版本的 SQLite 的完整清單和建置。

21. 在殼層指令碼中使用 sqlite3

在殼層指令碼中使用 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. 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
   -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
   -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
   -zip                 open the file as a ZIP Archive

CLI 對於命令列選項格式化相當彈性。允許使用一個或兩個連字號「-」作為開頭。因此「-box」和「--box」的意思相同。命令列選項會由左至右處理。因此「--box」選項會覆寫先前的「--quote」選項。

大部分命令列選項不言自明,但有幾個選項值得在下方進一步說明。

23.1. --safe 命令列選項

--safe 命令列選項會嘗試停用 CLI 的所有功能,這些功能可能會對主機電腦造成任何變更,但不會變更命令列上指定的特定資料庫檔案。其用意是,如果您收到來自未知或不可信來源的大型 SQL 腳本,您可以執行該腳本查看其功能,而無需冒險使用 --safe 選項。--safe 選項會停用(包括但不限於)

基本上,任何 CLI 功能,只要會讀取或寫入主資料庫檔案以外的磁碟檔案,都會被停用。

23.1.1. 繞過特定命令的 --safe 限制

如果命令列中也包含 "--nonce NONCE" 選項,其中 NONCE 字串為任意的大字串,則 ".nonce NONCE" 命令(使用相同的大字串)將允許下一個 SQL 陳述式或點命令繞過 --safe 限制。

假設您要執行一個可疑的指令碼,而該指令碼需要 --safe 通常會停用的其中一或兩個功能。例如,假設它需要附加一個額外的資料庫。或者假設指令碼需要載入特定的擴充功能。這可透過在 (經過仔細稽核的) ATTACH 陳述式或 ".load" 命令之前加上適當的 ".nonce" 命令,並使用 "--nonce" 命令列選項提供相同的隨機值來達成。這些特定命令隨後將被允許正常執行,但所有其他不安全的命令仍將受到限制。

使用 ".nonce" 很危險,因為錯誤可能會讓惡意指令碼損壞您的系統。因此,請小心、謹慎地使用 ".nonce",並在沒有其他方法可以在 --safe 模式下執行指令碼時,將其視為最後的手段。

23.2. --unsafe-testing 命令列選項

--unsafe-testing 命令列選項支援使用 CLI 來進行 SQLite 函式庫的內部測試。它並非建立、修改或查詢 SQLite 資料庫時,作為公用程式使用 CLI 所需或有用的功能。其預期用途是允許腳本測試,包括直接變更架構、解除防禦措施,以及啟用某些特殊用途、未記錄的、以測試為導向的 dot 指令。

僅因為需要使用 --unsafe-testing 選項才能引發的錯誤行為,通常不會因此而被視為錯誤。不支援或定義使用 --unsafe-testing 的 CLI 行為。

23.3. --no-utf8 和 --utf8 命令列選項

在 Windows 平台上,當使用主控台進行輸入或輸出時,需要在主控台可取得或傳送的字元編碼與 CLI 的內部 UTF-8 文字表示法之間進行轉換。過去版本的 CLI 接受這些選項,以啟用或停用轉換功能,該功能仰賴 Windows 主控台功能,可讓其在現代版本的作業系統上產生或接受 UTF-8。

目前的 CLI 版本 (3.44.1 或更新版本) 透過從 Windows 主控台 API 讀取或寫入 UTF-16 來執行主控台 I/O。由於這項功能即使在 Windows 版本回溯至 Windows 2000 上也能正確運作,因此不再需要這些選項。這些選項仍被接受,但不會產生任何效果。

在所有情況下,非主控台文字 I/O 都會編碼為 UTF-8。

在非 Windows 平台上,這些選項也會被忽略。

24. 從來源編譯 sqlite3 程式

若要在 unix 系統和使用 MinGW 的 Windows 上編譯命令列殼層,通常的 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

建議使用以下額外的編譯時間選項,以提供功能齊全的命令列殼層

此頁面最後修改於 2023-12-05 14:43:20 UTC