SQLite並沒有一次性做到位,只有下載這些東西是不能放在vs2010中並馬上使用的,下載下來的文件中有sqlite3.c/h/dll/def,還是不夠用的。我們需要的sqlite3.lib文件並不在其中,需要我們自己動手了。
這兒要用到visual studio提供的Visual Studio Command Prompt工具了。打開之後,進入含有sqlite3.dll和sqlite3.def的目錄下,輸入以下命令:
LIB /DEF:sqlite3.def /MACHINE:IX86
就能生成sqlite3.exp和sqlite3.lib文件了,這樣在工程中就可以加入lib文件進行編譯了。
SEC 1:
因為只是演示API,所以這次在vs2010下建立一個空的win32工程SQLite3Test,在工程的屬性-鏈接-輸入中添加sqlite3.lib的引用。添加新的文件main.cpp,寫一個main函數,並編譯一下。
好,接下來把sqlite3.h/def/exp/lib通通放進SQLite3Test\SQLite3Test\目錄下,跟main.cpp在一起,如圖:
把sqlite3.dll跟生成的exe放在一起。
SEC 2:
接下來開始進行sqlite3的使用。引入sqlite3.h頭文件,並寫下如下代碼:
#include <iostream>
#include "sqlite3.h"
using namespace std;
int main(int argc, char** argv)
{
sqlite3 * conn = NULL;
char * err_msg = NULL;
char sql[200] = "";
// 打開數據庫, 創建連接
if(sqlite3_open("test.db", &conn) != SQLITE_OK)
{
printf("無法打開!");
}
// 關閉連接。
if (sqlite3_close(conn) != SQLITE_OK)
{
printf("無法關閉,錯誤代碼: %s\n", sqlite3_errmsg(conn));
exit(-1);
}
printf("操作成功!\n");
return 0;
}
sqlite3_open的函數原型如下:
SQLITE_API int sqlite3_open(
const char *filename, /* Database filename (UTF-8) */
sqlite3 **ppDb /* OUT: SQLite db handle */
);
作用就不言而喻了,打開數據庫。
第一個參數是數據庫文件的名稱,如果沒有,那就會自動創建一個。
第二個參數是sqlite3的實例句柄的指針的指針。。(看到這兒我想起來,當時在linux下自己寫mysql的C++api的時候,也是用的雙重指針,搞死個人喲。。)
常言道:“有打開,就有關閉!”,所以sqlite3_close()就起了這個作用。
不過sqlite3_close的原型是這樣的:
SQLITE_API int sqlite3_close(sqlite3 *); //要格外注意雙重指針和普通指針。。
有了上面的萬金油例子,想必已經對初始化有所了解了。運行後就在Debug目錄下多了個test.db文件,不過大小為0KB,因為木有內容嘛!
SEC 3:
在數據庫中創建表並插入數據。在open和close的之間寫入如下代碼:
// 執行SQL
sprintf(sql, "CREATE TABLE test_for_cpp \
(id int, name varchar(20), age int)");
if (sqlite3_exec(conn, sql, NULL, NULL, &err_msg) != SQLITE_OK)
{
printf("操作失敗,錯誤代碼: %s", err_msg);
exit(-1);
}
//添加10條記錄
for (int i = 0; i < 10; i++)
{
// 執行SQL
sprintf(sql, "INSERT INTO test_for_cpp \
(id, name, age) VALUES \
(%d, '%s', %d)", i, "testPeople", i);
if (sqlite3_exec(conn, sql, NULL, NULL, &err_msg) != SQLITE_OK)
{
printf("操作失敗,錯誤代碼: %s", err_msg);
exit(-1);
}
}
sqlite3_exec的原型如下:
SQLITE_API int sqlite3_exec(
sqlite3*, /* An open database */
const char *sql, /* SQL to be evaluated */
int (*callback)(void*,int,char**,char**), /* Callback function */
void *, /* 1st argument to callback */
char **errmsg /* Error msg written here */
);
第一個參數為sqlite3實例。
第二個參數為要執行的sql語句。
第三個參數為回調函數的指針。因為這裡只是創建表和插入數據,並沒有數據返回,所以不需要填寫回調函數。以NULL代替。
第四個參數為回調函數所要使用的參數。同第三條。
第五個參數為錯誤信息。
這次再運行一下,就可以看到test.db已經不再是0KB了。
SEC 4:
再常言道:“有插入,就有讀取!”下面來讀取數據庫文件中的數據。
剛才提到了sqlite3_exec的回調函數,現在需要這個函數了。首先聲明一個回調函數:
int sqlite3_exec_callback(void *data, int nColumn,
char **colValues, char **colNames);
四個參數的類型不能變。
然後寫下該回調函數的實現:
int sqlite3_exec_callback(void *data, int nColumn, char **colValues, char **colNames)
{
for (int i = 0; i < nColumn; i++)
{
printf("%s\t", colValues[i]);
}
printf("\n");
return 0;
}
接下來在插入條目語句的後面寫下下面的語句:
// 查詢
sprintf(sql, "SELECT * FROM test_for_cpp");
sqlite3_exec(conn, sql, &sqlite3_exec_callback, 0, &err_msg);
TIP: 前面創建表、插入數據的代碼可以先注釋掉,否則運行一次就會插入10條數據,會造成點困擾。
運行就可以看到結果了:
因為該回調函數每從數據庫中取出一條數據就要調用一次,所以這是最耗時間的過程,這塊代碼應該盡量高效。
這只是一個簡單的例子,不過已經足夠平時的小眾軟件使用了。一些高級的用法比如sqlite3_db_mutex(讀寫互斥鎖)、sqlite3_backup_step(差異備份)等等,就可以看看sqlite3官方的教程了(猛戳傳送)。
作者:satanness