昨天做一个需求,参数的数量不确定,所以无法使用这个API:
- (BOOL)executeUpdate:(NSString*)sql, ...
但是用
- (BOOL)executeUpdate:(NSString*)sql withParameterDictionary:(NSDictionary *)arguments
可以很方便地处理这个场景,本文总结一下
两类insert语句
因为不管使用哪种API,都需要先拼接sql语句,所以先了解一下sql insert语句的写法。有2种,比较常见的是指定列名的insert:
insert into table_name (c1,c2,c3) values (v1,v2,v3);
如果自己指定了目标列名,那么插入的列的数量可以少于table schema,列的顺序也可以任意指定。第2种是不指定列名的insert:
insert into table_name values (v1,v2,v3);
这种写法不需要自己指定列名,比较方便,但是
values里需要包含所有的列,而且顺序要和table schema一致
FMDB的2种常用API
我自己比较常用的FMDB API有2个。如果参数的数量是确定的,而且不多,可以用这个API:
NSString *sql = @"insert into users values(:id, :name, :age)";
[db executeUpdate:sql, id, name, age];
上面的代码用了:key的语法,或者用?,效果也是一样的
NSString *sql = @"insert into users values(?,?,?)";
[db executeUpdate:sql, id, name, age];
另外一种场景,是参数的数量不确定,或者参数数量非常多,那上面这个API就不太方便,FMDB提供了另一个API,允许传入一个NSDictionary作为参数:
NSString *sql = @"insert into users values(:id, :name, :age)";
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:@"id123", @"id", @"kyfxbl", @"name", 23, @"age", nil];
[db executeUpdate:sql withParameterDictionary:dict];
注意Dictionary里的key需要和sql里的:key一致,FMDB根据key值来决定如何绑定
遇到的问题
我昨天就是用上面的第二种API来实现,不过遇到一个错误,总是报table_name.id may not be NULL。最后发现原因,是拼的sql采用了不指定列名的方式,类似于:
NSString *sql = @"insert into table_name values (:k1,:k2,:k3)";
然后刚好NSDictionary里元素的顺序又是错的,第一个元素的值是null,造成id为空,插入失败。其实关键不在于FMDB,而是sql没拼对。主要是我不了解FMDB的这个API,我以为它会自己处理顺序,实际上,FMDB不处理SQL拼接,只处理参数变量替换
有2个办法可以解决这个问题,一个办法是调整Dictionary里元素的顺序,使它和table schema列定义的顺序一致,不过比较困难。另一个办法就是重新拼sql,指定好列名
实际的代码
下面是实现的代码,删除了无关代码,以免干扰
-(void) handleJsonObject:(NSDictionary*) tableName
{
NSString *sql = [self assembleInsertSql:tableName];// 拼装sql语句:insert into table_name (c1,c2,c3) values (:a,:b,:c);
if(!sql){
return;// 说明data里无数据,不需要操作数据库
}
NSString *dbFilePath = [YLSGlobalUtils getDatabaseFilePath];
FMDatabase *db = [FMDatabase databaseWithPath:dbFilePath];
[db open];
NSArray *datas = [tableName objectForKey:@"data"];
for(NSDictionary *data in datas){
NSMutableDictionary *mutable = [NSMutableDictionary dictionaryWithDictionary:data];
[mutable removeObjectForKey:@"_id"];
BOOL result = [db executeUpdate:sql withParameterDictionary:mutable];
if(!result){
NSLog([NSString stringWithFormat:@"%d", [db lastErrorCode]], nil);
NSLog([db lastErrorMessage], nil);
}
}
[db close];
}
// 返回格式:insert into table_name (c1,c2,c3) values (:a,:b,:c);
-(NSString*) assembleInsertSql:(NSDictionary*) tableName
{
NSArray *datas = [tableName objectForKey:@"data"];
if([datas count] == 0){
return nil;
}
NSDictionary *record = [datas objectAtIndex:0];// 取出第一条记录,为了拿到列名
NSArray *columns = [record allKeys];
NSString *table = [tableName objectForKey:@"tableName"];
NSString *prefix = [NSString stringWithFormat:@"insert into %@ (", table];
NSMutableString *middle = [NSMutableString new];
for(int i=0;i<[columns count];i++){
NSString *columnName = [columns objectAtIndex:i];// 列名
if(![@"_id" isEqualToString:columnName]){
[middle appendString:columnName];
[middle appendString:@","];
}
}
NSString* cuttedMiddle = [YLSGlobalUtils removeLastOneChar:middle];
NSMutableString *suffix = [NSMutableString new];
[suffix appendString:@") values ("];
for(int i=0;i<[columns count];i++){
NSString *columnName = [columns objectAtIndex:i];// 列名
if(![@"_id" isEqualToString:columnName]){
[suffix appendString:@":"];
[suffix appendString:columnName];
[suffix appendString:@","];
}
}
NSString *cuttedSuffix = [YLSGlobalUtils removeLastOneChar:suffix];
NSMutableString *sql = [NSMutableString new];
[sql appendString:prefix];
[sql appendString:cuttedMiddle];
[sql appendString:cuttedSuffix];
[sql appendString:@");"];
return sql;
}
通过上面拼接sql的方法,虽然NSDictionary里的元素顺序不确定,但是列名和values里的顺序总是保证一致的,不会影响最后的插入
分享到:
相关推荐
对FMDB进行了二次封装,用起来更加方便简洁,无需再次书写sql语句,想学习FMDB的小伙伴们快来下载吧
数据库第三方FMDB,直接拖到工程中,引入相关文件就可以使用第三方FMDB的功能类。
此demo使用单例使用FMDB对数据库进行增、删、改、查;demo实现详细
fmdb的lib库,包括源代码等相关信息。可以直接将代码拖入到xcode项目中使用
fmdb数据库封装
ios数据库sqlite封装,FMDB最新打包,简单方便!
ios开发,用FMDB数据库开发的一个手机通讯录,支持查询,滑动删除等。
对FMDB的简单封装
fmdb本地数据库操作,增删改查
FMDB的自定义单例类的数据库demo
FMDB数据库的简单实用,帮助iOS开发者进行数据存储,包含增删改和队列封装
FMDB库
FMDB的两种多线程操作数据库创建表、插入、删除、更新、查询等。
FMDB 简单使用啦
Swift基础之FMDB的使用Demo
使用fmdb的一个ios demo
对FMDB的进一步封装,对常用的sql进行了封装,不需要去写SQL
http://blog.csdn.net/xyz_lmn/article/details/9312837 iOS学习笔记——数据库操作(使用FMDB)
FMDB是一个数据库的第三方类,相比于苹果官方coreData,更加轻量级,灵活!
一款轻量级的ios数据库存储、插入、获取、删除的代码操作,里面已经做好了封装,使用的时候只需相应的数据模型添加自己的属性,同时在创建表的时候增加属性即可。