FMDB是iOS平台的SQLite数据库框架,以OC的方式封装了SQLite的C语言API,使用起来更加面向对象,省去了很多麻烦、冗余的C语言代码,并且提供了多线程安全的数据库操作方法,有效地防止数据混乱。
FMDB有三个主要的类:
- FMDatabase
一个FMDatabase对象就代表一个单独的SQLite数据库
用来执行SQL语句 - FMResultSet
使用FMDatabase执行查询后的结果集 - FMDatabaseQueue
用于在多线程中执行多个查询或更新,它是线程安全的
打开数据库
通过指定SQLite数据库文件路径来创建FMDatabase对象
/** 通过指定SQLite数据库文件路径来创建FMDatabase对象
inPath : 文件路径,
传入具体文件路径,如果不存在会自动创建;
空字符串@"",会在临时目录创建一个空的数据库,当FMDatabase连接关闭时,数据库文件也被删除;
nil,会创建一个内存中临时数据库,当FMDatabase连接关闭时,数据库会被销毁
*/
+ (instancetype)databaseWithPath:(NSString *)aPath {
return FMDBReturnAutoreleased([[self alloc] initWithPath:aPath]);
}
示例:
FMDatabase *db = [FMDatabase databaseWithPath:path];
if (![db open]) {
NSLog(@"数据库打开失败!");
}
执行更新
在FMDB中,除查询以外的所有操作,都称为“更新”,
create
、drop
、insert
、update
、delete
等。
使用executeUpdate:方法执行更新
- (BOOL)executeUpdate:(NSString*)sql, ...
- (BOOL)executeUpdateWithFormat:(NSString*)format, ...
- (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments
示例:
[db executeUpdate:@"create table if not exists t_student (id integer primary key autoincrement, name test not null, score real default 1)"];
[db executeUpdate:@"insert into t_student(score,name) values (20,'jack')"];
[db executeUpdate:@"insert into t_student(score,name) values (?,?)",@(20),@"jack"];
执行查询
- (FMResultSet *)executeQuery:(NSString*)sql, ...
- (FMResultSet *)executeQueryWithFormat:(NSString*)format, ...
- (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments
示例:
FMResultSet *set = [db executeQuery:@"select id,name,score from t_student"];
// 遍历结果集:next方法返回yes代表有数据可取
while (set.next) {
int ID = [set intForColumnIndex:0];
NSString *name = [set stringForColumnIndex:1];
double score = [set intForColumnIndex:2];
NSLog(@"----%d----%@---%f",ID,name,score);
}
FMDatabaseQueue
FMDatabase这个类是线程不安全的,如果在多个线程中同时使用一个FMDatabase实例,会造成数据混乱等问题,为了保证线程安全,FMDB提供方便快捷的FMDatabaseQueue类
- FMDatabaseQueue的创建
// 只要创建数据库队列对象, FMDB内部就会自动给我们加载数据库对象
self.queue = [FMDatabaseQueue databaseQueueWithPath:path];
- 执行操作
// 会通过block传递队列中创建好的数据库给我们
[self.queue inDatabase:^(FMDatabase * _Nonnull db) {
//创建表
BOOL success = [db executeUpdate:@"create table if not exists t_student(id integer primary key autoincrement,name test not null,score real default 1)"];
if (success) {
NSLog(@"创建表成功");
}else{
NSLog(@"创建表失败");
}
//插入数据
BOOL success = [db executeUpdate:@"INSERT INTO t_student(score, name) VALUES (?, ?);", @(20), @"jackson"];
if (success) {
NSLog(@"插入成功");
}else
{
NSLog(@"插入失败");
}
//查询数据
FMResultSet *set = [db executeQuery:@"select id,name,score from t_student"];
// 遍历结果集:next方法返回yes代表有数据可取
while (set.next) {
int ID = [set intForColumnIndex:0];
NSString *name = [set stringForColumnIndex:1];
double score = [set intForColumnIndex:2];
NSLog(@"----%d----%@---%f",ID,name,score);
}
}];
事务
- 普通用法
[self.queue inDatabase:^(FMDatabase *db) {
// 开启事务
[db beginTransaction];
BOOL result1 = [db executeUpdate:@"UPDATE t_student SET score = 1500 WHERE name = 'zs';"];
BOOL result2 = [db executeUpdate:@"UPDATE t_student SET score = 500 WHERE name = 'ls';"];
if(result1 && result2){
// 提交事务
[db commit];
}else{
//事务回滚
[db rollback];
}
}];
- inTransaction
[self.queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
BOOL result1 = [db executeUpdate:@"UPDATE t_student SET score = 1500 WHERE name = 'zs';"];
BOOL result2 = [db executeUpdate:@"UPDATE t_student SET score = 500 WHERE name = 'ls';"];
if(result1 || result2){
*rollback = YES;
}
}];