iOS数据库FMDB操作
时间:2020-07-11 14:04:22
收藏:0
阅读:75
1、获取操作对象、获取\创建数据库
-
1.1 获取操作对象、获取数据库
- CHFmdb.h
#import <Foundation/Foundation.h> NS_ASSUME_NONNULL_BEGIN // 数据库管理器 #define CHDbMgr [CHFmdb shareInstance].fmdb // 数据库管理队列,该对象支持多线程操作 #define CHDbQueue [CHFmdb shareInstance].queue @interface CHFmdb : NSObject /** 数据库管理器 */ @property(nonatomic, strong) FMDatabase *fmdb; /** 数据库管理队列,该对象支持多线程操作 */ @property(nonatomic, strong) FMDatabaseQueue *queue; + (instancetype)shareInstance; @end NS_ASSUME_NONNULL_END
- CHFmdb.m
- 根据原数据库文件,拷贝数据库到沙盒文件夹,得到应用内部的数据库文件。这种方式通常应用表现在:提供电子书内容源文件用于展示。
#import "CHFmdb.h" @interface CHFmdb () @end #define DataBaseName @"OutLibrary" @implementation CHFmdb + (instancetype)shareInstance { static CHFmdb *fmdbMgr = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ fmdbMgr = [[self alloc] init]; // 判断是否存在数据库,如果有,就继续,如果没有就将工程里面的复制到Document // 获取所有文档路径 NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); // 获取第一个路径 NSString *docPath = [searchPaths objectAtIndex:0]; // 拼接完整路径 NSString *dbPath = [docPath stringByAppendingPathComponent:@"BookLibrary.db"]; // 创建文件管理器 NSFileManager *fileManager = [[NSFileManager alloc] init]; // 判断该路径上是否存在数据库 BOOL isExit = [fileManager fileExistsAtPath:dbPath]; // 如果不存在,讲工程里面数据库的复制到Document里面 if (!isExit) { // 获取工程里面的数据库路径 NSString *bundleDBPath = [[NSBundle mainBundle] pathForResource:DataBaseName ofType:@"db"]; // 拷贝工程里面的数据库到沙盒 BOOL success = [fileManager copyItemAtPath:bundleDBPath toPath:dbPath error:nil]; if (success) { //CHLog(@"数据库复制成功"); } } // 根据数据库路径创建数据库管理器 fmdbMgr.fmdb = [[FMDatabase alloc] initWithPath:dbPath]; // 为数据库设置缓存,提高查询效率 [fmdbMgr.fmdb setShouldCacheStatements:YES]; // 根据数据库路径创建数据库管理队列,该对象支持多线程操作 fmdbMgr.queue = [FMDatabaseQueue databaseQueueWithPath:dbPath]; }); return fmdbMgr; } @end
-
1.2 创建数据库
- CHFmdb.m
- 根据数据库文件路径获取数据库管理器,数据库不存在则自动根据路径创建。这种方式通常应用表现在:保存个人喜好,健康数据等。
#import "CHFmdb.h" @interface CHFmdb () @end @implementation CHFmdb + (instancetype)shareInstance { static CHFmdb *fmdbMgr = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ fmdbMgr = [[self alloc] init]; // 判断是否存在数据库,如果有,就继续,如果没有就将工程里面的复制到Document // 获取所有文档路径 NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); // 获取第一个路径 NSString *docPath = [searchPaths objectAtIndex:0]; // 拼接完整路径 NSString *dbPath = [docPath stringByAppendingPathComponent:@"BookLibrary.db"]; // 根据数据库路径创建数据库管理器 fmdbMgr.fmdb = [[FMDatabase alloc] initWithPath:dbPath]; // 为数据库设置缓存,提高查询效率 [fmdbMgr.fmdb setShouldCacheStatements:YES]; // 根据数据库路径创建数据库管理队列,该对象支持多线程操作 fmdbMgr.queue = [FMDatabaseQueue databaseQueueWithPath:dbPath]; }); return fmdbMgr; } @end
- CHFmdb.m
2、FMDatabase 详细操作
-
2.0 创建表
- 先判断表是否存在,不存在再创建。属性修饰:字符串用->TEXT, 整型值用->INTEGER。
- 创建 t_ReadHistory 表,属性有自动增长唯一的ID, 书本ID:bookId, 书名:bookName, 阅读时间:readTime
if ([CHDbMgr open]) { NSString *sqlStr = NSStringFormat(@"CREATE TABLE IF NOT EXISTS t_ReadHistory(id INTEGER PRIMARY KEY AUTOINCREMENT, bookId INTEGER, bookName TEXT, readTime TEXT);"); BOOL success = [CHDbMgr executeUpdate:sqlStr]; }
-
2.1 增 insert into
- executeUpdate:不确定的参数用?来占位(后面参数必须是oc对象,“;”代表语句结束)
- 例如基础数据类型的要加 “@(xxx)”转成对象类型NSNumber。
if ([CHDbMgr open]) { [CHDbMgr executeUpdate:@"insert into t_ReadHistory(bookId, bookName, readTime) values(?,?,?);" , @(1001), @"西游记", @"2020年06月23日"]; }
- executeUpdateWithForamat:不确定的参数用%@,%d等来占位(参数为原始数据类型,执行语句不区分大小写)
if ([CHDbMgr open]) { [CHDbMgr executeUpdateWithForamat:@"insert into t_ReadHistory(bookId, bookName, readTime) values(%ld, %@, %ld);", @(1001), @"西游记", @"2020年06月23日"]; }
- 参数是数组的使用方式
if ([CHDbMgr open]) { [CHDbMgr executeUpdate:@"insert into t_ReadHistory (bookId, bookName, readTime) values(?, ?, ?);" withArgumentsInArray:@[@(1001), @"西游记", @"2020年06月23日"]]; }
- executeUpdate:不确定的参数用?来占位(后面参数必须是oc对象,“;”代表语句结束)
-
2.2 删 delete
- 不确定的参数用?来占位 (后面参数必须是oc对象,需要将int包装成OC对象)
if ([CHDbMgr open]) { [CHDbMgr executeUpdate:@"delete from t_ReadHistory where bookId = ?;", @(1001)]; }
- 不确定的参数用%@,%d等来占位
if ([CHDbMgr open]) { [CHDbMgr executeUpdateWithFormat:@"delete from t_ReadHistory where bookName = %@;", @"西游记"]; }
-
2.3 查 select ... from
if ([CHDbMgr open]) { // FMResultSet结果集 FMResultSet *set = [CHDbMgr executeQuery:@"select bookId, bookName, readTime from t_ReadHistory;"]; // next 返回yes说明有数据 if ([set next]) { NSInteger bookId = [set intForColumn:@"bookId"]; NSString *bookName = [set stringForColumn:@"bookName"]; NSString *readTime = [set stringForColumn:@"readTime"]; } else { CHLog(@"查询出错"); } }
- 查询说明
- select命令就是查询,执行查询的方法是以-excuteQuery开头的。
- 执行查询时,如果成功返回FMResultSet对象,错误返回nil。
- 与执行更新相当,支持使用NSError参数。
- 同时,你也可以使用-lastErrorCode和-lastErrorMessage获知错误信息。
- FMResultSet获取不同数据格式的方法:
intForColumn: longForColumn: longLongIntForColumn: boolForColumn: doubleForColumn: stringForColumn: dataForColumn: dataNoCopyForColumn: UTF8StringForColumnIndex: objectForColumn:
- 查询符合要求的结果条数
if ([CHDbMgr open]) { // 查符合条件的书的总数 sqlStr = @"select COUNT(*) from t_ReadHistory where bookId = ?;"; NSUInteger bookCount = [CHDbMgr intForQuery:sqlStr, @(1001)]; }
- 查询说明
-
2.4 改 update
if ([CHDbMgr open]) {
[CHDbMgr executeUpdate:@"update t_ReadHistory set bookName = ? where bookId = ?", @"红楼梦", @(1001)];
}
-
2.5 删除表 drop ...
if ([CHDbMgr open]) {
// 如果表格存在 则销毁
[CHDbMgr executeUpadate:@"drop BookLibrary if existst t_ReadHistory;"];
}
-
2.6 当添加了一列数据时,如果有需要,获取自增的id:
if ([CHDbMgr open]) {
BOOL success = [CHDbMgr executeUpdate:@"insert into t_ReadHistory(bookId, bookName, readTime) values(?,?,?);" , @(1001), @"西游记", @"2020年06月23日"];
if (success) {
// 此处为刚才添加的自增id号
NSInteger logid = CHDbMgr.lastInsertRowId;
CHLog(@"NSInteger == %ld", logid);
}
}
3、FMDatabaseQueue类 实现多线程操作
- 在多个线程中同时使用一个FMDatabase实例是不明智的。现在你可以为每个线程创建一个FMDatabase对象,不要让多个线程分享同一个实例,他无法在多个线程中同事使用。否则程序会时不时崩溃或者报告异常。所以,不要初始化FMDatabase对象,然后在多个线程中使用。这时候,我们就需要使用FMDatabaseQueue来创建队列执行事务。
- 创建表
// 会通过block传递队列中创建好的数据库给我们
[CHDbQueue inDatabase:^(FMDatabase *db) {
// 编写需要执行的代码
NSString *sqlStr = NSStringFormat(@"CREATE TABLE IF NOT EXISTS t_ReadHistory(id INTEGER PRIMARY KEY AUTOINCREMENT, bookId INTEGER, bookName TEXT, readTime TEXT);");
BOOL success = [db executeUpdate:sqlStr];
if (success) {
CHLog(@"创建表成功");
}
else {
CHLog(@"创建表失败");
}
}];
- 多任务操作
// 会通过block传递队列中创建好的数据库给我们
[CHDbQueue inDatabase:^(FMDatabase *db) {
// 编写需要执行的代码
[db executeUpdate:@"insert into t_ReadHistory(bookId, bookName, readTime) values(?,?,?);" , @(1001), @"西游记", @"2020年06月23日"];
[db executeUpdate:@"insert into t_ReadHistory(bookId, bookName, readTime) values(?,?,?);" , @(1002), @"三国演义", @"2020年06月23日"];
}];
原文:https://www.cnblogs.com/CH520/p/13179204.html
评论(0)