免費開源的iOS開發學習平臺

FMDB:2-更新操作與查詢操作

在FMDB中,把對數據庫的操作合并為兩類,第一類是查詢操作,即使用SELECT語句執行的操作,查詢操作的特點是會返回查詢結果,繼而對查詢結果做進一步的處理;第二類是更新操作,凡是涉及到更新數據庫存儲內容的操作都屬于更新操作,例如在SQL中的UPDATE語句、INSERT語句等。

更新操作

在SQL語句中,所有非SELECT語句的都可以看成是更新操作,包括CREATE、UPDATE、INSERT、ALTER、DELETE、DROP等語句。在FMDB中,提供了executeUpdate:方法用于執行更新操作,需要執行的SQL語句作為參數傳入該方法中。

- (BOOL)executeUpdate:(NSString*)sql, ...;

執行更新語句會返回一個BOOL值。如果是YES則表示更新成功,如果是NO則表示更新失敗??梢哉{用lastErrorMessage和lastErrorCode方法來獲取失敗的原因。

- (NSString*)lastErrorMessage;
- (int)lastErrorCode;

查詢操作

在FMDB中,執行的SELECT語句對應查詢操作。所有的查詢操作可以通過executeQuery:方法來執行,并且查詢結果會作為該方法的返回值。

- (FMResultSet *)executeQuery:(NSString*)sql, ...;

執行查詢語句之后,如果成功會返回一個FMResultSet對象。如果失敗會返回nil,我們同樣可以調用lastErrorMessage和lastErrorCode方法來獲取失敗的原因。

為了遍歷查詢的結果集,需要使用while()循環。并且調用FMResultSet類的next方法,從一條記錄移動到下一條記錄。例如:

FMResultSet *s = [db executeQuery:@"SELECT * FROM myTable"];
while ([s next]) {
    //可以獲取到每條查詢記錄的值
}

FMResultSet有很多方法來獲取對應的值,主要包括兩類,第一類是通過列名獲取對應的值,第二類是通過列序號獲取對應的值。例如,FMResultSet.h中提供了如下根據列名獲取數值的方法:

  • intForColumn:
  • longForColumn:
  • longLongIntForColumn:
  • boolForColumn:
  • doubleForColumn:
  • stringForColumn:
  • dateForColumn:
  • dataForColumn:
  • dataNoCopyForColumn:
  • UTF8StringForColumnName:
  • objectForColumnName:

同樣也有{type}ForColumnIndex:方法來根據列序號獲取不同的值。這些方法能通過位置,而不是通過列名來獲取相對應的值。

通常來說我們不用手動調用FMResultSet的close方法。FMResultSet對象銷毀或者數據庫關閉時會自動調用FMResultSet的-close方法。

執行多條語句

當我們需要執行多條SQL語句時,FMDB也為我們提供了快捷方法,并不需要一條一條的執行??梢酝ㄟ^FMDatabase類中的executeStatements:方法來執行多條語句。

- (BOOL)executeStatements:(NSString *)sql;
- (BOOL)executeStatements:(NSString *)sql withResultBlock:(FMDBExecuteStatementsCallbackBlock)block;

下方的示例代碼中,我們把多條SQL語句都封裝在一個NSString類型的對象中執行。

NSString *sql = @"create table bulktest1 (id integer primary key autoincrement, x text);"
                 "create table bulktest2 (id integer primary key autoincrement, y text);"
                 "create table bulktest3 (id integer primary key autoincrement, z text);"
                 "insert into bulktest1 (x) values ('XXX');"
                 "insert into bulktest2 (y) values ('YYY');"
                 "insert into bulktest3 (z) values ('ZZZ');";

success = [db executeStatements:sql];

sql = @"select count(*) as count from bulktest1;"
       "select count(*) as count from bulktest2;"
       "select count(*) as count from bulktest3;";

success = [self.db executeStatements:sql withResultBlock:^int(NSDictionary *dictionary) {
    NSInteger count = [dictionary[@"count"] integerValue];
    XCTAssertEqual(count, 1, @"expected one record for dictionary %@", dictionary);
    return 0;
}];

SQL語句格式處理

在編寫SQL語句時不必手動去拼接,可以使用標準的SQLite綁定語法:

INSERT INTO myTable VALUES (?, ?, ?, ?)

這樣拼接SQL語句會更安全。?表示一個占位符,會被后續傳進來的值所替代。所有的執行方法都接受一組參數(比如NSArray,NSDictionary或者va_list),然后會做一些適當的轉義。

NSInteger identifier = 42;
NSString *name = @"Liam O'Flaherty (\"the famous Irish author\")";
NSDate *date = [NSDate date];
NSString *comment = nil;

BOOL success = [db executeUpdate:@"INSERT INTO authors (identifier, name, date, comment) VALUES (?, ?, ?, ?)", @(identifier), name, date, comment ?: [NSNull null]];
if (!success) {
    NSLog(@"error = %@", [db lastErrorMessage]);
}

注意:替換?的參數需要是對象,不可以是值類型。比如NSInteger需要變成NSNumber, NULL需要變成[NSNULL null]。

示例代碼

https://github.com/99ios/13.6


日韩av 中文字幕 1_亚洲第一区在线_亚洲V日韩V精品v无码专区_色鬼久久亚洲AV综合