小巧、快速、可靠。
三者擇其三。

編輯備註:此文件撰寫於 2004 年,作為從 SQLite2 轉換至 SQLite3 的程式設計人員指南。它保留為 SQLite 的歷史記錄的一部分。現代程式設計人員應參閱本網站其他地方提供的最新 SQLite 文件。

SQLite 版本 3 概觀

SQLite 版本 3.0 對程式庫進行了重大變更,包括

此文件是針對已熟悉 SQLite 版本 2.8 的使用者,快速介紹 SQLite 3.0 的變更。

命名變更

SQLite 版本 2.8 將持續獲得錯誤修正支援,直至可預見的未來。為了讓 SQLite 版本 2.8 和 SQLite 版本 3.0 能和平共存,SQLite 版本 3.0 中的主要檔案和 API 名稱已變更,加入字元「3」。例如,C 程式使用的包含檔案已從「sqlite.h」變更為「sqlite3.h」。而用於與資料庫互動的 shell 程式名稱已從「sqlite.exe」變更為「sqlite3.exe」。透過這些變更,可以在同一系統上同時安裝 SQLite 2.8 和 SQLite 3.0。而且,同一個 C 程式可以同時連結到 SQLite 2.8 和 SQLite 3.0,並同時使用這兩個程式庫。

新檔案格式

SQLite 資料庫檔案使用的格式已完全修改。舊的版本 2.1 格式和新的 3.0 格式互不相容。SQLite 版本 2.8 無法讀取版本 3.0 資料庫檔案,而 SQLite 版本 3.0 無法讀取版本 2.8 資料庫檔案。

若要將 SQLite 2.8 資料庫轉換成 SQLite 3.0 資料庫,請準備好版本 2.8 和 3.0 的命令列殼層。然後輸入類似下列的指令

sqlite OLD.DB .dump | sqlite3 NEW.DB

新的資料庫檔案格式使用 B+ 樹狀結構作為表格。在 B+ 樹狀結構中,所有資料都儲存在樹狀結構的葉節點中,而非葉節點和中間分支節點。使用 B+ 樹狀結構作為表格可以提高擴充性,並在不使用溢位頁面的情況下儲存較大的資料欄位。傳統的 B 樹狀結構仍用於索引。

新的檔案格式也支援 512 到 65536 位元組之間的變數頁面大小。頁面大小儲存在檔案標頭中,因此理論上同一個程式庫可以讀取具有不同頁面大小的資料庫,不過此功能尚未實際實作。

新的檔案格式會從其磁碟映像中省略未使用的欄位。例如,索引只使用 B 樹狀結構記錄的關鍵部分,而不使用資料。因此,對於索引,會省略記錄資料長度的欄位。例如關鍵字和資料的長度等整數值使用變長度編碼儲存,因此最常見的情況只需要一或兩個位元組即可儲存,但如果需要,最多可以編碼 64 位元組的資訊。整數和浮點數資料會以二進位格式儲存在磁碟中,而不是像 SQLite 版本 2.8 那樣轉換成 ASCII。這些變更加起來會讓資料庫檔案比 SQLite 版本 2.8 中的等效檔案小 25% 到 35%。

SQLite 3.0 版本中使用的低階 B 樹格式詳細資訊,請參閱 btreeInt.h 原始檔的標題註解,以及 檔案格式 文件。

明確定義型別和 BLOB 支援

SQLite 2.8 版本在內部會以各種格式處理資料,但在寫入磁碟或透過其 API 進行互動時,SQLite 2.8 會永遠將資料轉換成 ASCII 文字。相對地,SQLite 3.0 會將其內部資料表示公開給使用者,並在適當的時候將二進位表示儲存到磁碟。公開非 ASCII 表示是為了支援 BLOB 而新增的。

SQLite 2.8 版本具備一個特色,就是任何類型的資料都可以儲存在任何資料表欄位中,而不管該欄位的宣告型別為何。3.0 版本保留了這個特色,不過稍作修改。每個資料表欄位都會儲存任何類型的資料,儘管欄位對其宣告資料類型所定義的資料格式有親和性。當資料插入欄位時,該欄位會嘗試將資料格式轉換成欄位的宣告型別。所有 SQL 資料庫引擎都會這麼做。不同的是,即使無法進行格式轉換,SQLite 3.0 仍然會儲存資料。

例如,如果你有一個宣告為「INTEGER」類型的表格欄位,而你試著插入一個字串,該欄位會查看文字字串,並判斷它是否看起來像數字。如果該字串看起來像數字,它會被轉換成數字,並在數字沒有小數部分時轉換成整數,並以這種方式儲存。但如果該字串不是格式良好的數字,它仍會儲存為字串。類型為「TEXT」的欄位會在儲存數字之前,嘗試將其轉換成 ASCII 文字表示。但 BLOB 會儲存在 TEXT 欄位中,因為你通常無法將 BLOB 轉換成文字。

在其他大多數 SQL 資料庫引擎中,資料類型與儲存資料的表格欄位相關聯,也就是與資料容器相關聯。在 SQLite 3.0 中,資料類型與資料本身相關聯,而不是與其容器相關聯。Paul Graham 在他的書中ANSI Common Lisp 將此特性稱為「明示類型」。其他作者對「明示類型」一詞有其他定義,因此請注意不要混淆。但無論名稱為何,這就是 SQLite 3.0 支援的資料類型模型。

有關 SQLite 版本 3.0 中資料類型的其他資訊可單獨取得。

支援 UTF-8 和 UTF-16

SQLite 3.0 的新 API 包含例程,以主機電腦的原生位元組順序接受 UTF-8 和 UTF-16 的文字。每個資料庫檔案以 UTF-8、UTF-16BE(大端序)或 UTF-16LE(小端序)管理文字。在內部和磁碟檔案中,到處都使用相同的文字表示法。如果資料庫檔案(在檔案標頭中)指定的文字表示法與介面例程所需的文字表示法不符,則文字會即時轉換。持續將文字從一個表示法轉換到另一個表示法在運算上可能很昂貴,因此建議程式設計人員選擇一個表示法並在整個應用程式中堅持使用它。

在 SQLite 的目前實作中,SQL 剖析器僅適用於 UTF-8 文字。因此,如果您提供 UTF-16 文字,它將會被轉換。這只是一個實作問題,沒有什麼可以阻止未來版本的 SQLite 以原生方式剖析 UTF-16 編碼的 SQL。

在建立新的使用者定義 SQL 函數和排序順序時,每個函數或排序順序可以指定它是否適用於 UTF-8、UTF-16be 或 UTF-16le。可以為每個編碼註冊個別的實作。如果需要 SQL 函數或排序順序,但目前文字編碼的版本不可用,則文字會自動轉換。和以前一樣,此轉換需要運算時間,因此建議程式設計人員選擇一個編碼並堅持使用它,以將不必要的格式調整量減到最少。

SQLite 對它接收的文字並不特別挑剔,而且很樂意處理未正規化甚至格式良好的 UTF-8 或 UTF-16 的文字字串。因此,想要儲存 ISO8859 資料的程式設計人員可以使用 UTF-8 介面來執行此操作。只要不嘗試使用 UTF-16 排序順序或 SQL 函數,文字的位元組順序就不會以任何方式修改。

使用者定義的排序順序

校對順序只是一個文字的定義順序。當 SQLite 3.0 排序(或使用比較運算子,例如「<」或「>=")時,排序順序會先由資料類型決定。

校對順序用於比較兩個文字字串。校對順序不會變更 NULL、數字或 BLOB 的排序,只會變更文字。

校對順序實作為一個函數,它將兩個要比較的字串作為輸入,並在第一個字串小於、等於或大於第二個字串時傳回負值、零或正值。SQLite 3.0 內建一個名為「BINARY」的校對順序,它使用標準 C 函式庫中的 memcmp() 常式實作。BINARY 校對順序很適合英文文字。對於其他語言或地區,建議使用其他校對順序。

決定要使用哪個校對順序是由 SQL 中的 COLLATE 子句控制。COLLATE 子句可以出現在表格定義中,以定義表格欄位的預設校對順序,或出現在索引欄位中,或出現在 SELECT 陳述式的 ORDER BY 子句中。SQLite 計畫的強化功能包括標準 CAST() 語法,以允許定義運算式的校對順序。

64 位元 ROWID

表格的每一列都有唯一的 rowid。如果表格定義一個類型為「INTEGER PRIMARY KEY」的欄位,則該欄位會成為 rowid 的別名。但是,無論是否有 INTEGER PRIMARY KEY 欄位,每一列仍然有一個 rowid。

在 SQLite 版本 3.0 中,rowid 是 64 位元有號整數。這是 SQLite 版本 2.8 的擴充,後者僅允許 32 位元的 rowid。

為了最小化儲存空間,64 位元的 rowid 會儲存為變長整數。介於 0 到 127 之間的 rowid 只使用一個位元組。介於 0 到 16383 之間的 rowid 只使用 2 個位元組。最高到 2097152 使用 3 個位元組。以此類推。負 rowid 是允許的,但它們總是使用 9 個位元組的儲存空間,因此不鼓勵使用。當 rowid 由 SQLite 自動產生時,它們永遠是非負的。

改善並行性

SQLite 版本 2.8 允許多個同時讀取器或單一寫入器,但不能同時存在。SQLite 版本 3.0 允許一個程序開始寫入資料庫,而其他程序繼續讀取。寫入器仍必須在短暫的區間內取得資料庫的獨佔鎖定才能提交其變更,但寫入作業不再需要獨佔鎖定。有關 SQLite 版本 3.0 鎖定行為的更詳細報告可另行取得。

SQLite 現在也提供有限形式的表格層級鎖定。如果每個表格都儲存在個別的資料庫檔案中,這些個別檔案可以附加到主資料庫(使用 ATTACH 指令),而合併的資料庫將作為一個資料庫運作。但鎖定只會在需要時取得個別檔案。因此,如果你重新定義「資料庫」為兩個或兩個以上的資料庫檔案,那麼完全有可能讓兩個程序同時寫入同一個資料庫。為了進一步支援此功能,現在涉及兩個或兩個以上 ATTACH 資料庫的交易提交是原子的。

鳴謝

SQLite 版本 3.0 的實現,部分歸功於 AOL 開發人員支持並擁抱出色的開源軟體。

此頁面上次修改於 2023-10-10 17:29:48 UTC