摘要 IOS操作數(shù)據(jù)庫福贞,SQLite3和coredata是兩個(gè)非常好的選擇撩嚼,但是對(duì)于我們這些掌握了其他數(shù)據(jù)庫語言的人來說,使用這兩中操作都會(huì)覺得不方便挖帘,SQLite3使用起來太復(fù)雜了绢馍,而使用coredata的時(shí)候卻封裝太死了,我們需要自己些自己的數(shù)據(jù)庫語句肠套,這時(shí)候,F(xiàn)MDB就是一個(gè)非常不錯(cuò)的選擇猖任!
FMDB 詳解
什么是FMDB
FMDB是iOS平臺(tái)的SQLite數(shù)據(jù)庫框架
FMDB以O(shè)C的方式封裝了SQLite的C語言API
FMDB的優(yōu)點(diǎn)
使用起來更加面向?qū)ο竽阒桑∪チ撕芏嗦闊⑷哂嗟腃語言代碼
對(duì)比蘋果自帶的Core Data框架朱躺,更加輕量級(jí)和靈活
提供了多線程安全的數(shù)據(jù)庫操作方法刁赖,有效地防止數(shù)據(jù)混亂
FMDB的github地址
https://github.com/ccgus/fmdb
廢話少說,下面來介紹FMDB的使用吧
FMDB有三個(gè)主要的類
FMDatabase
一個(gè)FMDatabase對(duì)象就代表一個(gè)單獨(dú)的SQLite數(shù)據(jù)庫
用來執(zhí)行SQL語句
FMResultSet
使用FMDatabase執(zhí)行查詢后的結(jié)果集
FMDatabaseQueue
用于在多線程中執(zhí)行多個(gè)查詢或更新长搀,它是線程安全的
下面來打開數(shù)據(jù)庫 宇弛,一般都需要數(shù)據(jù)庫的路徑地址:path
通過指定SQLite數(shù)據(jù)庫文件路徑來創(chuàng)建FMDatabase對(duì)象
FMDatabase *db = [FMDatabase databaseWithPath:path];
if (![db open]) {
NSLog(@"數(shù)據(jù)庫打開失敗源请!");
}
path文件路徑有三種情況
1枪芒,具體文件路徑
如果不存在會(huì)自動(dòng)創(chuàng)建
2,空字符串@“”
會(huì)在臨時(shí)目錄創(chuàng)建一個(gè)空的數(shù)據(jù)庫
當(dāng)FMDatabase連接關(guān)閉時(shí)谁尸,數(shù)據(jù)庫文件也被刪除
3舅踪,nil
會(huì)創(chuàng)建一個(gè)內(nèi)存中臨時(shí)數(shù)據(jù)庫,當(dāng)FMDatabase連接關(guān)閉時(shí)良蛮,數(shù)據(jù)庫會(huì)被銷毀
CURD操作:
在FMDB中抽碌,除查詢以外的所有操作,都稱為“更新”
create决瞳、drop货徙、insert、update皮胡、delete等
使用executeUpdate:方法執(zhí)行更新
(BOOL)executeUpdate:(NSString)sql, …
(BOOL)executeUpdateWithFormat:(NSString)format, …
(BOOL)executeUpdate:(NSString)sql withArgumentsInArray:(NSArray )arguments
示例
[db executeUpdate:@“UPDATE t_student SET age = ? WHERE name = ?;“, @20, @“Jack”]
查詢方法
(FMResultSet )executeQuery:(NSString)sql, …
(FMResultSet )executeQueryWithFormat:(NSString)format, …
(FMResultSet )executeQuery:(NSString )sql withArgumentsInArray:(NSArray *)arguments
示例
// 查詢數(shù)據(jù)
FMResultSet *rs = [db executeQuery:@“SELECT * FROM t_student”];
// 遍歷結(jié)果集
while ([rs next]) {
NSString *name = [rs stringForColumn:@"name"];
int age = [rs intForColumn:@"age"];
double score = [rs doubleForColumn:@"score"];
}
多線程管理FMDB
FMDatabase這個(gè)類是線程不安全的痴颊,如果在多個(gè)線程中同時(shí)使用一個(gè)FMDatabase實(shí)例,會(huì)造成數(shù)據(jù)混亂等問題
為了保證線程安全胸囱,F(xiàn)MDB提供方便快捷的FMDatabaseQueue類
FMDatabaseQueue的創(chuàng)建
FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:path];
簡單使用
[queue inDatabase:^(FMDatabase *db) {
[db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Jack"];
[db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Rose"];
[db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Jim"];
FMResultSet *rs = [db executeQuery:@"select * from t_student"];
while ([rs next]) {
// …
}
}];
使用事務(wù)
[queue inTransaction:^(FMDatabase db, BOOL rollback) {
[db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Jack"];
[db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Rose"];
[db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Jim"];
FMResultSet *rs = [db executeQuery:@"select * from t_student"];
while ([rs next]) {
// …
}
}];
事務(wù)回滾
*rollback = YES;
-開啟/關(guān)閉資料庫
使用資料庫的第一件事祷舀,就是建立一個(gè)資料庫。要注意的是,在iOS環(huán)境下裳扯,只有document directory 是可以進(jìn)行讀寫的抛丽。在寫程式時(shí)用的那個(gè)Resource資料夾底下的東西都是read-only。因此饰豺,建立的資料庫要放在document 資料夾下亿鲜。方法如下:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [paths objectAtIndex:0];
NSString *dbPath = [documentDirectory stringByAppendingPathComponent:@"MyDatabase.db"];
FMDatabase
*db = [FMDatabase databaseWithPath:dbPath] ;
if (![db open]) {
NSLog(@“Could not open db.”);
return ;
}
通常這段程式碼會(huì)放在UIViewController中viewDidLoad的函式里。指定路徑后冤吨,用[FMDatabase databaseWithPath:]回傳一個(gè)FMDatabase物件蒿柳,如果該路徑本來沒有檔案,會(huì)新增檔案漩蟆,不然會(huì)開啟舊檔垒探。最后呼叫[db open]可以開啟該資料庫檔案,[db close]則關(guān)閉該檔案怠李。
-建立table
如果是新建的資料庫檔圾叼,一開始是沒有table的。建立table的方式很簡單:
[db executeUpdate:@"CREATE TABLE PersonList (Name text, Age integer, Sex integer, Phone text, Address text, Photo blob)"];
這是FMDB里很常用的指令捺癞,[ FMDatabase_object executeUpdate:]后面用NSString塞入SQLite語法夷蚊,就解決了。因?yàn)檫@篇主要是在講FMDB髓介,所以SQLite的語法就不多說了惕鼓,上述程式碼建立了一個(gè)名為PersonList的table,里面有姓名唐础、年齡箱歧、性別、電話一膨、地址和照片叫胁。(嗯….很范例的一個(gè)table)
-插入資料
插入資料跟前面一樣,用executeUpdate后面加語法就可以了汞幢。比較不同的是驼鹅,因?yàn)椴迦氲馁Y料會(huì)跟Objective-C的變數(shù)有關(guān),所以在string里使用?號(hào)來代表這些變數(shù)森篷。
[db executeUpdate:@"INSERT INTO PersonList (Name, Age, Sex, Phone, Address, Photo) VALUES (?,?,?,?,?,?)",
@"Jone", [NSNumber numberWithInt:20], [NSNumber numberWithInt:0], @“091234567”, @“Taiwan, ROC”, [NSData dataWithContentsOfFile:? filepath ]];
其中输钩,在SQLite中的text對(duì)應(yīng)到的是NSString,integer對(duì)應(yīng)NSNumber仲智,blob則是NSData买乃。該做的轉(zhuǎn)換FMDB都做好了,只要了解SQLite語法钓辆,應(yīng)該沒有什么問題才是剪验。
-更新資料
太簡單了肴焊,不想講,請(qǐng)看范例:
[db executeUpdate:@"UPDATE PersonList SET Age = ? WHERE Name = ?",[NSNumber numberWithInt:30],@“John”];
-取得資料
取得特定的資料功戚,則需使用FMResultSet物件接收傳回的內(nèi)容:
FMResultSet *rs = [db executeQuery:@"SELECT Name, org.apache.jasper.JasperException: For input stringAge, FROM PersonList"];
while ([rs next]) {
NSString *name = [rs stringForColumn:@"Name"];
int age = [rs intForColumn:@"Age"];
}
[rs close];
用[rs next]可以輪詢query回來的資料娶眷,每一次的next可以得到一個(gè)row里對(duì)應(yīng)的數(shù)值,并用[rs stringForColumn:]或[rs intForColumn:]等方法把值轉(zhuǎn)成Object-C的型態(tài)啸臀。取用完資料后則用[rs close]把結(jié)果關(guān)閉届宠。
-快速取得資料
在有些時(shí)候,只會(huì)query某一個(gè)row里特定的一個(gè)數(shù)值(比方只是要找John的年齡)乘粒,F(xiàn)MDB提供了幾個(gè)比較簡便的方法豌注。這些方法定義在FMDatabaseAdditions.h,如果要使用灯萍,記得先import進(jìn)來轧铁。
//找地址
NSString *address = [db stringForQuery:@"SELECT Address FROM PersonList WHERE Name = ?",@"John”];
//找年齡
int age = [db intForQuery:@"SELECT Age FROM PersonList WHERE Name = ?",@"John”];