寫在前面的話:之前的那版因為排版不好看重新整理了這份,所以這份跟之前的一樣啦~~~
————————————————
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~~