數據查詢通常會帶有查詢條件,這可使用SQL語句的where子句實現,可是在程序中須要動態綁定參數給where子句。查詢數據的具體操做步驟以下所示。
(1) 使用sqlite3_open函數打開數據庫。
(2) 使用sqlite3_prepare_v2函數預處理SQL語句。
(3) 使用sqlite3_bind_text函數綁定參數。
(4) 使用sqlite3_step函數執行SQL語句,遍歷結果集。
(5) 使用sqlite3_column_text等函數提取字段數據。
(6) 使用sqlite3_finalize和sqlite3_close函數釋放資源。
NoteDAO.cpp中的NoteDAO::findById是按照主鍵查詢數據函數,相關代碼以下:
html
[html] view plaincopysql
ValueMap NoteDAO::findById(string pDate) 數據庫
{ 微信
//初始化數據庫 函數
initDB(); 網站
sqlite3* db= NULL; spa
ValueMap dict ; .net
string path = dbDirectoryFile(); 指針
if (sqlite3_open(path.c_str(), &db) != SQLITE_OK) { ① code
sqlite3_close(db);
CCASSERT(false, "DB open failure.");
} else {
string qsql = "SELECT cdate,content FROM Note where cdate =?";
sqlite3_stmt *statement;
//預處理過程
if (sqlite3_prepare_v2(db, qsql.c_str(), -1, &statement, NULL) == SQLITE_OK) { ②
//綁定參數開始
sqlite3_bind_text(statement, 1, pDate.c_str(), -1, NULL); ③
//執行
if (sqlite3_step(statement) == SQLITE_ROW) { ④
char *cdate = (char *)sqlite3_column_text(statement, 0); ⑤
char *content = (char *)sqlite3_column_text(statement, 1);
dict["date"] = Value(cdate);
dict["content"] = Value(content);
}
}
sqlite3_finalize(statement); ⑥
sqlite3_close(db); ⑦
}
return dict;
}
該函數執行了6個步驟,其中第(1)個步驟如代碼第①行所示,它與建立數據庫的第一個步驟同樣,這裏就再也不介紹了。
第(2)個步驟如代碼第②行所示,語句sqlite3_prepare_v2(db, qsql.c_str(), -1, &statement, NULL)是預處理SQL語句。預處理的目的是將SQL編譯成二進制代碼,提升SQL語句的執行速度。sqlite3_prepare_v2函數的第三個參數表示SQL字符串的長度,-1表示所有SQL字符串。第四個參數是sqlite3_stmt指針的地址,它是語句對象,經過語句對象能夠執行SQL語句,第五個參數是SQL語句沒有執行的部分語句。
第(3)個步驟如代碼第③行所示,語句sqlite3_bind_text(statement, 1, pDate.c_str(), -1, NULL)是綁定SQL語句的參數,其中第一個參數是statement指針,第二個參數爲序號(從1開始),第三個參數爲字符串值,第四個參數爲字符串長度,第五個參數爲一個函數指針。若是SQL語句中帶有問號,則這個問號(它是佔位符)就是要綁定的參數,示例代碼以下所示:
string qsql = "SELECT cdate,content FROM Note where cdate =?";
第(4)個步驟爲使用sqlite3_step(statement)執行SQL語句,如代碼第④行所示。若是sqlite3_step函數返回int類型(即等於SQLITE_ROW),則說明還要其它行數據沒有遍歷。
第(5)個步驟爲提取字段數據,如代碼第⑤行所示,它使用sqlite3_column_text(statement, 0)函數讀取字符串類型的字段。須要說明的是,sqlite3_column_text函數的第二個參數用於指定select字段的索引(從0開始)。讀取字段函數的選擇與字段類型有關係,SQLite3中相似的經常使用函數還有:
sqlite3_column_blob()
sqlite3_column_double()
sqlite3_column_int()
sqlite3_column_int64()
sqlite3_column_text()
sqlite3_column_text16()
關於其它API,讀者能夠參考http://www.sqlite.org/cintro.html。
第(6)個步驟是釋放資源,與建立數據庫過程不一樣。使用sqlite3_close函數關閉數據庫(見第⑦行)以前,還要使用sqlite3_finalize函數釋放語句對象statement,見代碼第⑥行所示。
NoteDAO.cpp中的NoteDAO::findAll()是查詢全部數據函數,相關代碼以下:
ValueVector NoteDAO::findAll()
[html] view plaincopy
{
//初始化數據庫
initDB();
sqlite3* db= NULL;
string path = dbDirectoryFile();
ValueVector listData;
if (sqlite3_open(path.c_str(), &db) != SQLITE_OK) {
sqlite3_close(db);
CCASSERT(false, "DB open failure.");
} else {
string qsql = "SELECT cdate,content FROM Note";
sqlite3_stmt *statement;
//預處理過程
if (sqlite3_prepare_v2(db, qsql.c_str(), -1, &statement, NULL) == SQLITE_OK) {
//執行
while (sqlite3_step(statement) == SQLITE_ROW) {
char *cdate = (char *)sqlite3_column_text(statement, 0);
char *content = (char *)sqlite3_column_text(statement, 1);
ValueMap dict ;
dict["date"] = Value(cdate);
dict["content"] = Value(content);
listData.push_back(Value(dict));
}
}
sqlite3_finalize(statement);
sqlite3_close(db);
}
return listData;
}
查詢全部數據函數與按照主鍵查詢數據函數相似,區別在於本函數沒有查詢條件不須要綁定參數。遍歷的時候使用while循環語句,不是if語句:
[html] view plaincopy
while (sqlite3_step(statement) == SQLITE_ROW) {
……
}
爲了可以調用NoteDAO中查詢函數findAll (),咱們須要在HelloWorldScene場景中調用。HelloWorldScene.cpp主要代碼以下:
[html] view plaincopy
void HelloWorld::OnClickMenu5(Ref* pSender)
{
auto arry = NoteDAO::findAll(); ①
for (auto& v: arry)
{
log("-----------------");
ValueMap row = v.asValueMap(); ②
string date = row["date"].asString(); ③
string content = row["content"].asString(); ④
log("===>date: : %s", date.c_str());
log("===>content: : %s", content.c_str());
}
}
HelloWorld::OnClickMenu5函數是玩家點擊Read Data菜單時候回調的函數。其中代碼第①行是調用NoteDAO中查詢全部函數findAll (),第②行代碼是把從列表中取出的元素v,轉換爲ValueMap字典類型。第③行代碼是從字典中取值date數據。第④行代碼是從字典中取值content數據。
更多內容請關注國內第一本Cocos2d-x 3.2版本圖書《Cocos2d-x實戰:C++卷》
本書交流討論網站:http://www.cocoagame.net
更多精彩視頻課程請關注智捷課堂Cocos課程:http://v.51work6.com
歡迎加入Cocos2d-x技術討論羣:257760386
歡迎關注智捷iOS課堂微信公共平臺