FMDB的简单概述

这篇博客主要是用来简单介绍一下FMDB的基础用法,涉及到简单的增删改查

一:FMDB介绍

FMDB是一种第三方的开源库,FMDB就是对SQLite的API进行了封装,加上了面向对象的思想,简单来说就是让我们能更方遍的操作SQLite更加方便。

FMDB优点:

  • 使用起来更加面向对象,省去了很多麻烦、冗余的C语言代码
  • 对比苹果自带的CoreData框架,更加轻量级和灵活
  • 提供多线程安全,有效地防止数据混乱,原来的SQLite不是线程安全的

使用FMDB需要的步骤:

  1. 项目中添加libsqlite3库的依赖
  2. 推荐直接使用cocoapods导入到项目当中
  3. 在需要用到的类中导入FMDB的头文件 #import "FMDatabase.h"

二:FMDB的使用

FMDB的具体步骤我简单的归类为一下几个小点,下面会一一描述相应的citydb就是城市的数据库:

  1. 创建数据库
  2. 打开数据库
  3. 创建相应的库表
  4. 对库表进行操作
  5. 对查出数据的解析
  6. 关闭数据库

1:创建数据库的方法

根据FMDB官方的注解翻译过来的意思就是

/*
 1. 这个文件不一定必须存在沙盒中,所以如果已经存在的话就直接使用,不存在就会帮你创建一个;
 2. 你可以选择直接传空的字符串,那么系统会在临时目录创建一个空的数据库,当数据库关闭时,该数据库文件也被删除;
 3. 如果传nil,会在内存中临时创建一个空的数据库,当数据库关闭时,数据库文件也被删除;
*/
+ (FMDatabase *)databaseWithPath:(NSString *)filePath;

相应的实现方法是:

NSString *DocumentPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSString *dbPath = [DocumentPath stringByAppendingPathComponent:@"data.db"];
FMDatabase *citydb = [FMDatabase databaseWithPath:dbPath];

2:打开数据库

/*
打开数据库,一般用法是在查询语句之前调用一下,返回值是BOOL类型,这个BOOL的意思是告诉你这次打开是否成功,然后打开成功以后你就能对你的数据库进行操作了
*/
[citydb open];

3:创建库表

这里额外说明一下,[citydb executeUpdate:sql];这句话用的是executeUpdate方法,因为添加库表可以理解为更新数据库的行为,所以executeUpdate是可行的,同时用executeStatements方法也是同样可行的,executeStatements简单理解就是让数据库运行这个方法里的行为。

    FMDatabase * db = [FMDatabase databaseWithPath:self.dbPath];
    if ([db open]) {
        NSString *sql = @"create table if not exists city(cityName text, cityId text, userId text);";
        [citydb executeUpdate:sql];
    }
    

4:对数据库进行操作

/* 执行更新的SQL语句,字符串里面的"?",依次用后面的参数替代,必须是对象,不能是int等基本类型 */
- (BOOL)executeUpdate:(NSString *)sql,... ;
/* 执行更新的SQL语句,可以使用字符串的格式化进行构建SQL语句 */
- (BOOL)executeUpdateWithFormat:(NSString*)format,... ;
/* 执行更新的SQL语句,字符串中有"?",依次用arguments的元素替代 */
- (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments;

下面我在列举一下简单的增删改查四个方法

增加字段到city

FMDatabase * db = [FMDatabase databaseWithPath:self.dbPath];
    if ([db open]) {
        BOOL res = NO;
        NSDictionary *cityDic = @{@"杭州":@"1",@"上海":@"2",@"宁波":@"3",@"温州":@"4",@"台州":@"5",@"湖州":@"6",@"绍兴":@"7",@"金华":@"8"};
        for (NSString *key in cityDic.allKeys) {
            NSString *sqlStr = [NSString stringWithFormat:@"insert into city(cityName,cityId,userId)values('%@','%@','%@')",key,cityDic[key],@"123"];
            res = [db executeUpdate:sqlStr];
        }
        if (!res) {
            NSLog(@"error to insert  city");
        } else {
            NSLog(@"success to insert  city");
        }
        [db close];
    }

删除city表中,cityName为“杭州” 且cityId为“1”的字段

FMDatabase *db = [FMDatabase databaseWithPath:self.dbPath];
    if ([db open]) {
        NSString *sql = [NSString stringWithFormat:@"delete from city where cityName = '%@' and cityId = '%@'",@"杭州",@"1"];
        BOOL rs = [db executeUpdate:sql];
        if (!rs) {
            NSLog(@"error to update city");
        } else {
            NSLog(@"success to update city");
        }
        
        [db close];
    }

修改city表中,cityId为“2”的字段

FMDatabase * db = [FMDatabase databaseWithPath:self.dbPath];
    if ([db open]) {
        NSString *sqlStr = [NSString stringWithFormat:@"update city set cityName = '%@' where cityId = '2'",self.textField.text];
        BOOL res = [db executeUpdate:sqlStr];
        if (!res) {
            NSLog(@"error to insert  city");
        } else {
            NSLog(@"success to insert  city");
        }
        [db close];
    }

查询city表中的所有字段

FMDatabase *db = [FMDatabase databaseWithPath:self.dbPath];
    if ([db open]) {
        NSMutableDictionary *mutableDic = [[NSMutableDictionary alloc] init];
        NSString *sql = [NSString stringWithFormat:@"select * from city where userId = '%@'",@"123"];
        FMResultSet *rs = [db executeQuery:sql];
        while ([rs next]) {
            NSString *name = [rs stringForColumn:@"cityName"];
            NSString *cityId = [rs stringForColumn:@"cityId"];
            [mutableDic setObject:cityId forKey:name];
        }
        [db close];
        NSLog(@"%@",mutableDic);
    }

5:对查出的数据的解析

在得到查出的数据以后,需要对数据进行一些对应的解析,根据数据的类型要分别处理

/* 获取下一个记录 */
- (BOOL)next;
/* 获取记录有多少列 */
- (int)columnCount;
/* 通过列名得到列序号,通过列序号得到列名 */
- (int)columnIndexForName:(NSString *)columnName;
- (NSString *)columnNameForIndex:(int)columnIdx;
/* 获取存储的整形值 */
- (int)intForColumn:(NSString *)columnName;
- (int)intForColumnIndex:(int)columnIdx;
/* 获取存储的长整形值 */
- (long)longForColumn:(NSString *)columnName;
- (long)longForColumnIndex:(int)columnIdx;
/* 获取存储的布尔值 */
- (BOOL)boolForColumn:(NSString *)columnName;
- (BOOL)boolForColumnIndex:(int)columnIdx;
/* 获取存储的浮点值 */
- (double)doubleForColumn:(NSString *)columnName;
- (double)doubleForColumnIndex:(int)columnIdx;
/* 获取存储的字符串 */
- (NSString *)stringForColumn:(NSString *)columnName;
- (NSString *)stringForColumnIndex:(int)columnIdx;
/* 获取存储的日期数据 */
- (NSDate *)dateForColumn:(NSString *)columnName;
- (NSDate *)dateForColumnIndex:(int)columnIdx;
/* 获取存储的二进制数据 */
- (NSData *)dataForColumn:(NSString *)columnName;
- (NSData *)dataForColumnIndex:(int)columnIdx;
/* 获取存储的UTF8格式的C语言字符串 */
- (const unsigned cahr *)UTF8StringForColumnName:(NSString *)columnName;
- (const unsigned cahr *)UTF8StringForColumnIndex:(int)columnIdx;
/* 获取存储的对象,只能是NSNumber、NSString、NSData、NSNull */
- (id)objectForColumnName:(NSString *)columnName;
- (id)objectForColumnIndex:(int)columnIdx;

6:数据库表的关闭

/*
关闭数据库,在你对数据库的操作完成以后要记得关闭数据库
*/
[citydb close];

三:一些注意事项

下面要讲一讲我在学习FMDB的时候遇到的一些问题,给我的感觉呢,FMDB在Xcode中编写其实还是挺糟心的。因为你会发现有时候稍微写错一点点东西,就能让你整个方法崩溃,有可能一个简单的(')就让你整句查询语句说拜拜= =,而且Xcode不会告诉你到底是哪里出了问题,这就让人很难过了,所以你能做到的只有孰能生巧,不断的让自己熟练,少犯这样的低级错误。

在执行查询语句的时候一定要用- (BOOL)next 方法,就算你只查一个数据,也一定要用

错误的示范(因为只查一个数据,所以自以为是的没用next方法,然后GG了(╯‵□′)╯︵┻━┻)

if ([db open]) {
        NSString *sql = [NSString stringWithFormat:@"select * from city where cityId = '%@'",@"2"];
        FMResultSet *rs = [db executeQuery:sql];
        NSString *name = [rs stringForColumn:@"cityName"];
        [db close];
    }

正确的姿势应该是这样的

if ([db open]) {
        NSString *sql = [NSString stringWithFormat:@"select * from city where cityId = '%@'",@"2"];
        FMResultSet *rs = [db executeQuery:sql];
        while ([rs next]) {
            NSString *name = [rs stringForColumn:@"cityName"];
        }
        [db close];
    }

另外就是,在操作数据库的时候,大家一定要注意多线程的问题
FMDatabase这个类是线程不安全的,如果在多个线程同时使用一个FMDatabase实例,会造成数据混乱问题。
为了保证线程安全,FMDB提供方便快捷的FMDatabaseQueue类,要使用这个类,需要#import导入头文件"FMDatabaseQueue.h"FMDatabaseQueue类的操作大多都和FMDatabase很相似

最后要感谢一下同事陪我把这些东西一起弄懂,也学会了挺多,阿弥陀佛~

你可能感兴趣的:(FMDB的简单概述)