最近頻繁使用到 SQLite,越來越發現該數據庫的好用。SQLite 是一款開源、輕量、本地化存儲、功能強大的數據庫,由於它的這些特性,使得人們在項目中廣泛應用。
首先,你可能要去www.sqlite.org去下載一份 SQLite,可能是編好的,如果沒有,你可能需要自己去編一份,過程非常簡單。先來看看 SQLite 在工程中的使用。
它提供 sqlite3.h、sqlite3.lib、sqlite3.dll 這三份必需文件,我們只需在工程中含入 sqlite3.h,鏈入sqlite3.lib,在打包時提供 sqlite3.dll 副本即可,非常的簡單。而它的 API 接口也非常清晰好用,先來個總體介紹:
sqlite3 -- 數據庫連接
sqlite3_stmt -- SQL語句
sqlite3_open -- 打開數據庫,返回SQLITE_OK表示打開成功
sqlite3_close -- 關閉數據庫
sqlite3_key -- 爲數據庫設置加密Key,在sqlite3_open之後調用
sqlite3_rekey -- 更改數據庫的加密Key,如果之前數據庫未加密,則進行加密;如果兩個參數均爲0,則進行解密
sqlite3_exec -- 執行一條SQL語句,成功返回SQLITE_OK
sqlite3_sleep -- 將執行掛起一段時間
sqlite3_table_column_metadata -- 獲取表的某一列的屬性(類型、列名、是否爲null、是否是主鍵、是否是auto-increment)
sqlite3_prepare -- 準備SQL語句
sqlite3_finalize -- SQL語句執行完畢,進行銷燬釋放
sqlite3_db_handle -- 通過sqlite3_stmt獲取sqlite3指針
sqlite3_bind_int -- 綁定一個整數到SQL語句的某個參數
sqlite3_bind_double -- 綁定一個浮點數到SQL語句的某個參數
sqlite3_bind_text -- 綁定一個字符串到SQL語句的某個參數
sqlite3_bind_blob -- 綁定一個內存塊到SQL語句的某個參數
sqlite3_column_int -- 獲取查詢結果,按整型值返回
sqlite3_column_text -- 獲取查詢結果,按字符串返回
sqlite3_column_bolb -- 獲取查詢結果,按緩衝返回
sqlite3_column_bytes -- 獲取查詢結果某一列值的內存字節數,可結合sqlite3_column_blob使用
sqlite3_sql -- 查看sqlite3_stmt進行綁定後產生的SQL語句
sqlite3_bind_parameter_count -- 查看sqlite3_stmt的參數個數
sqlite3_bind_parameter_name -- 查看sqlite3_stmt的某個參數的列名
sqlite3_bind_parameter_index -- 查看sqlite3_stmt的某個列名對應的參數索引
sqlite3_clear_bindings -- 清除所有已綁定到sqlite3_stmt上的參數
sqlite3_reset -- 清除已綁定到sqlite3_stmt上的參數,但不清楚通過sqlite3_bind_blob綁定的參數
sqlite3_column_count -- 獲取查詢結果的列數
sqlite3_data_count -- 同上
sqlite3_column_type -- 獲取查詢結果中某一列的值類型
sqlite3_column_name -- 獲取查詢結果中某一索引對應的列名
sqlite3_column_database_name -- 獲取sqlite3_stmt執行對應的數據庫名
sqlite3_column_table_name -- 獲取sqlite3_stmt執行對應的表名
sqlite3_step -- 執行stmt語句,返回SQLITE_ROW表示查詢到數據,返回SQLITE_DONE表示成功,其他值爲失敗
sqlite3_changes -- 獲取執行SQL語句影響的行數,包括INSERT、UPDATE、DELETE,觸發器產生的不計在內
sqlite3_total_changes -- 同上,但包含觸發器產生的影響計數
sqlite3 和 sqlite3_stmt 均是結構體,我們需要用指針來操作。看起來 API 比較多,但只要理解了,就非常好用,這些 API 還有提供 V2 版本以及基於 UTF-16 的寬字符版本的,比如 sqlite3_open_v2、sqlite3_column_text16 等等,參數基本不變。下面看一個實際示例:
#include <sqlite/sqlite3.h>
#include <iostream>
#include <string>
using namespace std;
#pragma comment(lib, "sqlite3.lib")
sqlite3* OpenDatabase(const string& strDbFile)
{
sqlite3* pdb = 0;
sqlite3_open(strDbFile.c_str(), &pdb);
return pdb;
}
int main()
{
// 打開數據庫連接.
sqlite3* pDatabase = OpenDatabase("D:\\mytest.db");
if (!pDatabase)
{
return -1;
}
const char* const CREATE_TABLE =
"create table t_person("
"id integer primary key,"
"name varchar(50) not null,"
"age integer not null"
")";
// 創建表.
if (SQLITE_OK != sqlite3_exec(pDatabase, CREATE_TABLE, 0, 0, 0))
{
return -1;
}
string strName = "Bill Gates";
int age = 42;
// 準備 SQL 語句,參數用 ? 替代.
const char* const INSERT_STMT =
"insert into t_person values("
"null, ?, ?"
");";
sqlite3_stmt* pstmt = 0;
const char* pTail = 0;
sqlite3_prepare(pDatabase, INSERT_STMT, -1, &pstmt, &pTail);
if (!pstmt)
{
return -1;
}
// 綁定參數,第一個參數的索引爲 1 .以此類推.
sqlite3_bind_text(pstmt, 1, strName.c_str(), -1, SQLITE_STATIC);
sqlite3_bind_int(pstmt, 2, age);
if (SQLITE_DONE == sqlite3_step(pstmt))
{
cout<<"Add Person Successful!"<<endl;
}
// 銷燬釋放.
sqlite3_finalize(pstmt);
const char* const QUERY_STMT =
"select * from t_person;";
sqlite3_stmt* pQueryStmt = 0;
sqlite3_prepare(pDatabase, QUERY_STMT, -1, &pQueryStmt, &pTail);
if (pQueryStmt)
{
while (SQLITE_ROW == sqlite3_step(pQueryStmt))
{
// 獲取數據,第 1 列從 0 開始,以此類推.
int nPersonID = sqlite3_column_int(pQueryStmt, 0);
const unsinged char* pszPersonName = sqlite3_column_text(pQueryStmt, 1);
int nPersonAge = sqlite3_column_int(pQueryStmt, 2);
if (pszPersonName)
{
cout<<"ID: "<<nPersonID<<"\n"
<<"Name: "<<pszPersonName<<"\n"
<<"Age: "<<nPersonAge<<endl;
}
}
sqlite3_finalize(pQueryStmt);
}
// 關閉數據庫連接.
slqite3_close(pDatabase);
return 0;
}
看起來一副非常簡單的樣子,反正我是信了。SQLite 還支持事務的操作,你只需在要執行的操作前後加上事務語句即可:
sqlite3_exec("begin transaction;");
// 進行 INSERT、UPDATE、DELETE等多項操作
// ...
// ...
sqlite3_exec("commit transaction;");