簡(jiǎn)介
FMDB是SQLite在oc下的封裝,有三個(gè)主要的類(lèi)
1.FMDatabase – 表示一個(gè)單獨(dú)的SQLite數(shù)據(jù)庫(kù)。 用來(lái)執(zhí)行SQLite的命令。
2.FMResultSet – 表示FMDatabase執(zhí)行查詢(xún)后結(jié)果集
3.FMDatabaseQueue – 如果你想在多線(xiàn)程中執(zhí)行多個(gè)查詢(xún)或更新,你應(yīng)該使用該類(lèi)。這是線(xiàn)程安全的。
使用
創(chuàng)建FMDatabase對(duì)象時(shí)參數(shù)為SQLite數(shù)據(jù)庫(kù)文件路徑。該路徑可以是以下三種之一:
1.文件路徑。該文件路徑無(wú)需真實(shí)存在,如果不存在會(huì)自動(dòng)創(chuàng)建。
2.空字符串@”"。表示會(huì)在臨時(shí)目錄創(chuàng)建一個(gè)空的數(shù)據(jù)庫(kù),當(dāng)FMDatabase 鏈接關(guān)閉時(shí),文件也被刪除。
3.NULL. 將創(chuàng)建一個(gè)in-memory數(shù)據(jù)庫(kù)。同樣的,當(dāng)FMDatabase連接關(guān)閉時(shí),數(shù)據(jù)會(huì)被銷(xiāo)毀。
<pre><code>
FMDatabase *db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];
</code></pre>
在和數(shù)據(jù)庫(kù)交互 之前,數(shù)據(jù)庫(kù)必須是打開(kāi)的。如果資源或權(quán)限不足無(wú)法打開(kāi)或創(chuàng)建數(shù)據(jù)庫(kù),都會(huì)導(dǎo)致打開(kāi)失敗。
<pre><code>
if (![db open]) {
[db release];
return;
}
</code></pre>
執(zhí)行更新
一切不是SELECT命令的命令都視為更新。這包括 CREATE, UPDATE, INSERT,ALTER,COMMIT, BEGIN, DETACH, DELETE, DROP, END, EXPLAIN, VACUUM, and REPLACE (等)。
簡(jiǎn)單來(lái)說(shuō),只要不是以SELECT開(kāi)頭的命令都是UPDATE命令。
執(zhí)行更新返回一個(gè)BOOL值。YES表示執(zhí)行成功,否則表示有那些錯(cuò)誤 。你可以調(diào)用 -lastErrorMessage 和 -lastErrorCode方法來(lái)得到更多信息。
執(zhí)行查詢(xún)
SELECT命令就是查詢(xún),執(zhí)行查詢(xún)的方法是以 -excuteQuery開(kāi)頭的。
執(zhí)行查詢(xún)時(shí),如果成功返回FMResultSet對(duì)象, 錯(cuò)誤返回nil. 與執(zhí)行更新相當(dāng),支持使用 NSError**參數(shù)。同時(shí),你也可以使用 -lastErrorCode和-lastErrorMessage獲知錯(cuò)誤信息。
為了遍歷查詢(xún)結(jié)果,你可以使用while循環(huán)。你還需要知道怎么跳到下一個(gè)記錄。使用FMDB,很簡(jiǎn)單,就像這樣:
<pre><code>
FMResultSet *s = [db executeQuery:@"SELECT * FROM myTable"];
while ([s next]) {
//retrieve values for each record
}
</code></pre>
FMResultSet 提供了很多方法來(lái)獲得所需的格式的值:
<pre><code>
(int)intForColumn:(NSString*)columnName;
(int)intForColumnIndex:(int)columnIdx;
(long)longForColumn:(NSString*)columnName;
(long)longForColumnIndex:(int)columnIdx;
(long long int)longLongIntForColumn:(NSString*)columnName;
(long long int)longLongIntForColumnIndex:(int)columnIdx;
(unsigned long long int)unsignedLongLongIntForColumn:(NSString*)columnName;
(unsigned long long int)unsignedLongLongIntForColumnIndex:(int)columnIdx;
(BOOL)boolForColumn:(NSString*)columnName;
(BOOL)boolForColumnIndex:(int)columnIdx;
(double)doubleForColumn:(NSString*)columnName;
(double)doubleForColumnIndex:(int)columnIdx;
(NSString)stringForColumn:(NSString)columnName;
(NSString*)stringForColumnIndex:(int)columnIdx;
(NSDate)dateForColumn:(NSString)columnName;
(NSDate*)dateForColumnIndex:(int)columnIdx;
(NSData)dataForColumn:(NSString)columnName;
(NSData*)dataForColumnIndex:(int)columnIdx;
(const unsigned char *)UTF8StringForColumnIndex:(int)columnIdx;
(const unsigned char )UTF8StringForColumnName:(NSString)columnName;
// returns one of NSNumber, NSString, NSData, or NSNull
- (id)objectForColumnName:(NSString*)columnName;
- (id)objectForColumnIndex:(int)columnIdx;
</code></pre>
通常,你不需要調(diào)用[FMResultSet close]來(lái)關(guān)閉結(jié)果集,它會(huì)在自身deallocate或者父數(shù)據(jù)庫(kù)關(guān)閉的時(shí)候自動(dòng)關(guān)閉
使用FMDatabaseQueue 及線(xiàn)程安全
在多個(gè)線(xiàn)程中同時(shí)使用一個(gè)FMDatabase實(shí)例是不明智的。最好為每個(gè)線(xiàn)程創(chuàng)建一個(gè)FMDatabase對(duì)象。 不要讓多個(gè)線(xiàn)程分享同一個(gè)實(shí)例,它無(wú)法在多個(gè)線(xiàn)程中同時(shí)使用。 如果你這么干了,會(huì)有不好的事發(fā)生,程序會(huì)時(shí)經(jīng)常崩潰,或者發(fā)生異常,或者隕石會(huì)從天上掉下來(lái)砸到你Mac Pro(官方說(shuō)法...). 總之很崩潰。所以,不要初始化FMDatabase對(duì)象,然后在多個(gè)線(xiàn)程中使用。請(qǐng)使用 FMDatabaseQueue,它是你的朋友而且會(huì)幫助你。以下是使用方法
<code><pre>
FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath];
[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]];
}];
</code></pre>
FMDatabaseQueue 后臺(tái)會(huì)建立GCD隊(duì)列(依據(jù)類(lèi)名),并執(zhí)行你傳給G-C-D隊(duì)列的塊。這意味著 你從多線(xiàn)程同時(shí)調(diào)用調(diào)用方法,GCD也會(huì)按它接收的塊的順序來(lái)執(zhí)行