在前面的博客中已經(jīng)介紹了如何連接SQLite數(shù)據(jù)庫(kù),并且簡(jiǎn)單的查詢和遍歷結(jié)果集。在前面用到了sqlite3_stmt *stmt,也就是預(yù)編譯后的SQL語(yǔ)句。在本篇博客中會(huì)了解一下sqlite3_stmt,然后了解一下變量的綁定。變量綁定,簡(jiǎn)單的說(shuō)就是往預(yù)編譯后的SQL語(yǔ)句中傳入相應(yīng)的值。
一. sqlite3_stmt 的生命周期
這個(gè)對(duì)象的實(shí)例代表著一個(gè)被編譯成二進(jìn)制的SQL語(yǔ)句。每個(gè)SQL語(yǔ)句都必須經(jīng)過(guò)預(yù)編譯轉(zhuǎn)換成sqlite3_stmt才能被執(zhí)行。在iOS開(kāi)發(fā)中,application或者UIViewController等都是有自己的生命周期的,預(yù)編譯語(yǔ)句也是有自己的生命周期的,其生命周期如下:
1.sqlite3_stmt對(duì)象的生命起源于sqlite3_PRepare_v2(), 使用sqlite3_prepare_v2()可以創(chuàng)建sqlite3_stmt對(duì)象。
2.使用sqlite3_bind_*()接口可以給sqlite3_stmt對(duì)象綁定變量。
3.調(diào)用sqlite3_step()一次或者多次來(lái)運(yùn)行SQL語(yǔ)句。
4.調(diào)用sqlite3_reset()回到上一次執(zhí)行的SQL語(yǔ)句,你可以調(diào)用sqlite3_reset()多次,sqlite3_reset()更像版本管理中的回滾操作。
5.使用sqlite3_finalize()析構(gòu)函數(shù)來(lái)釋放sqlite3_stmt對(duì)象。
sqlite3_stmt對(duì)象的構(gòu)造函數(shù)(推薦使用“v2”接口):sqlite3_prepare(), sqlite3_prepare16(), sqlite3_prepare16_v2(), sqlite3_prepare_v2()
sqlite3_stmt對(duì)象的析構(gòu)函數(shù):sqlite3_finalize()
下方是有關(guān)sqlite3_stmt對(duì)象的接口,本篇博客主要介紹有關(guān)sqlite3_bind_*()的方法。

二、值綁定
先簡(jiǎn)單介紹一下什么是值綁定吧。用大白話說(shuō),值綁定就是在SQL語(yǔ)句預(yù)編譯時(shí)把一些參數(shù)使用占位符(這里是?號(hào))來(lái)代替,然后與程序中的變量進(jìn)行綁定。類似于字符串的格式化。如果你之前搞過(guò)java的JDBC或者php, 在他們操作數(shù)據(jù)庫(kù)執(zhí)行SQL語(yǔ)句時(shí)都有類似值綁定的一個(gè)概念。 就是把外界變量把SQL語(yǔ)句占位的值進(jìn)行替換。值綁定經(jīng)常在SELECT,INSERT,UPDATE等語(yǔ)句中進(jìn)行使用。
1.為預(yù)編譯SQL語(yǔ)句綁定變量,綁定不同類型變量需要不同的綁定接口,下方是常用的綁定變量的接口。

2.在sqlite3_prepare_v2()輸入的SQL語(yǔ)句的文本中,下面的這些參數(shù)將會(huì)被替換掉,在下面的參數(shù)中,NNN表示一個(gè)整數(shù)(這個(gè)整數(shù)就代表這個(gè)參數(shù)的索引),VVV代表一個(gè)字母標(biāo)示符(參數(shù)的名字)。可以使用sqlite3_bind_*()函數(shù)為上面的這些占位符進(jìn)行賦值。

說(shuō)的直白一些,“?”號(hào)就是匿名參數(shù),從第一個(gè)問(wèn)號(hào)出現(xiàn)往后的索引默認(rèn)是1,往后以此類推。而“?NNN”是為匿名參數(shù)指定索引,你可以這樣寫(xiě)“?1” , "?2"等,而:VVV, @VVV, $VVV這些就是有名參數(shù)了,VVV就是參數(shù)的名字。比如:ludashi, @ludashi, $ludashi。
下面的實(shí)例給出了參數(shù)不同的幾種表現(xiàn)形式, 前一種是匿名參數(shù),后邊參數(shù)就有自己的名字了。

3.sqlite3_bind_*()參數(shù)介紹(這些綁定函數(shù)執(zhí)行成功后回返回SQLITE_OK, 執(zhí)行不成功的話回返回相應(yīng)的錯(cuò)誤代碼)
(1) sqlite3_bind_*()的第一個(gè)參數(shù)是含有上述占位符預(yù)編譯后的語(yǔ)句指針,也就是sqlite3_stmt的對(duì)象。
(2) sqlite3_bind_*()的第二個(gè)參數(shù)是SQL語(yǔ)句中參數(shù)的索引,例如第一個(gè)參數(shù)的索引值是1,那么就傳1。匿名參數(shù)的索引是從1開(kāi)始往后遞增的,而有參數(shù)名稱的可以通過(guò)sqlite3_bind_parameter_index()接口傳入?yún)?shù)名稱來(lái)獲取該參數(shù)的索引,sqlite3_bind_parameter_index()用法如下,第一個(gè)參數(shù)是sqlite3_stmt的對(duì)象,而后邊的參數(shù)是SQL參數(shù)名稱,返回值就是該參數(shù)的索引。
int index = sqlite3_bind_parameter_index(statement, "$brandidMin");
(3) 第三個(gè)參數(shù)是要綁定的值。
(4) sqlite3_bind_blob(), sqlite3_bind_text()和sqlite3_bind_text16()這三個(gè)接口中還有有第四和第五個(gè)參數(shù),第四個(gè)參數(shù)代表第三個(gè)參數(shù)“綁定值”的字節(jié)長(zhǎng)度。第五個(gè)參數(shù)是一個(gè)指向內(nèi)存管理回調(diào)函數(shù)的指針。
4.每個(gè)綁定函數(shù)的使用場(chǎng)景
(1) BLOB是數(shù)據(jù)庫(kù)中存儲(chǔ)大數(shù)據(jù)的一種數(shù)據(jù)類型,它是以二進(jìn)制的形式來(lái)存儲(chǔ)數(shù)據(jù)的。
1 SQLITE_API int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
(2) 顧名思義,下面的方法是綁定double類型的數(shù)據(jù)的
1 SQLITE_API int sqlite3_bind_double(sqlite3_stmt*, int, double);
(3) 綁定一個(gè)32位的整型值
1 SQLITE_API int sqlite3_bind_int(sqlite3_stmt*, int, int);
(4) 綁定一個(gè)64位的整型值
1 SQLITE_API int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
(5)綁定一個(gè)NULL的值(在數(shù)據(jù)庫(kù)中可以為NULL)
1 SQLITE_API int sqlite3_bind_null(sqlite3_stmt*, int);
(6)綁定一個(gè)UTF-8編碼的字符串,第四個(gè)參數(shù)上面也提到了,是綁定字符串的長(zhǎng)度,如果為負(fù)值的話,就是傳多少就綁定多少。
1 SQLITE_API int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*));
(7)綁定一個(gè)UTF-16編碼的字符串,第四個(gè)參數(shù)上面也提到了,是綁定字符串的長(zhǎng)度,如果為負(fù)值的話,就是傳多少就綁定多少。
1 SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
(8) 綁定sqlite3_value結(jié)構(gòu)體類型的值,sqlite3_value結(jié)構(gòu)體可以保存任意格式的數(shù)據(jù)。
SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
(9)綁定一個(gè)任意長(zhǎng)度的BLOB類型的二進(jìn)制數(shù)據(jù),它的每一個(gè)字節(jié)被置0。第3個(gè)參數(shù)是字節(jié)長(zhǎng)度。這個(gè)函數(shù)的特殊用處是,創(chuàng)建一個(gè)大的BLOB對(duì)象,之后可以通過(guò)BLOB接口函數(shù)進(jìn)行更新。
1 SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
5.值綁定常用工具函數(shù)
(1)下方的函數(shù)返回預(yù)編譯SQL語(yǔ)句中參數(shù)的個(gè)數(shù),這些參數(shù)可以是匿名參數(shù),也可以是有名參數(shù)。

具體用法如下:
1 int count = sqlite3_bind_parameter_count(statement);2 NSLog(@"%d", count);
(2)通過(guò)索引獲取對(duì)應(yīng)參數(shù)的名稱

具體用法如下:
1 const char * name = sqlite3_bind_parameter_name(statement, 1);2 NSLog(@"%s", name);
(3) 在一個(gè)是通過(guò)名字獲取索引了,正好和上面的方法相反。

調(diào)用方式如下:
1 int index = sqlite3_bind_parameter_index(statement, ":brandidMax");2 NSLog(@":brandidMax——index = %d", index);
三、值綁定實(shí)例
下面的實(shí)例是在查詢語(yǔ)句中使用值綁定,綁定完值后,調(diào)用查詢數(shù)據(jù)庫(kù)的方法,然后進(jìn)行數(shù)值的輸出,因?yàn)樯厦嬲f(shuō)的夠多了,下面的代碼就不用加注釋了。
1 -(void) qureyInfoWithDataBase2: (sqlite3 *) database{ 2 3 NSString * qureyInfo = @"SELECT * FROM CARBRAND WHERE BRANDID > :brandidMin AND BRANDID < :brandidMax"; 4 5 sqlite3_stmt *statement; 6 7 const char * zSql = [qureyInfo UTF8String]; 8 9 int result = sqlite3_prepare_v2(database, zSql, -1, &statement, nil);10 11 int count = sqlite3_bind_parameter_count(statement);12 NSLog(@"count = %d", count);13 14 const char * name = sqlite3_bind_parameter_name(statement, 1);15 NSLog(@"name = %s", name);16 17 if (result == SQLITE_OK) {18 19 int index = sqlite3_bind_parameter_index(statement, ":brandidMax");20 NSLog(@":brandidMax_index = %d", index);21 22 //值綁定23 sqlite3_bind_int(statement, 1, 180);24 sqlite3_bind_int(statement, 2, 200);25 26 [self queryUserInfoWith: database WithStatement: statement];27 }28 29 }
查詢數(shù)據(jù)庫(kù)的方法
1 //查詢數(shù)據(jù)庫(kù) 2 - (void) queryUserInfoWith: (sqlite3 *) database WithStatement: (sqlite3_stmt *) statement { 3 4 while (sqlite3_step(statement) == SQLITE_ROW) { 5 6 int rowNum = sqlite3_column_int(statement, 0); 7 8 char *rowDataOne = (char *) sqlite3_column_text(statement, 1); 9 10 char *rowDataTow = (char *) sqlite3_column_text(statement, 2);11 12 NSString *nameString = [NSString stringWithUTF8String:rowDataOne];13 14 NSString *firstLetterString = [NSString stringWithUTF8String:rowDataTow];15 16 NSLog(@"BrandId = %d, Name = %@, FirstLetter = %@",rowNum , nameString, firstLetterString);17 18 }19 sqlite3_finalize(statement);20 21 }
輸入結(jié)果如下:

今天博客就先到這兒,關(guān)于SQLite數(shù)據(jù)庫(kù)的東西會(huì)繼續(xù)更新。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注