更新時間:2018-11-22 新增了插入/修改數(shù)據(jù)的注意事項(空值問題)
更新時間:2018-11-06 新增了修改(更新)數(shù)據(jù)時的多字段修改
更新時間:2018-07-13 修改了推薦的SQLite可視化工具
更新時間:2017-04-17 修改了代碼的排版
前言(嘮叨)
在網(wǎng)上搜FMDB的資料勤揩,要么是很精簡的介紹(針對比較有經(jīng)驗的開發(fā)者,新手無從下手),要么是排版亂七八糟、代碼有不少錯誤的(直接拷貝過去使用不了,新手還是很難玩轉(zhuǎn))高氮。FMDB作為這么棒的第三方庫,竟然沒有一篇文章是專門系統(tǒng)的、詳細(xì)的介紹它的屡江,簡直不能忍。鄙人尋思著給大家寫一篇赛不,于是就有了這篇“FMDB庫詳解”惩嘉,有錯誤或者不對的地方請大家及時的指正,鄙人將第一時間火速修改踢故,力爭做到文章的代碼拷貝就能用文黎,插上就能用(方便新手和大家的開發(fā)),另外文章中的代碼也力爭做到簡潔高效通俗大師化殿较。本文將持續(xù)更新
什么是FMDB
很簡單耸峭,一個iOS中SQLite API的封裝庫。
其他的巴拉巴拉一大堆總結(jié)下來就是:
1.是對libsqlite3庫的封裝淋纲,使用起來簡潔劳闹、高效,沒有原來的一大堆晦澀難懂、影響開發(fā)效率的C語句本涕,更加面向?qū)ο?br>
2.非常的輕量化业汰、靈活
3.對于多線程的并發(fā)操作進(jìn)行了處理,是線程安全的(重要特性之一)
4.因為它是OC語言封裝的菩颖,只能在ios開發(fā)的時候使用样漆,所以在實現(xiàn)跨平臺操作的時候存在局限性
FMDB重要(常用)類
- FMDatabase:一個FMDatabase對象就代表一個單獨(dú)的SQLite數(shù)據(jù)庫(注意并不是表),用來執(zhí)行SQL語句
- FMResultSet:使用FMDatabase執(zhí)行查詢后的結(jié)果集
- FMDatabaseQueue:用于在多線程中執(zhí)行多個查詢或更新,它是線程安全的
FMDB的使用步驟詳解
1.準(zhǔn)備步驟(基礎(chǔ)操作)
1.項目中導(dǎo)入FMDB Github地址
- Cocoapods導(dǎo)入(推薦)位他,什么你還沒有使用Cocoapods氛濒,那么就太out了,為了不被社會所淘汰鹅髓,趕緊學(xué)起來吧 唐巧-用CocoaPods做iOS程序的依賴管理 / CocoaPods使用詳解
- 手動下載工程舞竿,并導(dǎo)入
2.導(dǎo)入libsqlite3框架(一般情況下默認(rèn)是導(dǎo)入的,所以一般都不用做這一步),細(xì)心的朋友可能會發(fā)現(xiàn)我們的庫中還有一個libsqlite3.0框架窿冯,那么它們倆有什么區(qū)別呢
3.在需要用到FMDB的控制器(或模型)地方import FMDatabase.h
4.新建一個繼承自NSObject的對象骗奖,這里我們使用student,接下來數(shù)據(jù)庫中增刪改查的對象就用stduent進(jìn)行操作示例
5.你已經(jīng)躍躍欲試了吧醒串,別急执桌,本地的.sqlite你現(xiàn)在還無法查看,這里非常推薦火狐瀏覽器中的插件 SQLite Manager 現(xiàn)在推薦App Store里面自帶的Datum Free(免費(fèi)版)了芜赌,使用起來幾乎和火狐插件一毛一樣仰挣。
這里教大家一個快速打開sqlite文件的小技巧,在Finder中將.sqlite文件直接拖動到SQLite Manager的打開文件夾中缠沈,可以自動尋址快速打開
2.數(shù)據(jù)庫的創(chuàng)建
//1.獲取數(shù)據(jù)庫文件的路徑
_docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSLog(@"%@",_docPath);
mark_student = 1;
//設(shè)置數(shù)據(jù)庫名稱
NSString *fileName = [_docPath stringByAppendingPathComponent:@"student.sqlite"];
//2.獲取數(shù)據(jù)庫
_db = [FMDatabase databaseWithPath:fileName];
if ([_db open]) {
NSLog(@"打開數(shù)據(jù)庫成功");
} else {
NSLog(@"打開數(shù)據(jù)庫失敗");
}
這里我們可以打開_docPath的路徑膘壶,可以看到名為“student.sqlite”的數(shù)據(jù)庫已經(jīng)創(chuàng)建了
3.表的創(chuàng)建
//3.創(chuàng)建表
BOOL result = [_db executeUpdate:@"CREATE TABLE IF NOT EXISTS t_student (id integer PRIMARY KEY AUTOINCREMENT, name text NOT NULL, age integer NOT NULL, sex text NOT NULL);"];
if (result) {
NSLog(@"創(chuàng)建表成功");
} else {
NSLog(@"創(chuàng)建表失敗");
}
使用火狐瀏覽器的SQLite Manager插件打開student.sqlite可以看到t_student表已經(jīng)被創(chuàng)建
4.添加數(shù)據(jù)
//插入數(shù)據(jù)
NSString *name = [NSString stringWithFormat:@"王子涵%@",@(mark_student)];
int age = mark_student;
NSString *sex = @"男";
mark_student ++;
//1.executeUpdate:不確定的參數(shù)用?來占位(后面參數(shù)必須是oc對象洲愤,颓芭;代表語句結(jié)束)
BOOL result = [_db executeUpdate:@"INSERT INTO t_student (name, age, sex) VALUES (?,?,?)",name,@(age),sex];
//2.executeUpdateWithForamat:不確定的參數(shù)用%@,%d等來占位 (參數(shù)為原始數(shù)據(jù)類型柬赐,執(zhí)行語句不區(qū)分大小寫)
// BOOL result = [_db executeUpdateWithFormat:@"insert into t_student (name,age, sex) values (%@,%i,%@)",name,age,sex];
//3.參數(shù)是數(shù)組的使用方式
// BOOL result = [_db executeUpdate:@"INSERT INTO t_student(name,age,sex) VALUES (?,?,?);" withArgumentsInArray:@[name,@(age),sex]];
if (result) {
NSLog(@"插入成功");
} else {
NSLog(@"插入失敗");
}
多插入幾次后亡问,我們可以看到t_student表中添加了多條數(shù)據(jù)
PS:如果你需要插入空數(shù)據(jù),比如插入一個student對象肛宋,name為小明州藕,age為16,但是sex暫時不知道酝陈,那么你可以先不加sex床玻,這樣(要注意,對象與 后添?號一定要對應(yīng),不然會報錯的)
[_db executeUpdate:@"INSERT INTO t_student (name, age) VALUES (?,?)",name,@(age)];
同時,也可以在sex中插入一個空值遇西,但是這里的空值不是nil馅精,而是NSNull
[_db executeUpdate:@"INSERT INTO t_student (name, age, sex) VALUES (?,?,?)",name,@(age),[NSNull null]];
5.刪除數(shù)據(jù)
//1.不確定的參數(shù)用?來占位 (后面參數(shù)必須是oc對象,需要將int包裝成OC對象)
int idNum = 11;
BOOL result = [_db executeUpdate:@"delete from t_student where id = ?",@(idNum)];
//2.不確定的參數(shù)用%@粱檀,%d等來占位
//BOOL result = [_db executeUpdateWithFormat:@"delete from t_student where name = %@",@"王子涵"];
if (result) {
NSLog(@"刪除成功");
} else {
NSLog(@"刪除失敗");
}
6.修改數(shù)據(jù)
//修改學(xué)生的名字
NSString *newName = @"李浩宇";
NSString *oldName = @"王子涵2";
BOOL result = [_db executeUpdate:@"update t_student set name = ? where name = ?",newName,oldName];
if (result) {
NSLog(@"修改成功");
} else {
NSLog(@"修改失敗");
}
查看sqlite洲敢,可以看到王子涵2的姓名已經(jīng)被修改了
PS.上面的sql語句是只修改了對象的一個字段,如果我們需要更新對象的多個乃至全部字段呢茄蚯?這種情況下压彭,我們需要先寫一個格式為NSString的sql語句,將我們需要更新的字段名都寫入其中渗常,然后再調(diào)用另一個executeUpdate方法進(jìn)行更新壮不。代碼如下:
NSString *sql = [NSString stringWithFormat:@"update t_student set name = ?, age = ?, sex = ? where id = ?"];
[_db executeUpdate:sql withArgumentsInArray:@[newName, @(newAge),newSex, @(id)]];
7.查詢數(shù)據(jù)
//查詢整個表
FMResultSet * resultSet = [_db executeQuery:@"select * from t_student"];
//根據(jù)條件查詢
//FMResultSet * resultSet = [_db executeQuery:@"select * from t_student where id < ?", @(4)];
//遍歷結(jié)果集合
while ([resultSet next]) {
int idNum = [resultSet intForColumn:@"id"];
NSString *name = [resultSet objectForColumnName:@"name"];
int age = [resultSet intForColumn:@"age"];
NSString *sex = [resultSet objectForColumnName:@"sex"];
NSLog(@"學(xué)號:%@ 姓名:%@ 年齡:%@ 性別:%@",@(idNum),name,@(age),sex);
}
PS:在對FMDB數(shù)據(jù)庫對象的屬性值判斷是否為空時,不能用 nil 來判斷皱碘,而應(yīng)該用null來判斷询一,正確的寫法為
[[resultSet objectForColumnName:@"name"] isKindOfClass:[NSNull Class]];
執(zhí)行查詢之后控制臺的打印,可以看到打印出了目前的所有數(shù)據(jù)
8.表的刪除
//如果表格存在 則銷毀
BOOL result = [_db executeUpdate:@"drop table if exists t_student"];
if (result) {
NSLog(@"刪除表成功");
} else {
NSLog(@"刪除表失敗");
}
執(zhí)行之后癌椿,刷新SQLite健蕊,可以看到t_student表已經(jīng)被刪除了
總結(jié)
以上就是基本的使用方法,希望新手也可以看明白踢俄。此篇文章會不斷更新完善缩功,爭取做到FMDB最最詳細(xì)的介紹,我不嫌啰嗦都办,希望大家也不要嫌啰嗦(畢竟聞道有先后嫡锌,很多時候你寫得太簡單明了籠統(tǒng)了,新手們就比較難理解)脆丁。對應(yīng)的項目也上傳到Github了世舰,大家可以下載下來查看,傳送門:點我