iOS FMDB 数据库

FMDB

1、简述:

* FMDB是iOS平台的SQLite数据库框架,是对libsqlite3框架的封装

* FMDB以OC的方式封装了SQLite的C语言API

2、FMDB的优点:

* 使用起来更加面向对象,省去了很多麻烦、冗余的C语言代码

* 对比苹果自带的Core Data框架,更加轻量级和灵活

* 提供了多线程安全的数据库操作方法,有效地防止数据混乱

3、FMDB的github地址 传送门

4、FMDB的三个核心类

FMDatabase —— 一个FMDatabase对象就代表一个单独的SQLite数据库 用来执行SQL语句

FMResultSet —— 使用FMDatabase执行查询后的结果集

FMDatabaseQueue —— 用于在多线程中执行多个查询或更新,它是线程安全的

5、基本使用

1、下载FMDB文件的GitHub,并将FMDB文件夹添加到项目中(也可使用CocoaPods导入)—— pod'FMDB'

2、导入libsqlite3.0框架,导入头文件FMDatabase.h

3、代码实现,与SQLite使用步骤相似,创建数据库路径,获得数据库路径,打开数据库,然后对数据库进行增、删、改、查操作,最后关闭数据库。

导入libsqlite3.0库

实例Demo

本例是一个学生的数据库表格student,每个学生都自己所选的课程class,具体信息如下图Model:

Model

1、具体操作界面

具体操作界面

2、上代码

2.1、创建 DataForFMDB.h 类,导入头文件

#import"DataForFMDB.h"

#import <FMDB.h>

2.2、创建FMDB单例,以便全局共享

@interface DataForFMDB (){

FMDatabase *fmdb;

}

@end


@implementation DataForFMDB

static DataForFMDB *theData = nil;

+(instancetype)sharedDataBase{

@synchronized(self) {

if(!theData) {

theData = [[DataForFMDB alloc] init];

[theData initDataBase];

}

}

return theData;

}


-(void)initDataBase{

//获得Documents目录路径

NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];

//文件路径

NSString *filePath = [documentPath stringByAppendingPathComponent:@"student.db"];

//实例化FMDataBase对象

NSLog(@"---path:%@",filePath);

fmdb = [FMDatabase databaseWithPath:filePath];

if([fmdb open]) {

//初始化数据表

[self addStudentTable];

[self addClassTable];

[fmdb close];

}else{

NSLog(@"数据库打开失败---%@", fmdb.lastErrorMessage);

}

}


-(void)addStudentTable{

NSString*studentSQL =@"create table if not exists student (id integerPrimary Key Autoincrement, sId integer, sName text, sAge integer)";

BOOL studentSuccess = [fmdb executeUpdate:studentSQL];

if(!studentSuccess) {

NSLog(@"studentTable创建失败---%@",fmdb.lastErrorMessage);

}

}


-(void)addClassTable{

NSString*classSQL =@"create table if not exists class (id integerPrimary Key Autoincrement,scId integer, cName text)";

BOOL classSuccess = [fmdbexecuteUpdate:classSQL];

if(!classSuccess) {

NSLog(@"classTable创建失败---%@",fmdb.lastErrorMessage);

}

}


2.3、获取student表全部内容

-(NSMutableArray*)getAllStudent{

[fmdb open];

NSMutableArray *array = [NSMutableArray new];

FMResultSet *result = [fmdb executeQuery:@"select * from student"];

while([result next]) {

StudentFMDBModel *student = [[StudentFMDBModel alloc] init];

student.sId = [[result stringForColumn:@"sId"] integerValue];

student.sName= [result stringForColumn:@"sName"];

student.sAge= [[result stringForColumn:@"sAge"] integerValue];

[array addObject:student];

}

[fmdb close];

return array;

}


//调用

self.dataArray= [[DataForFMDB sharedDataBase] getAllStudent];


2.4、student表添加内容

-(void)addStudent:(StudentFMDBModel*)student{

[fmdb open];

NSString *SQL =@"insert into student(sId,sName,sAge) values(?,?,?)";

BOOL isAddSuccess = [fmdb executeUpdate:SQL,@(student.sId),student.sName,@(student.sAge)];

if(!isAddSuccess) {

NSLog(@"studentTable插入信息失败--%@",fmdb.lastErrorMessage);

}

[fmdb close];

}


//调用

[[DataForFMDB sharedDataBase] addStudent:student];


2.5、student表删除内容

-(void)deleteStudent:(StudentFMDBModel*)student{

[fmdb open];

NSString *SQL =@"delete from student where sId = ?";

BOOL isDeleteSuccess = [fmdb executeUpdate:SQL,@(student.sId)];

if(!isDeleteSuccess) {

NSLog(@"studentTable删除某一信息失败--%@",fmdb.lastErrorMessage);

}

[fmdb close];

}


//调用

[[DataForFMDB sharedDataBase] deleteStudent:self.dataArray[indexPath.row]];


2.6、student表修改内容

-(void)updateStudent:(StudentFMDBModel*)student{

[fmdb open];

NSString *SQL1 =@"update student set sName = ? where sId = ?";

NSString *SQL2 =@"update student set sAge = ? where sId = ?";

BOOL isSuccess1 = [fmdbexecuteUpdate: SQL1, student.sName,@(student.sId)];

BOOL isSuccess2 = [fmdbexecuteUpdate: SQL2,@(student.sAge),@(student.sId)];

if(!isSuccess1) {

NSLog(@"student.sName修改失败--%@",fmdb.lastErrorMessage);

}

if(!isSuccess2) {

NSLog(@"student.sAge修改失败--%@",fmdb.lastErrorMessage);

}

[fmdb close];

}


//调用

[[DataForFMDB sharedDataBase] updateStudent:student];


2.7、删除student表

-(void)deleteAllStudent{

[fmdb open];

NSString *SQL =@"delete from student";

BOOL isSuccess = [fmdb executeUpdate:SQL];

if(!isSuccess) {

NSLog(@"studentTable全部删除失败--%@",fmdb.lastErrorMessage);

}

//student表删除以后,对应的class也要删除

[self deleteAllClass];

[fmdb close];

}


//调用

[[DataForFMDB sharedDataBase] deleteAllStudent];


2.8、获取某一student class表的全部课程

-(NSMutableArray*)getAllClassFromStudent:(StudentFMDBModel*)student{

[fmdb open];

NSMutableArray *array = [NSMutableArray new];

FMResultSet *result = [fmdb executeQuery:[NSString stringWithFormat:@"select * from class where scId = %ld", student.sId]];

while([result next]) {

StudentClassModel*class = [[StudentClassModel alloc] init];

class.cName= [result stringForColumn:@"cName"];

[array addObject:class];

}

[fmdb close];

return array;

}


//调用

self.dataArray= [[DataForFMDB sharedDataBase] getAllClassFromStudent: student];


2.9、给class表添加课程

-(void)addClass:(StudentClassModel*)clas toStudent:(StudentFMDBModel*)student{

[fmdb open];

//scId integer, cName text

NSString*SQL = [NSStringstringWithFormat:@"insert into class (scId, cName) values (%ld,?)", student.sId];

BOOL isSuccess = [fmdb executeUpdate:SQL, clas.cName];

if(!isSuccess) {

NSLog(@"classTable插入信息失败--%@",fmdb.lastErrorMessage);

}

[fmdb close];

}


//调用

[[DataForFMDB sharedDataBase] addClass: class toStudent: student];


2.10、给class表删除课程

-(void)deleteClass:(StudentClassModel*)clas toStudent:(StudentFMDBModel*)student{

[fmdb open];

NSString *SQL = [NSString stringWithFormat:@"delete from class where scId = %ld and cName = ?", student.sId];

BOOL isSuccess = [fmdb executeUpdate:SQL,clas.cName];

if(!isSuccess) {

NSLog(@"classTable删除某一信息失败--%@",fmdb.lastErrorMessage);

}

[fmdb close];

}


//调用

[[DataForFMDB sharedDataBase] deleteClass: self.dataArray[indexPath.row] toStudent: student];


2.11、删除student下某一的全部class

-(void)deleteAllCarsFromStudent:(StudentFMDBModel*)student{

[fmdb open];

NSString *SQL = [NSString stringWithFormat:@"delete from class where scId = %ld", student.sId];

BOOL isSuccess = [fmdb executeUpdate:SQL];

if(!isSuccess) {

NSLog(@"student下某一的全部class删除失败--%@",fmdb.lastErrorMessage);

}

[fmdb close];

}


//调用

[[DataForFMDB sharedDataBase] deleteAllClassFromStudent: student];


2.12、//删除class表

-(void)deleteAllClass{

NSString *SQL =@"delete from class";

BOOL isSuccess = [fmdb executeUpdate:SQL];

if(!isSuccess) {

NSLog(@"classt全部删除失败--%@",fmdb.lastErrorMessage);

}

}


2.13、由名字查找学生student信息

查找操作界面

-(NSMutableArray*)seachAllInfoWith:(NSString*)str{

[fmdb open];

NSMutableArray*array = [NSMutableArray new];

//通过名字查询学生信息

NSString *SQL = [NSString stringWithFormat:@"select * from student where sName = '%@' ", str]; // '%@' 可以查询中文

FMResultSet *result = [fmdb executeQuery:SQL];

while([result next]) {

StudentFMDBModel *student = [[StudentFMDBModel alloc] init];

student.sId= [result intForColumn:@"sId"];

student.sName= [result stringForColumn:@"sName"];

[array addObject:student];

}

[fmdb close];

return array;

}


//调用

self.dataArray= [[DataForFMDB sharedDataBase] seachAllInfoWith: textField.text];


2.14、全部信息

全部信息界面

数据代码:

@property(nonatomic,strong)NSMutableArray*studentArray;//student数据源数组

@property(nonatomic,strong)NSMutableArray*allInfoArray;//student对应class数据源数组

self.studentArray = [[DataForFMDB sharedDataBase] getAllStudent];

for(inti =0; i<self.studentArray.count; i++){

StudentFMDBModel *student =  self.studentArray[i];

NSMutableArray *array = [[DataForFMDB sharedDataBase] getAllClassFromStudent:student];

[self.allInfoArray addObject:array];

}


知识点总结

1、数据库插入命令SQL  insert into

//1.executeUpdate:不确定的参数用?来占位(后面参数必须是oc对象,“;”代表语句结束)

[fmdb executeUpdate:@“insert into student(sId,sName,sAge) values(?,?,?);” ,@(student.sId), student.sName, @(student.sAge)];  //int / integer 类型的要加 “@(xxx)”转成NSNumber类型的

//2.executeUpdateWithForamat:不确定的参数用%@,%d等来占位 (参数为原始数据类型,执行语句不区分大小写

 [fmdb executeUpdateWithForamat:@“insert intot student (sId,sName,sAge)values(%ld,%@,%ld);”,student.sId, student.sName, student.sAge];    

//3.参数是数组的使用方式 

[fmdb executeUpdate:@“insert into student (sId,sName,sAge) values(?,?,?);” withArgumentsInArray:@[@(student.sId), student.sName, @(student.sAge)]];

2、数据库删除命令SQL  delete

//1.不确定的参数用?来占位 (后面参数必须是oc对象,需要将int包装成OC对象)

[fmdb executeUpdate:@“delete from student where sId = ?;”,@(student.sId)];

//2.不确定的参数用%@,%d等来占位

[fmdb executeUpdateWithFormat:@“delete from student where name = %@;”,student.sName];

3、数据库修改命令SQL  update

//修改学生的名字 

[fmdb executeUpdate:@“update student set sName = ? where sId = ?”,student.sName,@(student.sId)];

4、数据库查询命令SQL  select ... from

select命令就是查询,执行查询的方法是以-excuteQuery开头的。执行查询时,如果成功返回FMResultSet对象,错误返回nil。与执行更新相当,支持使用NSError参数。同时,你也可以使用-lastErrorCode和-lastErrorMessage获知错误信息。

FMResultSet获取不同数据格式的方法:

intForColumn:

longForColumn:

longLongIntForColumn:

boolForColumn:

doubleForColumn:

stringForColumn:

dataForColumn:

dataNoCopyForColumn:

UTF8StringForColumnIndex:

objectForColumn:

5、数据库销毁命令SQL drop ...

//如果表格存在 则销毁

 [fmdb executeUpadate:@“drop table if existst student;”];

6、使用FMDatabaseQueue类实现多线程操作

在多个线程中同时使用一个FMDatabase实例是不明智的。现在你可以为每 个线程创建一个FMDatabase对象,不要让多个线程分享同一个实例,他无法在多个线程中同事使用。否则程序会时不时崩溃或者报告异常。所以,不要初始化FMDatabase对象,然后在多个线程中使用。这时候,我们就需要使 用FMDatabaseQueue来创建队列执行事务。

//1.创建队列

FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath]; 

__block BOOL whoopsSomethingWrongHappened =true;

//2.把任务包装到事务里

[queue inTransaction:^(FMDatabase *db, BOOL *rollback)    {  whoopsSomethingWrongHappened &=  [db executeUpdate:@“insert into myTable values (?)”,    [NSNumber numberWith:1]];

whoopsSomethingWrongHappened &= [db executeUpdata:@“insert into myTable values (?)”, [NSNumber numberWithInt:2]];

whoopsSomethingWrongHappened &= [db executeUpdata:@“insert into myTable values(?)”[NSNumber  numberWithInt:3]];

//如果有错误 返回

if(!whoopsSomethingWrongHappened)  {   

 *rollback = YES;

return;

 }

}];


——————————————————

有什么问题欢迎大家提问哟,O(∩_∩)O~~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,099评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,473评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,229评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,570评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,427评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,335评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,737评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,392评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,693评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,730评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,512评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,349评论 3 314
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,750评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,017评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,290评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,706评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,904评论 2 335

推荐阅读更多精彩内容