写在前面的话:之前的那版因为排版不好看重新整理了这份,所以这份跟之前的一样啦~~~
————————————————
FMDB
1、简述:
1.1、FMDB是iOS平台的SQLite数据库框架,是对libsqlite3框架的封装
2.2、FMDB以OC的方式封装了SQLite的C语言API
2、FMDB的优点:
2.1、使用起来更加面向对象,省去了很多麻烦、冗余的C语言代码
2.2、对比苹果自带的Core Data框架,更加轻量级和灵活
2.3、提供了多线程安全的数据库操作方法,有效地防止数据混乱
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使用步骤相似,创建数据库路径,获得数据库路径,打开数据库,然后对数据库进行增、删、改、查操作,最后关闭数据库。
实例Demo
本例是一个学生的数据库表格student,每个学生都自己所选的课程class,具体信息如下图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 = [fmdb executeUpdate: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([resultnext]) {
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);
}
[fmdbclose];
}
//调用
[[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 = [NSString stringWithFormat:@"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([resultnext]) {
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.1、executeUpdate:不确定的参数用?来占位(后面参数必须是oc对象,“;”代表语句结束)
[fmdb executeUpdate:@"insert into student(sId,sName,sAge) values(?,?,?);" ,@(student.sId), student.sName, @(student.sAge)];
//int/integer 类型的要加 “@(xxx)”转成NSNumber类型的
1.2、executeUpdateWithForamat:不确定的参数用%@,%d等来占位 (参数为原始数据类型,执行语句不区分大小写
[fmdb executeUpdateWithForamat:@"insert intot student (sId,sName,sAge)values(%ld,%@,%ld);",student.sId, student.sName, student.sAge];
1.3、参数是数组的使用方式
[fmdb executeUpdate:@"insert into student (sId,sName,sAge) values(?,?,?);" withArgumentsInArray:@[@(student.sId), student.sName, @(student.sAge)]];
2、数据库删除命令SQL delete
2.1、不确定的参数用?来占位 (后面参数必须是oc对象,需要将int包装成OC对象)
[fmdb executeUpdate:@"delete from student where sId = ?;", @(student.sId)];
2.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~~