为什么执行 dispatch group enterfmdb就会闪退

FMDB封装了SQLite3的方法,操作数据库变得很简单。
增删改查变简单之后,那么问题来了,如何使用多线程优化对数据库的操作?
这是我们的第一反应估计是dispatch_async().
那么问题又来了,多线程操作如何防止database被lock?
哇哈哈,这个时候就要用到FMDatabaseQueue。
先来了解下FMDatabaseQueue的用法。
先来建个表热热身
NSString* path = [NSHomeDirectory() stringByAppendingPathComponent:@&Documents/test.db&];
NSLog(@&path = %@&,path);
self.dbQueue = [FMDatabaseQueue databaseQueueWithPath:path];
[self.dbQueue inDatabase:^(FMDatabase *db) {
BOOL result =
[db executeUpdate:@&create table if not exists testTable (id integer PRIMARY KEY AUTOINCREMENT, name text)&];
NSLog(@&creare %@&,result?@&success&:@&fail&);
没错,就是这么的简单。
那么再来插入几条数据
[self.dbQueue inDatabase:^(FMDatabase *db) {
for (int i = 0; i & 500; i++) {
[db executeUpdate:@&insert into testTable (name) values(?)&,[NSString stringWithFormat:@&name-%d&,i]];
恩,很帅气有木有。
开启事务,再插入一次
[self.dbQueue inTransaction:^(FMDatabase *db, BOOL *rollback) {
BOOL result = YES;
for (int i = 500; i & 1000; i++) {
[db executeUpdate:@&insert into testTable (name) values(?)&,[NSString stringWithFormat:@&name-%d&,i]];
if (!result) {
NSLog(@&break&);
*rollback = YES;
对比下效率:
NSDate* one = [NSDate date];
[self.dbQueue inDatabase:^(FMDatabase *db) {
for (int i = 0; i & 500; i++) {
[db executeUpdate:@&insert into testTable (name) values(?)&,[NSString stringWithFormat:@&name-%d&,i]];
NSDate* two = [NSDate date];
NSTimeInterval first = [two timeIntervalSinceDate:one];
NSLog(@&first = %lf&,first);
NSDate* three = [NSDate date];
[self.dbQueue inTransaction:^(FMDatabase *db, BOOL *rollback) {
BOOL result = YES;
for (int i = 500; i & 1000; i++) {
[db executeUpdate:@&insert into testTable (name) values(?)&,[NSString stringWithFormat:@&name-%d&,i]];
if (!result) {
NSLog(@&break&);
*rollback = YES;
NSDate* four = [NSDate date];
NSTimeInterval second = [four timeIntervalSinceDate:three];
NSLog(@&second = %lf&,second);
输出打印:
22:01:57.756 FMDB[] path = /Users/zhutc/Library/Developer/CoreSimulator/Devices/01-480E-ADC8-8F77C160A18F/data/Containers/Data/Application/6D0C0AE6-3069-4BEE-A7B9-BD/Documents/test.db
22:01:57.759 FMDB[] creare success
22:02:03.029 FMDB[] first = 5.270233
22:02:03.052 FMDB[] second = 0.022609
再看看删除:
NSDate* five = [NSDate date];
[self.dbQueue inDatabase:^(FMDatabase *db) {
[db executeUpdate:@&delete from testTable where id & 500&];
NSDate* six = [NSDate date];
NSTimeInterval third = [six timeIntervalSinceDate:five];
NSLog(@&third = %lf&,third);
NSDate* seven = [NSDate date];
[self.dbQueue inTransaction:^(FMDatabase *db, BOOL *rollback) {
[db executeUpdate:@&delete from testTable where
id &= 500&];
NSDate* eight = [NSDate date];
NSTimeInterval fourth = [eight timeIntervalSinceDate:seven];
NSLog(@&fourth = %lf&,fourth);
看看打印:
22:02:03.066 FMDB[] third = 0.013382
22:02:03.080 FMDB[] fourth = 0.013715
还是事务高大上!!!
可以看出来:使用事务处理就是将所有任务执行完成以后将结果一次性提交到数据库,如果此过程出现异常则会执行回滚操作,这样节省了大量的重复提交环节所浪费的时间。
多线程在哪里?
看下FMDatabaseQueue的源码,发现了一个串行的queue,而且这个queue是同步调用
这个源码是比较老得,最新版的没下载下来,就拿过来用用。最新版的变动是使用同一个queue,可重入。
- (void)inDatabase:(void (^)(FMDatabase *db))block {
FMDBRetain(self);
dispatch_sync(_queue, ^() {
FMDatabase *db = [self database];
block(db);
if ([db hasOpenResultSets]) {
NSLog(@&Warning: there is at least one open result set around after performing [FMDatabaseQueue inDatabase:]&);
FMDBRelease(self);
到这里应该就知道,我们只需要使用dispatch_async,然后配合FMDatabaseQueue。
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[self.dbQueue inTransaction:^(FMDatabase *db, BOOL *rollback) {
BOOL result = YES;
for (int i = 500; i & 1000; i++) {
[db executeUpdate:@&insert into testTable (name) values(?)&,[NSString stringWithFormat:@&name-%d&,i]];
if (!result) {
NSLog(@&break&);
*rollback = YES;
最新版的FMDB不可以在多个队列中使用同一个FMDatabaseQueue实例,会有问题。至于为毛,等研究透了在补充。哇哈哈!1
本文已收录于以下专栏:
相关文章推荐
原文地址1:/Article/18028
原文地址2:http://blog.csdn.net/xyz_lmn/article/details/9312837F...
SQLite数据库多线程操作:
在上面一节中已经讲过FMDB的用法了,接下来讲讲sqlite在都线程中的用法。如果应用中使用了多线程操作数据库,那么就需要使用FMDatabaseQueue来...
操作数据库时,如果是有多个并发线程同时使用到了同一个数据库,就有可能发生同时操作的可能,这个时候数据会崩溃。FMDB 给我们提供了FMDatabaseQueue 这样一种解决方法。
自己用GCD 的d...
databaseQueue实现
数据库操作
iOS中原生的SQLite API在使用上相当不友好,在使用时,非常不便。于是,就出现了一系列将SQLite API进行封装的库,例如FMDB、PlausibleDatabase、sqlitepers...
iOS中原生的SQLite API在使用上相当不友好,在使用时,非常不便。于是,就出现了一系列将SQLite API进行封装的库,例如FMDB、PlausibleDatabase、sqlitepers...
如果你的公司用户基数足够大,那么根据埋点数据分析得到的反馈是非常有用的。除了第三方的埋点数据分析,比如友盟,如果我们希望自己也存一份数据,作为对友盟数据的对比,在iOS工程中如何实现呢?...
iOS sqlite3保存数组NSArray
NSData/NSArray数组存储为SQLite
在ios开发中,大家很可能会用到这样一个数据库封装:fmdb.
该封装相比coredata来说有他自己的优势:接口清晰,设计简单,符合规范,多线程情况下使用databasequeue来进行操作也很方...
他的最新文章
讲师:王哲涵
讲师:王渊命
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)iOS(186)
使用FMDB创建一个表。首先要知道表中的元素有哪些,表的主键是哪个,数据在存储后,用于查询的条件是一个还是多个,考虑清楚表的结构,对后面完成功能更方便。
首先使用cocoa
pods导入FMDB
1:因为我要存储的数据来自后台返回的json串,我使用MVC模式来显示数据。所以表中的元素都是Model(模型)的属性。然后再考虑主键,如果只是用一个tableview来显示数据,那这个主键可以用一个字符串代替,以后查询的时候,通过这个字符串,就能将表里的数据拿到,从而显示出来。下面是我用到的数据模型的model(模型)。
#import &Foundation/Foundation.h&
@interface LMTopicsModel : NSObject
/* 名称 */
@property(nonatomic,copy)NSString *
@property(nonatomic,copy)NSString *profile_
/* 文本内容 */
@property(nonatomic,copy)NSString *
/* 发帖子时间 */
@property(nonatomic,copy)NSString *create_
/* 点赞数 */
@property(nonatomic,assign)NSI
/* 踩数 */
@property(nonatomic,assign)NSI
/* 转发数 */
@property(nonatomic,assign)NSI
/* 评论数 */
@property(nonatomic,assign)NSI
/* 新浪加v */
@property(nonatomic,assign,getter=isSina_v)BOOL sina_v;
/* 小图 */
@property(nonatomic,copy)NSString *small_
/* 大图 */
@property(nonatomic,copy)NSString *large_
/* 中图 */
@property(nonatomic,copy)NSString *middle_
/* 宽度 */
@property(nonatomic,copy)NSString *
/* 高度 */
@property(nonatomic,copy)NSString *
@property(nonatomic,copy)NSString *ID;
/* 加载更多的参数 */
@property(nonatomic,copy)NSString *
#import &LMTopicsModel.h&
#import &MJExtension.h&
@implementation LMTopicsModel
+(NSDictionary *)mj_replacedKeyFromPropertyName
@&small_image&:@&image0&,
@&middle_image&:@&image2&,
@&large_image&:@&image1&,
@&ID&:@&id&
2:因为我的数据在首页就要显示出来,我在AppDelegate.m里面创建了这个数据库。
#import &AppDelegate.h&
#import &MainViewController.h&
#import &ProjectTool.h&
#import &FMDB.h&
@interface AppDelegate ()
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//创建主窗口
self.window = [[UIWindow alloc] init];
self.window.frame = [UIScreen mainScreen].
self.window.backgroundColor = [UIColor whiteColor];
//设置根控制器
UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:[[MainViewController alloc]init]];
self.window.rootViewController =
//显示窗口
[self.window makeKeyAndVisible];
//创建数据库
[self createFMDB];
return YES;
#pragma mark - 创建数据库
-(void)createFMDB
NSString *dbFilePath = [ProjectTool getFMDBPath];
为什么要往应用程序里添加数据库文件这个过程:
因为下面要进行判断,会根据这个路径去查找应用程序的路径中到底有没有这个文件,
如果有,则不用在此拷贝了,
如果没有,则重新拷贝一次,
数据库文件必须添加进取,否则无法进行数据库的操作,而且必须添加一次,
那么为什么必须要添加一次呢?
因为我们在程序中实现对数据库的修改,然而却又把数据库添加了一次,
那么新添加的数据库就会把旧的数据库覆盖掉,那么程序中对数据库的修改也不能实现,
所以数据库只能添加一次且是在程序运行初添加
//根据上面拼接好的路径 dbFilePath ,利用NSFileManager 类的对象的fileExistsAtPath方法来检测是否存在,返回一个BOOL值
//1. 创建NSFileManager对象
NSFileManager包含了文件属性的方法
NSFileManager *fm = [NSFileManager defaultManager];
//2. 通过 NSFileManager 对象 fm 来判断文件是否存在,存在 返回YES
不存在返回NO
BOOL isExist = [fm fileExistsAtPath:dbFilePath];
//- (BOOL)fileExistsAtPath:(NSString *)
//如果不存在 isExist = NO,拷贝工程里的数据库到Documents下
if (!isExist)
//创建FMDB数据库
FMDatabase *db = [FMDatabase databaseWithPath:dbFilePath];
if ([db open]) {
NSString *sql = [NSString stringWithFormat:@&CREATE TABLE %@(prikey TEXT,name TEXT,profile_image TEXT,text TEXT,create_time TEXT,ding TEXT,cai TEXT,repost TEXT,comment TEXT,sina_v TEXT,small_image TEXT,width TEXT,height TEXT,ID TEXT,maxtime TEXT)&,dbTableName];
BOOL res = [db executeUpdate:sql];
if (!res) {
NSLog(@&创建数据库失败&);
NSLog(@&创建数据库成功!&);
[db close];
NSLog(@&数据库打开失败&);
补:ProjectTool获取数据库路径
#import &Foundation/Foundation.h&
@interface ProjectTool : NSObject
/*获取FMDB数据库的路径*/
+(NSString *)getFMDBP
#import &ProjectTool.h&
#define DATABASE_FILE_NAME @&project.sqlite&
@implementation ProjectTool
+(NSString *)getFMDBPath
/*===---===
在这个部分中我么进行一下操作:(要把数据库文件存放到储存的位置中)
1.获取应用程序的路径,在手机中就是 应用程序存储数据的地方
2.把数据库文件的名称拼接到上面得到的路径上
3.根据拼接好的路径去寻找,并判断这个文件是否存在
===---===*/
//获取应用程序的路径
NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory,
NSUserDomainMask,
NSString *documentFolderPath = [searchPaths objectAtIndex:0];
//往应用程序路径中添加数据库文件名称,把它们拼接起来, 这里用到了宏定义(目的是不易出错)
NSString *dbFilePath = [documentFolderPath stringByAppendingPathComponent:DATABASE_FILE_NAME];
return dbFileP
3:为了方便对进行增删改查,我创建一个工具类,在这后面我再进行操作的时候,只需要通过工具类来操作。
DataBaseTool.h
#import &Foundation/Foundation.h&
@interface DataBaseTool : NSObject
//创建单利对象,防止创建多个数据库
+(DataBaseTool *)shareDataBaseT
//插入数据
-(void)insertModelArray:(NSMutableArray *)modelArray
byPrKey:(NSString *)PrK
//查询数据
-(NSMutableArray *)queryModelArrayByPrKey:(NSString *)PrK
//删除数据
-(void)deleteModelArrayByPrKey:(NSString *)PrK
//查询所有数据
-(void)queryA
//删除所有数据
-(void)clearA
DataBaseTool.m
#import &DataBaseTool.h&
#import &ProjectTool.h&
#import &LMTopicsModel.h&
#import &FMDB.h&
static DataBaseTool *shareDataBase =
@implementation DataBaseTool
//创建单利对象,防止创建多个数据库
+(DataBaseTool *)shareDataBaseTool
static dispatch_once_t onceT
dispatch_once(&onceToken, ^{
shareDataBase = [[DataBaseTool alloc]init];
return shareDataB
//插入数据
-(void)insertModelArray:(NSMutableArray *)modelArray byPrKey:(NSString *)PrKey
//存储信息
FMDatabase *db = [FMDatabase databaseWithPath:[ProjectTool getFMDBPath]];
if ([db open]) {
for (LMTopicsModel *model in modelArray) {
//创建一个社区table
NSString *sql = [NSString stringWithFormat:
@&insert into %@ (prikey,name ,profile_image ,text ,create_time
,ding ,cai
,repost ,comment ,sina_v ,small_image ,width ,height ,ID,maxtime) values ('%@','%@','%@','%@','%@','%@','%@',%@,'%@','%@','%@','%@','%@','%@','%@')&,dbTableName,PrKey,model.name,model.profile_image,model.text,model.create_time,@(model.ding),@(model.cai),@(model.repost),@(ment),@(model.sina_v),model.small_image,model.width,model.height,model.ID,model.maxtime];
BOOL res = [db executeUpdate:sql];
if (!res) {
NSLog(@&更新失败!&);
NSLog(@&成功!&);
[db close];
//查询数据query
-(NSMutableArray *)queryModelArrayByPrKey:(NSString *)PrKey
FMDatabase *db = [FMDatabase databaseWithPath:[ProjectTool getFMDBPath]];
NSMutableArray *dbArray = [NSMutableArray array];
if ([db open]) {
NSString *sql = [NSString stringWithFormat:@&select * from %@ where prikey = '%@'&,dbTableName,PrKey];
//执行sql查询语句
FMResultSet *rs = [db executeQuery:sql];
while ([rs next]) {
LMTopicsModel *model = [[LMTopicsModel alloc]init];
model.name = [rs stringForColumn:@&name&];
model.profile_image = [rs stringForColumn:@&profile_image&];
model.text = [rs stringForColumn:@&text&];
model.create_time = [rs stringForColumn:@&create_time&];
model.ding = [[rs stringForColumn:@&ding&] integerValue];
model.cai = [[rs stringForColumn:@&cai&] integerValue];
model.repost = [[rs stringForColumn:@&repost&] integerValue];
ment = [[rs stringForColumn:@&comment&] integerValue];
model.sina_v = [[rs stringForColumn:@&sina_v&] integerValue];
model.small_image = [rs stringForColumn:@&small_image&];
model.width = [rs stringForColumn:@&width&];
model.height = [rs stringForColumn:@&height&];
model.ID = [rs stringForColumn:@&ID&];
model.maxtime = [rs stringForColumn:@&maxtime&];
[dbArray addObject:model];
[db close];
return dbA
//删除数据
-(void)deleteModelArrayByPrKey:(NSString *)PrKey
FMDatabase *db = [FMDatabase databaseWithPath:[ProjectTool getFMDBPath]];
if ([db open]) {
NSString *sql = [NSString stringWithFormat:@&delete from %@ where prikey = '%@'&,dbTableName,PrKey];
BOOL res = [db executeUpdate:sql];
if (!res) {
NSLog(@&删除失败&);
NSLog(@&删除成功!&);
[db close];
//查询所有数据
-(void)queryAll
FMDatabase *db = [FMDatabase databaseWithPath:[ProjectTool getFMDBPath]];
if ([db open]) {
int i = 0;
NSString * sql = [NSString stringWithFormat:@&select * from %@&,dbTableName];
FMResultSet * rs = [db executeQuery:sql];
while ([rs next]) {
NSString *ID = [rs stringForColumn:@&ID&];
NSString *text = [rs stringForColumn:@&text&];
NSLog(@&查询的数据 %d,%@,%@&,i++,ID,text);
[db close];
//删除所有数据
-(void)clearAll
FMDatabase *db = [FMDatabase databaseWithPath:[ProjectTool getFMDBPath]];
if ([db open]) {
NSString * sql =[NSString stringWithFormat:@&delete from %@&,dbTableName];
BOOL res = [db executeUpdate:sql];
if (!res) {
NSLog(@&清除失败!&);
NSLog(@&清除完成!&);
4.使用情境:
无网状态下:(从数据库取出,然后赋值给数据,刷新tableview)
NSString *private_key = @&homeInfo&;
//从数据库取出
NSMutableArray *dbModelArray = [[DataBaseTool shareDataBaseTool]queryModelArrayByPrKey:private_key];
[self.lmTableView reloadData];
请求到最新的数据:(先清除原来数据库所有的数据,再将新的数据存储)
//存储数据
[[DataBaseTool shareDataBaseTool]deleteModelArrayByPrKey:private_key];
[[DataBaseTool shareDataBaseTool]insertModelArray:[NSMutableArray arrayWithArray:tempArray] byPrKey:private_key];
请求到更多的数据:(在原来数据的基础上插入更多数据,不用删除原来的数据)
//存储数据
[[DataBaseTool shareDataBaseTool]insertModelArray:[NSMutableArray arrayWithArray:tempArray] byPrKey:private_key];
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:260771次
积分:4257
积分:4257
排名:第7522名
原创:202篇
转载:29篇
评论:26条
(2)(14)(2)(4)(7)(1)(6)(4)(7)(6)(9)(5)(6)(40)(16)(4)(7)(19)(17)(6)(4)(9)(9)(5)(24)
(window.slotbydup = window.slotbydup || []).push({
id: '4740881',
container: s,
size: '200,200',
display: 'inlay-fix'FMDB 二次封装工具类,让你快速学会封装,集成数据库 - IOS - 伯乐在线
& FMDB 二次封装工具类,让你快速学会封装,集成数据库
上个版本为了增加用户体验,部分页面集成了离线缓存数据功能,于是就在项目里使用了数据库管理离线数据。下面交大家一步步学会使用FMDB,以及FMDB的二次封装,同事把我二次封装的数据库放出来,希望能够帮助大家快速学习,集成数据库功能吧。
一.首先看一下STDB文件结构
STDB文件结构
Table.h主要放一些Table的创建语句, 方便管理我的数据库各张表创建
DBDefine.h主要放一些表名的宏定义,数据库版本号,数据库名字等等,方便我们在使用数据库过程中更直观管理版本和各种表
STDBTool.h,STDBTool.m具体封装实现代码
Table.h结构
二.具体实现功能
1 . STDBTool.h 头文件看一下
STDBTool.h
我定义了三个FMDatabaseQueue 因为实际操作中我需要数据库嵌套,如果只使用一个FMDatabaseQueue 将会陷入死循环,下面看一下1FMDatabaseQueue源码分析一下原因:
FMDatabaseQueue 全局变量
创建一个队列_queue = dispatch_queue_create([[NSString stringWithFormat:@"fmdb.%@", self] UTF8String], NULL);默认是串行队列,数据库操作的时候FMDB源码如下图
FMDatabaseQueue 同步执行源码
同步执行串行队列 block块里按着顺序执行。
任务1执行 ——&任务二等待任务一执行完毕执行,任务一等待任务二执行完毕执行,死锁。 如果新建一个串行队列
这样就没有问题。 至于同步异步并行串行网上也有很多,不在一一介绍啦。
2 . STDBTool的初始化 ,很显然 STDBTool用的是单例啦, 看一下alloc方法
STDBTool 初始化
这里面也就是创建一下数据库文件,设置数据库版本号。
当数据库有新表需要增加时,我们需要改变数据库版本号,对数据库进行升级。
.查询数据库当前版本
NSString * sql = [NSString stringWithFormat:@"PRAGMA user_version"];
FMResultSet * rs = [db executeQuery:sql];
int nVersion = 0;
while ([rs next]) {
nVersion = [rs intForColumn:@"user_version"];
NSString * sql = [NSString stringWithFormat:@"PRAGMA user_version"];FMResultSet * rs = [db executeQuery:sql];&&&&&&int nVersion = 0;&&&&&&while ([rs next]) {&&&&&&&&&&nVersion = [rs intForColumn:@"user_version"];&&&&}
与宏定义数据库版本不一致 需要更新 设置 数据库版本号
NSString *sql = [NSString stringWithFormat:@"PRAGMA user_version = %ld",(long)newVersion];
BOOL ret = [db executeUpdate:sql];
NSString *sql = [NSString stringWithFormat:@"PRAGMA user_version = %ld",(long)newVersion];&& BOOL ret = [db executeUpdate:sql];
STDBTool初始化就这些吧。也没什么难点,主要是跟大家一起回顾一下。
3 .实现的数据库数据操作功能
一般数据库操作无非是增删改查这些基本操作,当然我的封装也是基于实现这些功能的。但是根据具体情况我们需要进行封装。
执行单个sql语句时候,不需要使用事务处理,我们需要知道操作类型,这里我写了个枚举type 便于区分
-(void)executeSQL:(NSString *)sqlStr actionType:(ST_DB_ActionType)actionType withBlock:(void(^)(BOOL bRet, FMResultSet *rs, NSString *msg))block{
[_dbQueue inDatabase:^(FMDatabase *db) {
if (actionType == ST_DB_SELECT) {
//查询语句 需要返回记录集
FMResultSet * rs = [db executeQuery:sqlStr];
if ([db hadError]) {
block(NO,rs,[db lastErrorMessage]);
NSLog(@"executeSQL error %d:
%@",[db lastErrorCode],[db lastErrorMessage]);
block(YES,rs,nil);
//更新操作 只关心操作是否执行成功,不关心记录集
返回布尔值
无执行结果
BOOL ret = [db executeUpdate:sqlStr];
if ([db hadError]) {
block(NO,nil,[db lastErrorMessage]);
NSLog(@"executeSQL error %d:
%@",[db lastErrorCode],[db lastErrorMessage]);
block(ret,nil,nil);
1234567891011121314151617181920212223
-(void)executeSQL:(NSString *)sqlStr actionType:(ST_DB_ActionType)actionType withBlock:(void(^)(BOOL bRet, FMResultSet *rs, NSString *msg))block{ [_dbQueue inDatabase:^(FMDatabase *db) {&&&& if (actionType == ST_DB_SELECT) {&&&&&&&& //查询语句 需要返回记录集&&&&&& FMResultSet * rs = [db executeQuery:sqlStr];&&&&&&&& if ([db hadError]) {&&&&&&&&&&&& block(NO,rs,[db lastErrorMessage]);&&&&&&&&&&&& NSLog(@"executeSQL error %d:&&%@",[db lastErrorCode],[db lastErrorMessage]);&&&&&&&& }else{&&&&&&&&&&&& block(YES,rs,nil);&&&&&&&& }&&&& }else{&&&&&&&& //更新操作 只关心操作是否执行成功,不关心记录集&&返回布尔值&&无执行结果&&&&&&&& BOOL ret = [db executeUpdate:sqlStr];&&&&&&&& if ([db hadError]) {&&&&&&&&&&&& block(NO,nil,[db lastErrorMessage]);&&&&&&&&&&&& NSLog(@"executeSQL error %d:&&%@",[db lastErrorCode],[db lastErrorMessage]);&&&&&&&& }else{&&&&&&&&&&&& block(ret,nil,nil);&&&&&&&& }&&&& } }];}
根据查询结果 确定是更新还是新增操作,只需要知道是否操作成功,不关心结果集 只处理一个查询更新,不需要事务处理
- (void)executeRelevanceSql:(NSArray *)sqlList withBlock:(void(^)(BOOL ret,NSString * errMsg))block{
__block BOOL
[_dbQueue inDatabase:^(FMDatabase *db) {
FMResultSet * rs = [db executeQuery:sqlList[0]];
if ([db hadError]) {
block(NO,[db lastErrorMessage]);
NSLog(@"da_error_%@",[db lastErrorMessage]);
int nCount = 0;
if ([rs next]) {
//获取查询数据的个数
nCount = [rs intForColumnIndex:0];
[rs close];
NSString * nextSqlString =
if (nCount & 0) {
//查询到了结果
执行update操作
nextSqlString = sqlList[1];
//查询无结果
执行 insert into 操作
nextSqlString = sqlList[2];
ret = [db executeUpdate:nextSqlString];
if ([db hadError]) {
block(NO,[db lastErrorMessage]);
NSLog(@"da_error_%@",[db lastErrorMessage]);
block(ret, nil);
12345678910111213141516171819202122232425262728293031323334
- (void)executeRelevanceSql:(NSArray *)sqlList withBlock:(void(^)(BOOL ret,NSString * errMsg))block{&&&&__block BOOL ret;&&&&[_dbQueue inDatabase:^(FMDatabase *db) {&&&&&&&&FMResultSet * rs = [db executeQuery:sqlList[0]];&&&&&&&&if ([db hadError]) {&&&&&&&&&&&&block(NO,[db lastErrorMessage]);&&&&&&&&&&&&NSLog(@"da_error_%@",[db lastErrorMessage]);&&&&&&&&}&&&&&&&&&int nCount = 0;&&&&&&&&if ([rs next]) {&&&&&&&&&&&&//获取查询数据的个数&&&&&&&&&&&&nCount = [rs intForColumnIndex:0];&&&&&&&&}&&&&&&&&[rs close];&&&&&&&&&NSString * nextSqlString = nil;&&&&&&&&if (nCount & 0) {&&&&&&&&&&&&//查询到了结果&&执行update操作&&&&&&&&&&&&nextSqlString = sqlList[1];&&&&&&&&}else{&&&&&&&&&&&&//查询无结果&&执行 insert into 操作&&&&&&&&&&&&nextSqlString = sqlList[2];&&&&&&&&}&&&&&&&&&ret = [db executeUpdate:nextSqlString];&&&&&&&&if ([db hadError]) {&&&&&&&&&&&&block(NO,[db lastErrorMessage]);&&&&&&&&&&&&NSLog(@"da_error_%@",[db lastErrorMessage]);&&&&&&&&}else{&&&&&&&&&&&&block(ret, nil);&&&&&&&&}&&&&}];}
注:sql语句数组,sqlList[0]查询select语句 sqList[1] update更新语句 sqlList[2] insert into 插入语句
根据查询结果 确定是更新还是新增操作,只需要知道是否操作成功,不关心结果集 只处理一个查询更新,不需要事务处理
- (void)executeRelevanceSql:(NSArray *)sqlList withBlock:(void(^)(BOOL ret,NSString * errMsg))block{
__block BOOL
[_dbQueue inDatabase:^(FMDatabase *db) {
FMResultSet * rs = [db executeQuery:sqlList[0]];
if ([db hadError]) {
block(NO,[db lastErrorMessage]);
NSLog(@"da_error_%@",[db lastErrorMessage]);
int nCount = 0;
if ([rs next]) {
//获取查询数据的个数
nCount = [rs intForColumnIndex:0];
[rs close];
NSString * nextSqlString =
if (nCount & 0) {
//查询到了结果
执行update操作
nextSqlString = sqlList[1];
//查询无结果
执行 insert into 操作
nextSqlString = sqlList[2];
ret = [db executeUpdate:nextSqlString];
if ([db hadError]) {
block(NO,[db lastErrorMessage]);
NSLog(@"da_error_%@",[db lastErrorMessage]);
block(ret, nil);
1234567891011121314151617181920212223242526272829303132
- (void)executeRelevanceSql:(NSArray *)sqlList withBlock:(void(^)(BOOL ret,NSString * errMsg))block{__block BOOL ret;[_dbQueue inDatabase:^(FMDatabase *db) {&&&&FMResultSet * rs = [db executeQuery:sqlList[0]];&&&&if ([db hadError]) {&&&&&&&&block(NO,[db lastErrorMessage]);&&&&&&&&NSLog(@"da_error_%@",[db lastErrorMessage]);&&&&}&&&&int nCount = 0;&&&&if ([rs next]) {&&&&&&&&//获取查询数据的个数&&&&&&&&nCount = [rs intForColumnIndex:0];&&&&}&&&&[rs close];&&&&&NSString * nextSqlString = nil;&&&&if (nCount & 0) {&&&&&&&&//查询到了结果&&执行update操作&&&&&&&&nextSqlString = sqlList[1];&&&&}else{&&&&&&&&//查询无结果&&执行 insert into 操作&&&&&&&&nextSqlString = sqlList[2];&&&&}&&&&ret = [db executeUpdate:nextSqlString];&&&&if ([db hadError]) {&&&&&&&&block(NO,[db lastErrorMessage]);&&&&&&&&NSLog(@"da_error_%@",[db lastErrorMessage]);&&&&}else{&&&&&&&&block(ret, nil);&&&&}}];}
注: sql语句数组,sqlList[0]查询select语句 sqListupdate更新语句 sqlList insert into 插入语句
4 . sqlList 是一个二维数组,每一个成员包含三个sql语句,分别是查询,更新,插入,并且根据查询结果返回是执行更新 还是 插入操作。使用dbQueue2 用于直接调用。批量处理,使用事务。
- (void)executeDbQueue2RelevanceTransactionSqlList:(NSArray *)sqlList withBlock:(void(^)(BOOL bRet, NSString *msg, BOOL *bRollback))block{
__block BOOL ret = NO;
[_dbQueue2 inTransaction:^(FMDatabase *db, BOOL *rollback) {
for (NSArray * singleSqlList in sqlList ) {
FMResultSet * rs = [db executeQuery:singleSqlList[0]];
if ([db hadError]) {
block(NO,[db lastErrorMessage],rollback);
NSLog(@"da_error_%@",[db lastErrorMessage]);
int nCount = 0;
while ([rs next]){
= [rs intForColumnIndex:0];
[rs close];
NSString * nextSqlString =
if (nCount & 0){
//执行更新
nextSqlString = singleSqlList[1];
//执行插入
nextSqlString = singleSqlList[2];
ret = [db executeUpdate:nextSqlString];
if ([db hadError])
block(NO, [db lastErrorMessage], rollback);
NSLog(@"executeSql Err %d: %@", [db lastErrorCode], [db lastErrorMessage]);
block(ret, nil, rollback);
123456789101112131415161718192021222324252627282930313233343536
- (void)executeDbQueue2RelevanceTransactionSqlList:(NSArray *)sqlList withBlock:(void(^)(BOOL bRet, NSString *msg, BOOL *bRollback))block{&&&&__block BOOL ret = NO;&&&&[_dbQueue2 inTransaction:^(FMDatabase *db, BOOL *rollback) {&&&&&&&&for (NSArray * singleSqlList in sqlList ) {&&&&&&&&&&&&FMResultSet * rs = [db executeQuery:singleSqlList[0]];&&&&&&&&&&&&if ([db hadError]) {&&&&&&&&&&&&&&&&block(NO,[db lastErrorMessage],rollback);&&&&&&&&&&&&&&&&NSLog(@"da_error_%@",[db lastErrorMessage]);&&&&&&&&&&&&}else{&&&&&&&&&&&&&&&&int nCount = 0;&&&&&&&&&&&&&&&&while ([rs next]){&&&&&&&&&&&&&&&&&&&&nCount&&= [rs intForColumnIndex:0];&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&[rs close];&&&&&&&&&&&&&&&&&NSString * nextSqlString = nil;&&&&&&&&&&&&&&&&if (nCount & 0){&&&&&&&&&&&&&&&&&&&&//执行更新&&&&&&&&&&&&&&&&&&&&nextSqlString = singleSqlList[1];&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&else{&&&&&&&&&&&&&&&&&&&&//执行插入&&&&&&&&&&&&&&&&&&&&nextSqlString = singleSqlList[2];&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&& ret = [db executeUpdate:nextSqlString];&&&&&&&&&&&&&&&&if ([db hadError])&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&block(NO, [db lastErrorMessage], rollback);&&&&&&&&&&&&&&&&&&&&NSLog(@"executeSql Err %d: %@", [db lastErrorCode], [db lastErrorMessage]);&&&&&&&&&&&&&&&&}&&&&&&&&&&&&}&&&&&&&&}&&&&&&&& block(ret, nil, rollback);&&&&}];}
注:sql语句数组,sqlArr[i][0]:查询语句;sqlArr:update语句;sqlArr:insert into语句
5.sql语句数组中每个成员有2条语句,第一条是select语句,第二条是insert into语句,根据第一个sql的执行结果确定第二条语句是否执行。根据查询结果确定是否新增,批量处理,使用事务处理,不需要返回记录集使用dbQueue2,用于程序中直接调用(非封装在其他方法中)
Objective-C
-(void)executeInsertTransactionSqlList:(NSArray *)sqlStrList withBlock:(void(^)(BOOL bRet, NSString *msg, BOOL *bRollback))block
__block BOOL ret = NO;
NSLog(@"开始啦---");
[_dbQueue2
inTransaction:^(FMDatabase *db, BOOL *rollback){
for (NSArray *sqlArray in sqlStrList){
FMResultSet *rs = [db executeQuery:[sqlArray objectAtIndex:0]];
if ([db hadError]){
block(NO, [db lastErrorMessage], rollback);
NSLog(@"executeSql Err %d: %@", [db lastErrorCode], [db lastErrorMessage]);
int nCount = 0;
while ([rs next]){
nCount = [rs intForColumnIndex:0];
[rs close];
if (nCount &= 0){
ret = [db executeUpdate:[sqlArray objectAtIndex:1]];
if ([db hadError])
block(NO, [db lastErrorMessage], rollback);
NSLog(@"executeSql Err %d: %@", [db lastErrorCode], [db lastErrorMessage]);
block(ret, nil, rollback);
12345678910111213141516171819202122232425262728293031
-(void)executeInsertTransactionSqlList:(NSArray *)sqlStrList withBlock:(void(^)(BOOL bRet, NSString *msg, BOOL *bRollback))block{&&&&__block BOOL ret = NO;&&&& NSLog(@"开始啦---");&&&&[_dbQueue2&&inTransaction:^(FMDatabase *db, BOOL *rollback){&&&&&&&&&for (NSArray *sqlArray in sqlStrList){&&&&&&&&&&&&FMResultSet *rs = [db executeQuery:[sqlArray objectAtIndex:0]];&&&&&&&&&&&&if ([db hadError]){&&&&&&&&&&&&&&&&block(NO, [db lastErrorMessage], rollback);&&&&&&&&&&&&&&&&NSLog(@"executeSql Err %d: %@", [db lastErrorCode], [db lastErrorMessage]);&&&&&&&&&&&&}&&&&&&&&&&&&&int nCount = 0;&&&&&&&&&&&&while ([rs next]){&&&&&&&&&&&&&&&&nCount = [rs intForColumnIndex:0];&&&&&&&&&&&&}&&&&&&&&&&&&[rs close];&&&&&&&&&&&&&if (nCount &= 0){&&&&&&&&&&&&&&&&ret = [db executeUpdate:[sqlArray objectAtIndex:1]];&&&&&&&&&&&&&&&&if ([db hadError])&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&block(NO, [db lastErrorMessage], rollback);&&&&&&&&&&&&&&&&&&&&NSLog(@"executeSql Err %d: %@", [db lastErrorCode], [db lastErrorMessage]);&&&&&&&&&&&&&&&&}&&&&&&&&&&&&}&&&&&&&&}&&&&&&&&block(ret, nil, rollback);&&&&}];}
注:sql语句数组,sqlArr[i][0]:查询语句;sqlArr:insert into语句
6.批量处理更新或者新增sql语句,不需要返回记录集 无事务处理
- (void)executeSQLList:(NSArray *)sqlStrList db:(FMDatabase *)db withBlock:(void(^)(BOOL bRet, NSString *msg))block{
__block BOOL bRet = NO;
for (NSString * sqlString in sqlStrList) {
bRet = [db executeUpdate:sqlString];
if ([db hadError]) {
block(bRet,[db lastErrorMessage]);
NSLog(@"executeSQLList Err %d: %@", [db lastErrorCode], [db lastErrorMessage]);
block(bRet,nil);
123456789101112
- (void)executeSQLList:(NSArray *)sqlStrList db:(FMDatabase *)db withBlock:(void(^)(BOOL bRet, NSString *msg))block{&&&&__block BOOL bRet = NO;&&&&for (NSString * sqlString in sqlStrList) {&&&&&&&&bRet = [db executeUpdate:sqlString];&&&&&&&&if ([db hadError]) {&&&&&&&&&&&&block(bRet,[db lastErrorMessage]);&&&&&&&&&&&&NSLog(@"executeSQLList Err %d: %@", [db lastErrorCode], [db lastErrorMessage]);&&&&&&&&&&&&break;&&&&&&&&}&&&&}&&&&block(bRet,nil);}
注: sql语句数组update或者insert into语句
7.批量处理更新或者新增sql语句,并且不需要返回记录集,使用事务处理
-(void)executeTransactionSqlList:(NSArray *)sqlStrList withBlock:(void(^)(BOOL bRet, NSString *msg, BOOL *bRollback))block
__block BOOL bRet = NO;
inTransaction:^(FMDatabase *db, BOOL *rollback){
for (NSString *sqlStr in sqlStrList)
bRet = [db executeUpdate:sqlStr];
if ([db hadError])
block(bRet, [db lastErrorMessage], rollback);
NSLog(@"executeSQLList Err %d: %@", [db lastErrorCode], [db lastErrorMessage]);
block(bRet, nil, rollback);
123456789101112131415161718
-(void)executeTransactionSqlList:(NSArray *)sqlStrList withBlock:(void(^)(BOOL bRet, NSString *msg, BOOL *bRollback))block{&&&&__block BOOL bRet = NO;&&&&[_dbQueue&&inTransaction:^(FMDatabase *db, BOOL *rollback){&&&&&&&&&for (NSString *sqlStr in sqlStrList)&&&&&&&&{&&&&&&&&&&&&bRet = [db executeUpdate:sqlStr];&&&&&&&&&&&&if ([db hadError])&&&&&&&&&&&&{&&&&&&&&&&&&&&&&block(bRet, [db lastErrorMessage], rollback);&&&&&&&&&&&&&&&&NSLog(@"executeSQLList Err %d: %@", [db lastErrorCode], [db lastErrorMessage]);&&&&&&&&&&&&&&&&break;&&&&&&&&&&&&}&&&&&&&&}&&&&&&&&block(bRet, nil, rollback);&&&&}];}
注:sql语句数组update或者insert into语句
还有几个方法在防止死循环嵌套 类似的函数。
,感觉有用的话star一下,谢谢大家。希望能帮到大家。
可能感兴趣的话题
o 102 回复
关于iOS频道
iOS频道分享iOS和Swift开发,应用设计和推广,iOS相关的行业动态。
新浪微博:
推荐微信号
(加好友请注明来意)
– 好的话题、有启发的回复、值得信赖的圈子
– 分享和发现有价值的内容与观点
– 为IT单身男女服务的征婚传播平台
– 优秀的工具资源导航
– 翻译传播优秀的外文文章
– 国内外的精选文章
– UI,网页,交互和用户体验
– 专注iOS技术分享
– 专注Android技术分享
– JavaScript, HTML5, CSS
– 专注Java技术分享
– 专注Python技术分享
& 2017 伯乐在线}

我要回帖

更多关于 dispatch group wait 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信