FMDB详解(v2.7)

2018-04-14  本文已影响27人  开发者老岳

包含仨主要类:
FMDatabaseFMResultSetFMDatabaseQueue

创建数据库

FMDatabase 是基于一个数据库文件的path创建的,该path有三种情况:

NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:@"tmp.db"];
FMDatabase *db = [FMDatabase databaseWithPath:path];

打开

操作数据库前,数据库必须是打开状态的。当空间不足或者没有权限的时候,就会打开失败。

if (![db open]) {
    db = nil;
    return;
}

Executing Updates

Executing Queries

FMResultSet *s = [db executeQuery:@"SELECT * FROM myTable"];
while ([s next]) {
    //retrieve values for each record
}

结果只有一个的时候,也要调用next方法。如下:

FMResultSet *s = [db executeQuery:@"SELECT COUNT(*) FROM myTable"];
if ([s next]) {
    int totalCount = [s intForColumnIndex:0];
}

FMResultSet有若干方法可用于解析返回的数据,如下:

Closing

当执行完queries(查询)或updates(更新)数据库后,要手动-closeFMDatabase连接,释放相应的资源。

 [db close];

Transactions

FMDatabase can begin and commit a transaction by invoking one of the appropriate methods or executing a begin/end transaction statement.

多语句和批量处理(Multiple Statements and Batch Stuff)

可以通过调用FMDatabaseexecuteStatements:withResultBlock:方法来执行多条sql语句:

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;
}];

数据清理(Data Sanitization)

查询时问号?的使用:

NSInteger identifier = 42;
NSDate *date = [NSDate date];
NSString *comment = nil;

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

冒号的使用:

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

FMDatabaseQueue 和线程安全

不要在多个线程里共享使用同一个FMDatabase的单例,因为会有线程安全的问题。多线程里要用FMDatabaseQueue,使用方法:

//创建队列
FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath];
//使用
[queue inDatabase:^(FMDatabase *db) {
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", @1];
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", @2];
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", @3];

    FMResultSet *rs = [db executeQuery:@"select * from foo"];
    while ([rs next]) {
        …
    }
}];

FMDataBaseQueue使用事务:

[queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", @1];
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", @2];
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", @3];

    if (whoopsSomethingWrongHappened) {
        *rollback = YES;
        return;
    }

    // etc ...
}];

FMDatabaseQueue能保证在多线程里任务顺序的执行,而不会冲突。

Making custom sqlite functions, based on blocks.

You can do this! For an example, look for -makeFunctionNamed: in main.m

上一篇 下一篇

猜你喜欢

热点阅读