1. 概述
SQLite是一個嵌入式SQL數據庫引擎。與大多數其他 SQL 數據庫不同,SQLite 沒有單獨的服務器進程。SQLite 直接讀寫普通磁盤文件。具有多個表、索引、觸發器和視圖的完整SQL數據庫包含在單個磁盤文件中。
SQLite比MySQL還要輕量級,官方提供的程序包大約1MB。但是這麼小的內容居然也是一個關係型數據庫,所以SQLite也很適合作爲入門數據庫。其中,SQL最基礎的功能就是查詢了。
2. 詳論
2.1. 打開/關閉數據庫
使用數據庫的第一步當然是打開數據庫了。對於C接口來說,通常的實現是提供一個打開的接口,得到一個句柄或者指針,然後通過這個句柄或者指針進行進一步操作,包括關閉數據庫操作。SQLite正是這麼設計的:
int nRes = sqlite3_open("D:/test.db", &pDB);
if (nRes != SQLITE_OK) {
cout << "Open database fail: " << sqlite3_errmsg(pDB);
return 1;
}
sqlite3_close(pDB);
通過sqlite3_open()這個函數打開數據庫文件,如果數據庫.db文件不存在,則會創建這個文件文件。一旦創建成功,在程序結束時最好調用sqlite3_close()這個函數進行關閉,否則會內存泄漏。如果需要更加精細的打開數據庫文件控制,最好使用sqlite3_open_v2()這個接口:
int flags =
SQLITE_OPEN_READWRITE | SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_SHAREDCACHE;
int nRes = sqlite3_open_v2("D:/test.db", &pDB, flags, nullptr);
sqlite3_open_v2()提供了很多打開數據庫文件時的配置,例如如果需要在數據庫文件不存在時進行創建,可以再加上SQLITE_OPEN_CREATE。
2.2. 數據查詢
如果在可視化管理工具(例如SQLite Expert)中,無論是查詢、插入、修改或者刪除操作,都是直接輸入SQL語句,然後執行運行操作,就可以得到相應的結果。SQLite也有這樣的接口sqlite3_exec(),例如我們查詢一個表中所有的數據:
char* cErrMsg;
int res =
sqlite3_exec(pDB, "select * from metadata;", ResultCallBack, 0, &cErrMsg);
if (res != SQLITE_OK) {
cout << "select fail: " << cErrMsg << endl;
return false;
}
sqlite3_free(cErrMsg);
sqlite3_exec()是一個回調函數,每查詢到一行數據就調用一次:
int ResultCallBack(void* NotUsed, int argc, char** argv,
char** azColName) {
for (int i = 0; i < argc; i++) {
cout << azColName[i] << " = " << (argv[i] ? argv[i] : "NULL") << ", ";
}
cout << endl;
return 0;
}
如果需要進行更加細粒度的控制,那麼一個合適的做法是使用statement(語句)。首先,我們將我們需要的sql語句編譯成數據庫引擎識別的字節碼,這個步驟可以叫做prepare(準備):
sqlite3_stmt* statement = nullptr;
int ret = sqlite3_prepare_v2(pDB, sqlStr, -1, &statement, nullptr);
if (ret != SQLITE_OK) {
printf("prepare error ret : %d\n", ret);
return 1;
}
接着,就是執行準備好的SQL語句:
while (sqlite3_step(statement) == SQLITE_ROW) {
//...
}
sqlite3_setp()每次查詢一行記錄,並且返回SQLITE_ROW;知道查詢完成,就返回SQLIET_DONE。通過這種方式實現了一種類似迭代器的操作,循環遍歷每個查詢結果。
最後,我們對每一行查詢的結果進行解析:
while (sqlite3_step(statement) == SQLITE_ROW) {
cout << sqlite3_data_count(statement) << '\n';
cout << sqlite3_column_text(statement, 0) << '\t'
<< sqlite3_column_text(statement, 1) << '\n';
}
sqlite3_column_X是一系列函數,可以直接獲取每一行相應列的數據類型。例如獲取整型就是sqlite3_column_int。
另外,不要忘了關閉這個語句:
sqlite3_finalize(statement);