轉自:http://blog.devtang.com/blog/2012/04/22/use-fmd

1
2
3
4
5
6
7
8
9
10
11
NSString* docsdir = [NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString* dbpath = [docsdir stringByAppendingPathComponent:@"user.sqlite"];
FMDatabase* db = [FMDatabase databaseWithPath:dbpath];
[db open];
FMResultSet *rs = [db executeQuery:@"select * from people"];
while ([rs next]) {
    NSLog(@"%@ %@",
        [rs stringForColumn:@"firstname"],
        [rs stringForColumn:@"lastname"]);
}
[db close];

能夠看到,使用FMDB後的數據庫代碼清晰明瞭,比原生的API優雅多了。另外,FMDB同時兼容ARC和非ARC工程,會自動根據工程配置來調整相關的內存管理代碼。git

使用說明

該使用說明主要翻譯自fmdb的github項目說明文檔: https://github.com/ccgus/fmdbgithub

引入相關文件

首先將FMDB從github上clone下來,而後將如下文件copy到你的工程中:sql

1
2
3
4
5
6
7
8
9
10
FMDatabase.h
FMDatabase.m
FMDatabaseAdditions.h
FMDatabaseAdditions.m
FMDatabasePool.h
FMDatabasePool.m
FMDatabaseQueue.h
FMDatabaseQueue.m
FMResultSet.h
FMResultSet.m

創建數據庫

創建數據庫只須要以下一行便可,當該文件不存在時,fmdb會本身建立一個。若是你傳入的參數是空串:@」」 ,則fmdb會在臨時文件目錄下建立這個數據庫,若是你傳入的參數是 NULL,則它會創建一個在內存中的數據庫。數據庫

1
FMDatabase *db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];

打開數據庫

使用以下語句,若是打開失敗,多是權限不足或者資源不足。一般打開完操做操做後,須要調用close方法來關閉數據庫。安全

1
2
3
4
5
6
7
8
if (![db open]) {
    // error 
    return;
}
// some operation
// ...

[db close];

執行更新操做

除了Select操做以外,其它的都是更新操做。更新操做使用以下方法,若是有錯誤,能夠用error參數中得到。多線程

1
-[FMDatabase executeUpdate:error:withArgumentsInArray:orVAList:]

執行查詢操做

查詢操做示例以下。注意:即便操做結果只有一行,也須要先調用FMResultSet的next方法。閉包

1
2
3
4
5
6
7
8
9
FMResultSet *s = [db executeQuery:@"SELECT * FROM myTable"];
while ([s next]) {
    //retrieve values for each record
}

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

FMDB提供以下多個方法來獲取不一樣類型的數據:app

1
2
3
4
5
6
7
8
9
10
11
intForColumn:
longForColumn:
longLongIntForColumn:
boolForColumn:
doubleForColumn:
stringForColumn:
dateForColumn:
dataForColumn:
dataNoCopyForColumn:
UTF8StringForColumnIndex:
objectForColumn:

一般狀況下,你並不須要關閉FMResultSet,由於相關的數據庫關閉時,FMResultSet也會被自動關閉。oop

數據參數

一般狀況下,你能夠按照標準的SQL語句,用?表示執行語句的參數,如:spa

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

而後,能夠咱們能夠調用executeUpdate方法來將?所指代的具體參數傳入,一般是用變長參數來傳遞進去的,以下:

1
2
NSString *sql = @"insert into User (name, password) values (?, ?)";
[db executeUpdate:sql, user.name, user.password];

這裏須要注意的是,參數必須是NSObject的子類,因此象int,double,bool這種基本類型,須要封裝成對應的包裝類才行,以下所示:

1
2
3
4
// 錯誤,42不能做爲參數
[db executeUpdate:@"INSERT INTO myTable VALUES (?)", 42];
// 正確,將42封裝成 NSNumber 類
[db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:42]];

線程安全

若是咱們的app須要多線程操做數據庫,那麼就須要使用FMDatabaseQueue來保證線程安全了。切記不能在多個線程中共同一個FMDatabase對象而且在多個線程中同時使用,這個類自己不是線程安全的,這樣使用會形成數據混亂等問題。

使用FMDatabaseQueue很簡單,首先用一個數據庫文件地址來初使化FMDatabaseQueue,而後就能夠將一個閉包(block)傳入inDatabase方法中。在閉包中操做數據庫,而不直接參與FMDatabase的管理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 建立,最好放在一個單例的類中
FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath];

// 使用
[queue inDatabase:^(FMDatabase *db) {
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]];
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]];
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]];

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

// 若是要支持事務
[queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]];
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]];
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]];

    if (whoopsSomethingWrongHappened) {
        *rollback = YES;
        return;
    }
    // etc…
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:4]];
}];
相關文章
相關標籤/搜索