iOS開發之SQLite--C語言介面規範(三)——Binding Values To Prepared Statements,sqlite--cbinding
在前面的部落格中已經介紹了如何串連SQLite資料庫,並且簡單的查詢和遍曆結果集。在前面用到了sqlite3_stmt *stmt,也就是先行編譯後的SQL語句。在本篇部落格中會瞭解一下sqlite3_stmt,然後瞭解一下變數的綁定。變數綁定,簡單的說就是往先行編譯後的SQL語句中傳入相應的值。
一. sqlite3_stmt 的生命週期
這個對象的執行個體代表著一個被編譯成二進位的SQL語句。每個SQL語句都必須經過先行編譯轉換成sqlite3_stmt才能被執行。在iOS開發中,Application或者UIViewController等都是有自己的生命週期的,先行編譯語句也是有自己的生命週期的,其生命週期如下:
1.sqlite3_stmt對象的生命起源於sqlite3_prepare_v2(), 使用sqlite3_prepare_v2()可以建立sqlite3_stmt對象。
2.使用sqlite3_bind_*()介面可以給sqlite3_stmt對象綁定變數。
3.調用sqlite3_step()一次或者多次來運行SQL語句。
4.調用sqlite3_reset()回到上一次執行的SQL語句,你可以調用sqlite3_reset()多次,sqlite3_reset()更像版本管理中的復原操作。
5.使用sqlite3_finalize()解構函式來釋放sqlite3_stmt對象。
sqlite3_stmt對象的建構函式(推薦使用“v2”介面):sqlite3_prepare(), sqlite3_prepare16(), sqlite3_prepare16_v2(), sqlite3_prepare_v2()
sqlite3_stmt對象的解構函式:sqlite3_finalize()
下方是有關sqlite3_stmt對象的介面,本篇部落客要介紹有關sqlite3_bind_*()的方法。
二、值綁定
先簡單介紹一下什麼是值綁定吧。用大白話說,值綁定就是在SQL語句先行編譯時把一些參數使用預留位置(這裡是?號)來代替,然後與程式中的變數進行綁定。類似於字串的格式化。如果你之前搞過Java的JDBC或者PHP, 在他們操作資料庫執行SQL語句時都有類似值綁定的一個概念。 就是把外界變數把SQL語句佔位的值進行替換。值綁定經常在SELECT,INSERT,UPDATE等語句中進行使用。
1.為先行編譯SQL語句綁定變數,綁定不同類型變數需要不同的綁定介面,下方是常用的綁定變數的介面。
2.在sqlite3_prepare_v2()輸入的SQL語句的文本中,下面的這些參數將會被替換掉,在下面的參數中,NNN表示一個整數(這個整數就代表這個參數的索引),VVV代表一個字母標示符(參數的名字)。可以使用sqlite3_bind_*()函數為上面的這些預留位置進行賦值。
說的直白一些,“?”號就是匿名參數,從第一個問號出現往後的索引預設是1,往後以此類推。而“?NNN”是為匿名參數指定索引,你可以這樣寫“?1” , "?2"等,而:VVV, @VVV, $VVV這些就是有名參數了,VVV就是參數的名字。比如:ludashi, @ludashi, $ludashi。
下面的執行個體給出了參數不同的幾種表現形式, 前一種是匿名參數,後邊參數就有自己的名字了。
3.sqlite3_bind_*()參數介紹(這些綁定函數執行成功後回返回SQLITE_OK, 執行不成功的話回返回相應的錯誤碼)
(1) sqlite3_bind_*()的第一個參數是含有上述預留位置先行編譯後的語句指標,也就是sqlite3_stmt的對象。
(2) sqlite3_bind_*()的第二個參數是SQL語句中參數的索引,例如第一個參數的索引值是1,那麼就傳1。匿名參數的索引是從1開始往後遞增的,而有參數名稱的可以通過sqlite3_bind_parameter_index()介面傳入參數名稱來擷取該參數的索引,sqlite3_bind_parameter_index()用法如下,第一個參數是sqlite3_stmt的對象,而後邊的參數是SQL參數名稱,傳回值就是該參數的索引。
int index = sqlite3_bind_parameter_index(statement, "$brandidMin");
(3) 第三個參數是要綁定的值。
(4) sqlite3_bind_blob(), sqlite3_bind_text()和sqlite3_bind_text16()這三個介面中還有有第四和第五個參數,第四個參數代表第三個參數“綁定值”的位元組長度。第五個參數是一個指向記憶體管理回呼函數的指標。
4.每個綁定函數的使用情境
(1) BLOB是資料庫中儲存大資料的一種資料類型,它是以二進位的形式來儲存資料的。
1 SQLITE_API int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
(2) 顧名思義,下面的方法是綁定double類型的資料的
1 SQLITE_API int sqlite3_bind_double(sqlite3_stmt*, int, double);
(3) 綁定一個32位的整型值
1 SQLITE_API int sqlite3_bind_int(sqlite3_stmt*, int, int);
(4) 綁定一個64位的整型值
1 SQLITE_API int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
(5)綁定一個NULL的值(在資料庫中可以為NULL)
1 SQLITE_API int sqlite3_bind_null(sqlite3_stmt*, int);
(6)綁定一個UTF-8編碼的字串,第四個參數上面也提到了,是綁定字串的長度,如果為負值的話,就是傳多少就綁定多少。
1 SQLITE_API int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*));
(7)綁定一個UTF-16編碼的字串,第四個參數上面也提到了,是綁定字串的長度,如果為負值的話,就是傳多少就綁定多少。
1 SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
(8) 綁定sqlite3_value結構體類型的值,sqlite3_value結構體可以儲存任意格式的資料。
SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
(9)綁定一個任意長度的BLOB類型的位元據,它的每一個位元組被置0。第3個參數是位元組長度。這個函數的特殊用處是,建立一個大的BLOB對象,之後可以通過BLOB介面函數進行更新。
1 SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
5.值綁定常用工具函數
(1)下方的函數返回先行編譯SQL語句中參數的個數,這些參數可以是匿名參數,也可以是有名參數。
具體用法如下:
1 int count = sqlite3_bind_parameter_count(statement);2 NSLog(@"%d", count);
(2)通過索引擷取對應參數的名稱
具體用法如下:
1 const char * name = sqlite3_bind_parameter_name(statement, 1);2 NSLog(@"%s", name);
(3) 在一個是通過名字擷取索引了,正好和上面的方法相反。
調用方式如下:
1 int index = sqlite3_bind_parameter_index(statement, ":brandidMax");2 NSLog(@":brandidMax——index = %d", index);
三、值綁定執行個體
下面的執行個體是在查詢語句中使用值綁定,綁定完值後,調用查詢資料庫的方法,然後進行數值的輸出,因為上面說的夠多了,下面的代碼就不用加註釋了。
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 }
查詢資料庫的方法
1 //查詢資料庫 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 }
輸入結果如下:
今天部落格就先到這兒,關於SQLite資料庫的東西會繼續更新。