【譯】SQLite C/C++ 接口介紹


SQLite C/C++ 接口介紹

這篇文章簡要的介紹了 SQLite 的 C/C++ 接口。

早期版本的 SQLite 很好學是因爲他們只提供了 5 個 C/C++ 的接口。但是隨着 SQLite 功能的增加,新的 C/C++ 接口加入,現在已經有超過 200 個不同的 API 了。這對新人可能是一種阻礙。幸運的是,大部分的 C/C++ 接口都是有特殊用途的,不需要了解。儘管有這麼多的入口點,核心的 API 還是相當的簡單而且容易使用。這篇文章旨在提供所有能使讀者容易理解 SQLite 如何工作的背景信息。

一個獨立的接口文檔提供了 SQLite 不同的 C/C++ 接口的詳細說明。一旦讀者理解了操作 SQLite 的基本概念,該文檔就可以成爲參考手冊了。這篇文章只是一個介紹,不會是 SQLite 的完整、權威的參考手冊。

1.0 核心對象和接口

SQL 數據庫引擎的核心任務是計算 SQL 語句的值(evaluate statements of SQL)。爲了完成這個目的,開發者需要了解兩個對象:

數據庫連接對象(The database connection object):sqlite3 
預處理好的語句對象(The prepared statement object): sqlite3_stmt

嚴格來講,對於一些封裝好的便捷接口 prepared statement object不是必須的,比如 sqlite3exec 還有 sqlite3get_table, 在內部求值時都會封裝並隱藏這些 prepared statement object。然而,要想充分利用 SQLite, 理解 prepared statements 還是有必要的。

Database connection 和 prepared statement 對象由下面列出的一組 C/C++ 接口(interface routine)控制。

sqlite3_open()  
sqlite3_prepare()  
sqlite3_step()  
sqlite3_column()  
sqlite3_finalize()  
sqlite3_close()  

上面列出的 6 個 C/C++ 接口還有兩個對象組成了 SQLite 的核心功能。理解了這些的開發者在使用 SQLite 時就會很容易了。

注意上面列出的這些接口只是一類接口而不是實際的接口。這些接口都有許多不同的版本。比如,上面列出的一個叫做 sqlite3open() 的接口,事實上是由 3 個完全不同的接口組成的:sqlite3open()sqlite3open16() 還有 sqlite3openv2()。上面列表中提到的 sqlite3column() 實際上並不存在。列表中提到的 “sqlite3_column()” 實際上是由一簇爲了獲取不同列類型的接口組成。

下面是核心接口的簡要介紹:

sqlite3_open()    這個接口打開一個到 SQLite 數據庫文件的鏈接並返回一個數據庫連接對象。這通常是應用程序調用的第一個 SQLite 的 API,並且也是其他大部分的 SQLite API 所需要的。大部分的 SQLite 接口需要一個指向 database connection object 的指針作爲第一個參數,可以認爲是數據庫連接對象上的方法。這個接口是數據庫連接對象的構造器。

sqlite3prepare()    這個接口將 SQL 語句轉換爲一個 prepared statement 對象並返回指向這個對象的指針。這個接口需要之前使用 sqlite3open() 返回的數據庫連接對象,還有一個包含 SQL 語句的文本字符串作爲參數。這個 API 實際上並不執行 SQL 語句。它僅僅只是準備用於執行的 SQL 語句。把每個 SQL 語句想象成一個小型的計算機程序。sqlite3prepare() 是爲了把那個程序編譯成對象代碼(object code)。Prepared statement 就是這個對象代碼。之後 sqlite3step() 運行這個對象代碼獲取結果。

注意對於新的程序已經不推薦使用 sqlite3prepare()。新的應用推薦使用sqlite3prepare_v2() 接口。

sqlite3step()     這個接口用於執行之前用 sqlite3prepare() 創建的 prepared statement。這個接口只返回結果集的第一條結果。爲了獲取第二條結果,再調用一次 sqlite3step()。繼續調用 sqlite3step() 直到語句結束。不返回結果的語句(比如:INSERT, UPDATE, 或者 DELETE 語句)調用一次 sqlite3_step() 就行了。

sqlite3column()    這個接口返回使用 sqlite3step() *查詢的 prepared statement 的結果集中當前行的某一列。每次調用完 *sqlite3step() 都會產生一個新的 result set row。這個接口可以被調用多次用於獲取一行中的不同列。正如上面所提到的,事實上在 SQLite 的 API 中並沒有 "sqlite3column()" 這個函數。相反的,我們這裏調用的 "sqlite3_column()" 是爲了獲取某列中不同類型值的一簇的接口占位符(a place-holder for an entire family of functions)。這類接口中有返回結果大小(如果是字符串或者 BLOB,譯註:Binary Large OBject)還有結果集中列數的接口。

sqlite3_column_blob()  
sqlite3_column_bytes()  
sqlite3_column_bytes16()  
sqlite3_column_count()  
sqlite3_column_double()  
sqlite3_column_int()  
sqlite3_column_int64()  
sqlite3_column_text()  
sqlite3_column_text16()  
sqlite3_column_type()  
sqlite3_column_value()  

sqlite3finalize()    這個接口銷燬之前由 sqlite3prepare() 創建的 prepared statement。爲了避免內存泄露,必須這個接口銷燬之前創建的 prepared statement。

sqlite3close()    這個接口關閉之前由調用 sqlite3open() 創建的數據庫連接。在關閉數據庫連接前所有與之關聯的 prepared statements 都應該已經被銷燬了。

1.1 核心接口和對象的使用方法

一個想要使用 SQLite 的應用程序通常在初始化時使用 sqlite3open() 創建一個數據庫連接。注意 sqlite3open() 既可以用於打開一個現存的數據庫,也可以創建並打開一個新的數據庫。因爲許多的應用程序只使用一個數據庫連接,所以就沒有理由讓一個應用程序多次調用 sqlite3_open() 創建多個數據庫連接 - 同一個數據庫或者不同的數據庫。有時一個多線程的應用會爲不同的線程創建獨立的數據庫連接。注意,爲了訪問兩個或者多個數據庫也沒必要創建多個獨立的連接。一個單一的數據庫連接可以使用 ATTACH SQL 語句同時訪問兩個或者多個數據庫(譯註:http://sqlite.awardspace.info/syntax/sqlitepg12.htm)。

許多應用在關閉時調用 sqlite3_close() 銷燬它們的數據庫連接。比如,一個使用 SQLite 作爲它的應用程序文件格式(application file format)會在點擊 文件/打開(File/Open) 菜單時創建一個數據庫連接,在點擊 文件/關閉 (File/Close) 菜單時關閉這個連接。

要執行 SQL 語句,程序需要遵循以下幾步:

使用 **sqlite3_prepare()** 創建一個 prepared statement。      
通過一次或多次調用 **sqlite3_step()** 查詢 prepared statement 的結果。    
對於查詢來說,在調用 **sqlite3_step()** 後通過調用 **sqlite3_column()** 獲取結果。    
使用 **sqlite3_finalize()** 銷燬 prepared statement。    

上述都是爲了高效的使用 SQLite 讀者所需要知道的。其餘的都只是補充和細節。

2.0 核心 API 的便捷封裝

sqlite3exec() 是使用一次函數調用完成上述四種接口調用的便捷封裝。sqlite3exec() 在處理結果集的每行時調用傳入的回調函數。sqlite3gettable() 是另一個使用一次函數調用完成上述四種接口調用的便捷封裝。sqlite3gettable() 與sqlite3_exec() 的不同之處是將結果集保存在堆中而不是每次都調用回調函數。

需要注意的是 sqlite3exec() 和 sqlite3get_table() 都不能實現核心接口不能完成的事。事實上,這些封裝都是完全由核心接口實現的。

3.0 參數綁定與重用 Prepared Statements

在之前的討論中,都假設每個 SQL 語句都只准備一次( prepared once),執行(evaluated),然後銷燬。但是,SQLite 允許相同的 prepared statement 被執行多次。通過以下的方法實現:

sqlite3_reset()
sqlite3_bind()

sqlite3step() 執行一次或多次 prepared statement 後,通過 sqlite3reset() 可以重置並重新執行(evaluated)。對現存的 prepared statement 使用 sqlite3reset() 可以避免調用 sqlite3prepare() 創建一個新的 prepared statement。對於部分的 SQL 語句,調用 sqlite3prepare() 的時間和調用 sqlite3step() 一樣。所以避免調用sqlite3_prepare() 對性能提升有重大的影響。

通常不會對一個 SQL 語句執行(evaluate)多次。更常見的是,執行一個相似的語句。例如,你想通過執行多次 INSERT 語句插入不同的值。爲了實現類似的靈活性,SQLite 允許對一條 SQL 語句每次“綁定”不同的值。這些值之後可以改變,並且同樣的 prepared statement 使用新的值可以二次使用。(譯註:說白了就是對一個表一次插入多條數據,每次插入的不同的值在 SQL 語句中用通配符佔位)

在 SQLite 中,任何地方都允許插入字符串字面量(string literal),可以使用以下幾種形式:

?
?NNN
:AAA
$AAA
@AAA

在上面個的例子中,NNN 代表整型值( integer value ),AAA 是個標識符(identifier)(譯註:字母數字組合)。參數的初始值爲 NULL。在第一次調用sqlite3step() 之前或立即在調用 sqlite3reset() 之後,應用程序可以調用某個sqlite3bind() 接口綁定值到參數上。每次調用 sqlite3bind() 都會覆蓋之前綁定到相同參數的值。

應用可以按需要提前準備多個 SQL prepared statements 並按需要執行(evaluate)。沒有嚴格的限制 prepared statements 的數量。

4.0 配置 SQLite

默認的 SQLite 配置對於大部分的應用工作的都挺好的。但有時開發者想要優化設置項去嘗試壓榨出更多的性能,或者利用一些隱蔽的特性。

sqlite3config() 可以設置 SQLite 全局的,進程級(process-wide)的配置項。sqlite3config() 只能在數據庫連接建立後被調用。sqlite3_config() 允許程序員做以下的事情:

調整 SQLite 如何分配內存,包括爲安全敏感(safety-critical)的實時的嵌入式系統和應用程序定義的(application-defined)內存分配器設置爲可選的(alternative)內存分配器(memory allocators)。
設置一個進程級的錯誤日誌。
指定一個應用程序定義的頁緩存(page cache)。
調整 mutex 的使用,這樣就可以使用多種線程模型,或者替換一個程序定義的 mutex 系統。

在進程級的設置完成(configuration is complete)並且數據庫連接已經創建後,不同的數據庫連接可以通過調用 sqlite3limit() 和 sqlite3db_config() 配置。

5.0 擴展 SQLite

SQLite 包含可以擴展功能的接口。這些接口(routine)包括:

sqlite3_create_collation()  
sqlite3_create_function()  
sqlite3_create_module()  
sqlite3_vfs_register()  

sqlite3createcollation() 接口用於創建排序文字用的新的校對隊列(collating sequences)。sqlite3createmodule() 接口用於註冊新的虛表實現。sqlite3vfsregister() 創建一個新的 VFS(譯註:Virtual File System,虛擬文件系統)。

sqlite3createfunction() 接口用於創建新的 SQL 函數(function)—— scalar 函數或者 aggregate 函數(譯註:http://www.w3schools.com/sql/sql_functions.asp)。新的函數實現通常使用以下的額外接口:

sqlite3_aggregate_context()
sqlite3_result()
sqlite3_user_data()
sqlite3_value()

所有的 SQLite 內建 SQL 函數都使用的是這些接口創建的。可以參考 SQLite 的源文件,尤其是 date.c 和 func.c。

共享庫或者 DLL 可以作爲 SQLite 的可裝卸擴展(loadable extensions)(譯註:http://www.sqlite.org/cvstrac/wiki?p=LoadableExtensions)。

6.0 其他接口

這篇文章只提到了 SQLite 的一些基礎接口。SQLite 庫中還包含一些這裏沒有提到的有用的 API。可以在 SQLite 的 C/C++ 的接口說明中找到完整的函數列表(譯註:http://sqlite.org/c3ref/intro.html)。參考此文檔可以找到完整和權威的關於SQLite 接口的信息。(

轉載地址:http://blog.cocoabit.com/2014-08-27-sqlite-jie-kou-jie-shao/

發佈了18 篇原創文章 · 獲贊 11 · 訪問量 34萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章