iOS中原生的SQLite API在使用上相当不友好,在使用时,非常不便。于是,就出现了一系列将SQLite API进行封装的库,例如FMDB、PlausibleDatabase、sqlitepersistentobjects等,FMDB (https://github.com/ccgus/fmdb) 是一款简洁、易用的封装库,这一篇文章简单介绍下FMDB的使用。
在FMDB下载文件后,工程中必须导入如下文件,并使用libsqlite3.dylib 依赖包。
FMDB同时兼容ARC和非ARC工程,会自动根据工程配置来调整相关的内存管理代码。
FMDatabase : 一个单一的SQLite数据库,用于执行SQL语句。
FMResultSet :执行查询一个FMDatabase结果集,这个和Android的Cursor类似。
FMDatabaseQueue :在多个线程来执行查询和更新时会使用这个类。
db = [FMDatabase databaseWithPath:database_path];
1、当数据库文件不存在时,fmdb会自己创建一个。
2、 如果你传入的参数是空串:@"" ,则fmdb会在临时文件目录下创建这个数据库,数据库断开连接时,数据库文件被删除。
3、如果你传入的参数是 NULL,则它会建立一个在内存中的数据库,数据库断开连接时,数据库文件被删除。
打开数据库:
[cpp]view plaincopy
[db?open]
返回BOOL型。
[db?close]
除了查询操作,FMDB数据库操作都执行executeUpdate方法,这个方法返回BOOL型。
看一下例子:
if([db open]) {
NSString?*sqlCreateTable?=??[NSString?stringWithFormat:@"CREATE?TABLE?IF?NOT?EXISTS?'%@'?('%@'?INTEGER?PRIMARY?KEY?AUTOINCREMENT,?'%@'?TEXT,?'%@'?INTEGER,?'%@'?TEXT)",TABLENAME,ID,NAME,AGE,ADDRESS];
BOOLres?=?[db?executeUpdate:sqlCreateTable];
if(!res)?{
NSLog(@"error?when?creating?db?table");
}else{
NSLog(@"success?to?creating?db?table");
}
[db?close];
}
添加数据:
if([db open]) {
NSString?*insertSql1=?[NSString?stringWithFormat:
@"INSERT?INTO?'%@'?('%@',?'%@',?'%@')?VALUES?('%@',?'%@',?'%@')",
TABLENAME,?NAME,?AGE,?ADDRESS,?@"张三",?@"13",?@"济南"];
BOOLres?=?[db?executeUpdate:insertSql1];
NSString?*insertSql2?=?[NSString?stringWithFormat:
@"INSERT?INTO?'%@'?('%@',?'%@',?'%@')?VALUES?('%@',?'%@',?'%@')",
TABLENAME,?NAME,?AGE,?ADDRESS,?@"李四",?@"12",?@"济南"];
BOOLres2?=?[db?executeUpdate:insertSql2];
if(!res)?{
NSLog(@"error?when?insert?db?table");
}else{
NSLog(@"success?to?insert?db?table");
}
[db?close];
}
修改数据:
if([db open]) {
NSString?*updateSql?=?[NSString?stringWithFormat:
@"UPDATE?'%@'?SET?'%@'?=?'%@'?WHERE?'%@'?=?'%@'",
TABLENAME,???AGE,??@"15",AGE,??@"13"];
BOOLres?=?[db?executeUpdate:updateSql];
if(!res)?{
NSLog(@"error?when?update?db?table");
}else{
NSLog(@"success?to?update?db?table");
}
[db?close];
}
删除数据:
if([db open]) {
NSString?*deleteSql?=?[NSString?stringWithFormat:
@"delete?from?%@?where?%@?=?'%@'",
TABLENAME,?NAME,?@"张三"];
BOOLres?=?[db?executeUpdate:deleteSql];
if(!res)?{
NSLog(@"error?when?delete?db?table");
}else{
NSLog(@"success?to?delete?db?table");
}
[db?close];
}
数据库查询操作:
查询操作使用了executeQuery,并涉及到FMResultSet。
if([db open]) {
NSString?*?sql?=?[NSString?stringWithFormat:
@"SELECT?*?FROM?%@",TABLENAME];
FMResultSet?*?rs?=?[db?executeQuery:sql];
while([rs?next])?{
intId?=?[rs?intForColumn:ID];
NSString?*?name?=?[rs?stringForColumn:NAME];
NSString?*?age?=?[rs?stringForColumn:AGE];
NSString?*?address?=?[rs?stringForColumn:ADDRESS];
NSLog(@"id?=?%d,?name?=?%@,?age?=?%@??address?=?%@",?Id,?name,?age,?address);
}
[db?close];
}
数据库多线程操作:
如果应用中使用了多线程操作数据库,那么就需要使用FMDatabaseQueue来保证线程安全了。 应用中不可在多个线程中共同使用一个FMDatabase对象操作数据库,这样会引起数据库数据混乱。 为了多线程操作数据库安全,FMDB使用了FMDatabaseQueue,使用FMDatabaseQueue很简单,首先用一个数据库文件地址来初使化FMDatabaseQueue,然后就可以将一个闭包(block)传入inDatabase方法中。 在闭包中操作数据库,而不直接参与FMDatabase的管理。
FMDatabaseQueue * queue = [FMDatabaseQueue databaseQueueWithPath:database_path];
dispatch_queue_t?q1?=?dispatch_queue_create("queue1",?NULL);
dispatch_queue_t?q2?=?dispatch_queue_create("queue2",?NULL);
dispatch_async(q1,?^{
for(inti?=?0;?i?<?50;?++i)?{
[queue?inDatabase:^(FMDatabase?*db2)?{
NSString?*insertSql1=?[NSString?stringWithFormat:
@"INSERT?INTO?'%@'?('%@',?'%@',?'%@')?VALUES?(?,??,??)",
TABLENAME,?NAME,?AGE,?ADDRESS];
NSString?*?name?=?[NSString?stringWithFormat:@"jack?%d",?i];
NSString?*?age?=?[NSString?stringWithFormat:@"%d",?10+i];
BOOLres?=?[db2?executeUpdate:insertSql1,?name,?age,@"济南"];
if(!res)?{
NSLog(@"error?to?inster?data:?%@",?name);
}else{
NSLog(@"succ?to?inster?data:?%@",?name);
}
}];
}
});
dispatch_async(q2,?^{
for(inti?=?0;?i?<?50;?++i)?{
[queue?inDatabase:^(FMDatabase?*db2)?{
NSString?*insertSql2=?[NSString?stringWithFormat:
@"INSERT?INTO?'%@'?('%@',?'%@',?'%@')?VALUES?(?,??,??)",
TABLENAME,?NAME,?AGE,?ADDRESS];
NSString?*?name?=?[NSString?stringWithFormat:@"lilei?%d",?i];
NSString?*?age?=?[NSString?stringWithFormat:@"%d",?10+i];
BOOLres?=?[db2?executeUpdate:insertSql2,?name,?age,@"北京"];
if(!res)?{
NSLog(@"error?to?inster?data:?%@",?name);
}else{
NSLog(@"succ?to?inster?data:?%@",?name);
}
}];
}
});