摘要 IOS操作数据库,SQLite3和coredata是两个非常好的选择,但是对于我们这些掌握了其他数据库语言的人来说,使用这两中操作都会觉得不方便,SQLite3使用起来太复杂了,而使用coredata的时候却封装太死了,我们需要自己些自己的数据库语句,这时候,FMDB就是一个非常不错的选择!
FMDB 详解
什么是FMDB
FMDB是iOS平台的SQLite数据库框架
FMDB以OC的方式封装了SQLite的C语言API
FMDB的优点
使用起来更加面向对象,省去了很多麻烦、冗余的C语言代码
对比苹果自带的Core Data框架,更加轻量级和灵活
提供了多线程安全的数据库操作方法,有效地防止数据混乱
FMDB的github地址
https://github.com/ccgus/fmdb
废话少说,下面来介绍FMDB的使用吧
FMDB有三个主要的类
FMDatabase
一个FMDatabase对象就代表一个单独的SQLite数据库
用来执行SQL语句
FMResultSet
使用FMDatabase执行查询后的结果集
FMDatabaseQueue
用于在多线程中执行多个查询或更新,它是线程安全的
下面来打开数据库 ,一般都需要数据库的路径地址:path
通过指定SQLite数据库文件路径来创建FMDatabase对象
FMDatabase *db = [FMDatabase databaseWithPath:path];
if (![db open]) {
NSLog(@"数据库打开失败!");
}
path文件路径有三种情况
1,具体文件路径
如果不存在会自动创建
2,空字符串@“”
会在临时目录创建一个空的数据库
当FMDatabase连接关闭时,数据库文件也被删除
3,nil
会创建一个内存中临时数据库,当FMDatabase连接关闭时,数据库会被销毁
CURD操作:
在FMDB中,除查询以外的所有操作,都称为“更新”
create、drop、insert、update、delete等
使用executeUpdate:方法执行更新
(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
示例
// 查询数据
FMResultSet *rs = [db executeQuery:@“SELECT * FROM t_student”];
// 遍历结果集
while ([rs next]) {
NSString *name = [rs stringForColumn:@"name"];
int age = [rs intForColumn:@"age"];
double score = [rs doubleForColumn:@"score"];
}
多线程管理FMDB
FMDatabase这个类是线程不安全的,如果在多个线程中同时使用一个FMDatabase实例,会造成数据混乱等问题
为了保证线程安全,FMDB提供方便快捷的FMDatabaseQueue类
FMDatabaseQueue的创建
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]) {
// …
}
}];
使用事务
[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]) {
// …
}
}];
事务回滚
*rollback = YES;
-开启/关闭资料库
使用资料库的第一件事,就是建立一个资料库。要注意的是,在iOS环境下,只有document directory 是可以进行读写的。在写程式时用的那个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 ;
}
通常这段程式码会放在UIViewController中viewDidLoad的函式里。指定路径后,用[FMDatabase databaseWithPath:]回传一个FMDatabase物件,如果该路径本来没有档案,会新增档案,不然会开启旧档。最后呼叫[db open]可以开启该资料库档案,[db close]则关闭该档案。
-建立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语法,就解决了。因为这篇主要是在讲FMDB,所以SQLite的语法就不多说了,上述程式码建立了一个名为PersonList的table,里面有姓名、年龄、性别、电话、地址和照片。(嗯….很范例的一个table)
-插入资料
插入资料跟前面一样,用executeUpdate后面加语法就可以了。比较不同的是,因为插入的资料会跟Objective-C的变数有关,所以在string里使用?号来代表这些变数。
[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对应到的是NSString,integer对应NSNumber,blob则是NSData。该做的转换FMDB都做好了,只要了解SQLite语法,应该没有什么问题才是。
-更新资料
太简单了,不想讲,请看范例:
[db executeUpdate:@"UPDATE PersonList SET Age = ? WHERE Name = ?",[NSNumber numberWithInt:30],@“John”];
-取得资料
取得特定的资料,则需使用FMResultSet物件接收传回的内容:
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可以得到一个row里对应的数值,并用[rs stringForColumn:]或[rs intForColumn:]等方法把值转成Object-C的型态。取用完资料后则用[rs close]把结果关闭。
-快速取得资料
在有些时候,只会query某一个row里特定的一个数值(比方只是要找John的年龄),FMDB提供了几个比较简便的方法。这些方法定义在FMDatabaseAdditions.h,如果要使用,记得先import进来。
//找地址
NSString *address = [db stringForQuery:@"SELECT Address FROM PersonList WHERE Name = ?",@"John”];
//找年龄
int age = [db intForQuery:@"SELECT Age FROM PersonList WHERE Name = ?",@"John”];