iOS FMDB庫詳解

更新時間: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對象就代表一個單獨的SQLite數(shù)據(jù)庫(注意并不是表),用來執(zhí)行SQL語句
  • FMResultSet:使用FMDatabase執(zhí)行查詢后的結(jié)果集
  • FMDatabaseQueue:用于在多線程中執(zhí)行多個查詢或更新,它是線程安全的

FMDB的使用步驟詳解

1.準(zhǔn)備步驟(基礎(chǔ)操作)

1.項目中導(dǎo)入FMDB Github地址

2.導(dǎo)入libsqlite3框架(一般情況下默認(rèn)是導(dǎo)入的,所以一般都不用做這一步),細(xì)心的朋友可能會發(fā)現(xiàn)我們的庫中還有一個libsqlite3.0框架,那么它們倆有什么區(qū)別呢

libsqlite3的導(dǎo)入步驟.png

3.在需要用到FMDB的控制器(或模型)地方import FMDatabase.h

FMDB的導(dǎo)入.png

4.新建一個繼承自NSObject的對象,這里我們使用student,接下來數(shù)據(jù)庫中增刪改查的對象就用stduent進(jìn)行操作示例

student對象.png

5.你已經(jīng)躍躍欲試了吧,別急,本地的.sqlite你現(xiàn)在還無法查看,這里非常推薦火狐瀏覽器中的插件 SQLite Manager 現(xiàn)在推薦App Store里面自帶的Datum Free(免費版)了,使用起來幾乎和火狐插件一毛一樣。

Mac官方的應(yīng)用商店App Store中的Datum free

(現(xiàn)在已經(jīng)不支持了)火狐瀏覽器插件.png

這里教大家一個快速打開sqlite文件的小技巧,在Finder中將.sqlite文件直接拖動到SQLite Manager的打開文件夾中,可以自動尋址快速打開


SQLite Manager界面.png
Finder中的.sqlite文件.png
sqlite文件打開后的樣子.png

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)建了


student.sqlite

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)建

t_student表

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ù)

添加的數(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)被修改了

王子涵2姓名修改為了李浩宇

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ù)

執(zhí)行查詢數(shù)據(jù)后控制臺的打印結(jié)果

8.表的刪除

//如果表格存在 則銷毀
BOOL result = [_db executeUpdate:@"drop table if exists t_student"];
if (result) {
  NSLog(@"刪除表成功");
} else {
  NSLog(@"刪除表失敗");
}

執(zhí)行之后,刷新SQLite,可以看到t_student表已經(jīng)被刪除了

刷新SQLite
t_student表被刪除

總結(jié)

以上就是基本的使用方法,希望新手也可以看明白。此篇文章會不斷更新完善,爭取做到FMDB最最詳細(xì)的介紹,我不嫌啰嗦,希望大家也不要嫌啰嗦(畢竟聞道有先后,很多時候你寫得太簡單明了籠統(tǒng)了,新手們就比較難理解)。對應(yīng)的項目也上傳到Github了,大家可以下載下來查看,傳送門:點我

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,333評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,491評論 3 416
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,263評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,946評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,708評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,409評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,939評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,774評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,976評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,641評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,872評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,650評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,958評論 2 373

推薦閱讀更多精彩內(nèi)容