本文簡述了SQLite的概念,並詳細描述了SQLite在Linux和Windows平台下的編譯方法
關於 SQLite
SQLite是一個進程內的庫,實現了自給自足的、無服務器的、零配置的、事務性的 SQL 數據庫引擎。它是一個零配置的數據庫,這意味着與其他數據庫一樣,您不需要在系統中配置。
就像其他數據庫,SQLite 引擎不是一個獨立的進程,可以按應用程序需求進行靜態或動態連接。SQLite 直接訪問其存儲文件。
SQLite3命令
與關系數據庫進行交互的標准 SQLite 命令類似於 SQL。命令包括 CREATE、SELECT、INSERT、UPDATE、DELETE 和 DROP。這些命令基於它們的操作性質可分為以下幾種:
DDL - 數據定義語言
命 令 | 描 述 |
CREATE | 創建一個新的表,一個表的視圖,或者數據庫中的其他對象。 |
ALTER | 修改數據庫中的某個已有的數據庫對象,比如一個表 |
DROP | 刪除整個表,或者表的視圖,或者數據庫中的其他對象 |
DML - 數據操作語言
命 令 | 描 述 |
INSERT | 創建一條記錄 |
UPDATE | 修改記錄 |
DELETE | 刪除記錄 |
DQL - 數據查詢語言
命 令 | 描 述 |
SELECT | 從一個或多個表中檢索某些記錄 |
SQLite3的源碼
關於SQLite3的源碼下載請移步SQLite官網下載:
SQLite3 在Linux下的編譯
本文的編譯環境如下:
編譯命令行管理工具
關於libsqlite3.so共享庫的編譯與使用
編譯
-fPIC:PIC(Position-Independent Code),表示編譯為位置獨立的代碼,在產生的代碼中,沒有絕對地址,全部使用相對地址,因此代碼可以被加載至內存的任意位置。不用此選項的話編譯后的代碼是位置相關的,再加載時根據加載到的位置再次重定位.所以動態載入時是通過代碼拷貝的方式來滿足不同進程的需要,而不能達到真正代碼段共享的目的。
-shared:表示生成一個共享目標文件(讓連接器生成T類型的導出符號表,有時候也生成弱連接W類型的導出符號),即我們所說的共享庫(動態鏈接庫)。它可以和其他目標文件連接產生可執行文件。只有部分系統支持該選項。
-lpthread:用於確保SQLite是線程安全的。但因為命令行工具是單線程的,對命令行工具則可編譯成非線程安全的,可以忽略pthread庫。
-ldl:用於支持動態裝載,sqlite3_load_extension()接口和SQL函數load_extension()需要用到它。如果不需要這些特性,可以使用SQLITE_OMIT_LOAD_EXTENSION編譯選項來忽略
使用
在你的程序中(例如test.c)通過包含頭文件sqlite3.h來使用庫中的函數,編譯程序的命令為
-L. : 告訴編譯器在當前目錄(.)中查找共享函數庫
-lsqlite3: 指明編譯器查找共享庫libsqlite3.so,編譯器查找共享庫時有隱含的命名規則,即在給出的名字前面加上lib,后面加上.so來確定庫的名稱。
通過ldd test可查看test程序是如何調用共享庫中的函數的,當未指定LD_LIBRARY_PATH時,共享庫libsqlite3.so是找不到的。
編譯和使用靜態庫
-static:添加static后會將庫也包含在目標文件中,使得目標文件體積非常大,下圖為兩者的區別
note: 關於ar命令
ar [-]p[mod] [……] archive [member...]
p:該參數描述了接下來要執行的操作,具體操作命令如下,但在單次命令執行過程中,只能選擇其中一個
參 數 |
描 述 |
參 數 |
描 述 |
d |
從文件包中刪除文件 |
r |
在文件包中代替文件 |
m |
從文件包中移動文件到包尾 |
t |
列出包中文件名為files指明的文件名的文件內容 |
p |
打印出文件包中的文件 |
x |
從文件包中解壓出文件名為files指明的文件 |
q |
在文件包尾加入文件 |
[mod]:若干關鍵字跟隨在p參數后,用於描述施加在操作行為上的變化
參 數 |
描 述 |
參 數 |
描 述 |
a |
與r或m共同使用來將files指明的文件放置於posname之后 |
s |
強制重新生成文件包的符號表 |
b |
與a作用相同,但是是在posname之前使用 |
T |
只在Solaris中有這個參數.在不支持長文件名的文件系統中減短長文件名. 沒有這個操作的話,長文件的解壓結果是錯誤的 |
c |
無提示模式創建文件包 |
u |
與r共同使用,用來僅取代那些在生成文件包之后改動過的文件 |
i |
與b相同 |
v |
細節化,並打印一個文件包的描述 |
note: 當靜態庫與共享庫同名時,優先使用共享庫
SQLite在windows下編譯(VS2019)
靜態編譯庫文件
創建新項目
將下載的文件添加到項目中,本項目配置選用Release, x64版本
增加預處理定義
_USRDLL
SQLITE_ENABLE_RTREE
SQLITE_ENABLE_COLUMN_METADATA
SQLITE_ENABLE_FTS5
SQLITE_ENABLE_UNLOCK_NOTIFY
添加並修改模板定義文件 sqlite3.def
修改模塊定義文件:在最后追加 sqlite3_unlock_notify
配置類型改為靜態庫lib
生成解決方案
在項目路徑的\x64\Release文件下,即可找到.lib文件
創建測試工程
將上一步生成的.lib文件,連同sqlite3.h和sqlite3ext.h共同添加到項目當中
設置頭文件包含路徑及庫路徑,此處的路徑分別為頭文件(sqlite3.h和sqlite3ext.h)存放路徑和庫文件(.lib)存放路徑
編輯測試代碼
添加main.cpp文件,編輯測試代碼
1 #include <stdio.h> 2 #include "sqlite3.h" 3 #pragma comment(lib,"test_sqlite_lib") 4 5 /* print a record from table outputed by sql statement */ 6 static int callback(void* NotUsed, int argc, char** argv, char** azColName) { 7 int i; 8 for (i = 0; i < argc; i++) { 9 printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL"); 10 } 11 printf("\n"); 12 return 0; 13 } 14 15 int main(int argc, char** argv) { 16 sqlite3* db; 17 char* zErrMsg = 0; 18 int rc; 19 20 if (argc != 3) { 21 fprintf(stderr, "Usage: %s DATABASE SQL-STATEMENT\n", argv[0]); 22 return(1); 23 } 24 rc = sqlite3_open(argv[1], &db); /* open database */ 25 if (rc) { 26 fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db)); 27 sqlite3_close(db); 28 return(1); 29 } 30 rc = sqlite3_exec(db, argv[2], callback, 0, &zErrMsg); /* execute SQL statement */ 31 if (rc != SQLITE_OK) { 32 fprintf(stderr, "SQL error: %s\n", zErrMsg); 33 sqlite3_free(zErrMsg); 34 } 35 sqlite3_close(db); /* close database */ 36 return 0; 37 }
編譯后生成test_sqlite.exe程序,它的運行依賴於sqlite3.dll。注意程序中也可以不使用pragma指令導入sqlite3.lib,而是在test項目屬性中添加對上面的dll項目sqlit3的引用。
這個C程序的例子顯示怎么使用sqlite的C/C++接口。數據庫的名字由第一個參數取得,第二個參數是一條或更多的SQL執行語句。這個程序調用sqlite3_open()打開指定的數據庫,調用sqlite3_exec()對數據庫執行SQL語句,callback函數會作用在SQL語句結果集的每條記錄上。最后用sqlite3_close()關閉數據庫連接。
編譯並執行
在VS環境實測過程中,在工具選項卡中打開命令行,在.exe文件路徑下執行以下命令即可
主要參考: