FMDB使用

框架地址:[https://github.com/ccgus/fmdb]

  • 下載框架


    Snip20160912_6.png
  • 首先要明白框架中幾個重要的類

    • FMDatabase 代表一個數(shù)據(jù)庫 并且可以使用它執(zhí)行sqlite語句
    • FMDatabaseQueue 是線程安全的存儲跟讀取數(shù)據(jù) 這里有一個概念---事物
    • FMResultSet 結(jié)果集 從數(shù)據(jù)庫中讀取數(shù)據(jù)的集合
  • 使用之前會發(fā)現(xiàn)編譯報錯,需要先在Build Phases->Link Binary With Libraries->導(dǎo)入libsqlite3.tbd 再次編譯就??

FMDatabase

  • 首先我們我們不考慮線程安全下使用FMDatabase來創(chuàng)建數(shù)據(jù)庫實現(xiàn)離線緩存
    • 導(dǎo)入#import "FMDB.h"
// 1.獲得數(shù)據(jù)庫路徑
     NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"daba.sqlist"];
    // 2.創(chuàng)建數(shù)據(jù)對象
    FMDatabase *dataBase = [FMDatabase databaseWithPath:path];
    
    // 3.打開數(shù)據(jù)庫的時候首先判斷當(dāng)前數(shù)據(jù)庫是否存在, 如果不存儲在就創(chuàng)建一個并打開, 如果存儲在那么就不創(chuàng)建直接打開
    BOOL isSuccess = [dataBase open];
    if (!isSuccess) {
        NSLog(@"打開數(shù)據(jù)庫失敗");
    }else{
        NSLog(@"打開數(shù)據(jù)庫成功");
    
    }
}
  • 創(chuàng)建好數(shù)據(jù)庫之后,接下來就是根據(jù)我們的需求在數(shù)據(jù)庫中中創(chuàng)建表了,一個數(shù)據(jù)庫可以創(chuàng)建多張表, 一張表包含多個字段,也就是對應(yīng)表的column, 表是有row跟column構(gòu)成, 有點類似Excle表

  • 細節(jié)不多說 創(chuàng)建一個完整的字段表

// 數(shù)據(jù)庫前提是open狀態(tài)
    /**
     * PRIMARY KEY 主鍵
     * AUTOINCREMENT 自動增量
     * UNIQUE 唯一
     * DEFAULT 默認值
     *  @param INTEGER 整型
     *  @param TEXT    文本
     *  @param REAL    浮點型
     *  @param
     *  @param BLOB    二進制
     */
    BOOL isSuccess = [dataBase executeUpdate:@"CREATE TABLE IF NOT EXIST t_table (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE, age INTEGER  NOT NULL UNIQUE DEFAULT 0, score REAL NOT NULL unique, data BLOB);"];
    
    if (!isSuccess) {
        NSLog(@"創(chuàng)建表成功");
    }else{
        NSLog(@"創(chuàng)建表失敗");
        
    }
  • 表創(chuàng)建完成了,接下來就是我們利用FMDatabase對象要插入數(shù)據(jù)了, 這里我們了解一下插入數(shù)據(jù)的常見3中寫法
    /**此種方式后面拼接的參數(shù)必須為對象 不可以為int double等基本數(shù)據(jù)類型*/
    [dataBase executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
    /**此種方式后面拼接的參數(shù)可以為int double等基本數(shù)據(jù)類型 因為是使用的占位符*/
    [dataBase executeUpdateWithFormat:@"insert into t_table(name, age, score, data) values(%@, %d , %f, %@)", @"jake", 12, 91.0, [NSData data]];
    /**此種方式后面拼接的參數(shù)必須為對象 不可以為int double等基本數(shù)據(jù)類型 將對象依次防近視數(shù)組*/
    [dataBase executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)" withArgumentsInArray:@[@12, @91.0, [NSData data]]];

-注意 當(dāng)我們存儲表中BLOB 對應(yīng)的字段如果為字典的時候,這個時候我們不應(yīng)該把字典往里存,應(yīng)當(dāng)使用[NSKeyedArchiver archivedDataWithRootObject:<#(nonnull id)#>] 將字典轉(zhuǎn)換成NSData類型, 這樣當(dāng)我們?nèi)〕鰯?shù)據(jù)的時候取出的是NSData類型,再將NSData類型數(shù)據(jù)通過[NSKeyedUnarchiver unarchiveObjectWithData:<#(nonnull NSData *)#>];反歸檔得到就是字典,如果直接存字典,從數(shù)據(jù)數(shù)據(jù)庫中取出的是字符串, 字典裝模型時候會報錯

  • 下面再說一下查表, 更行表 刪除表數(shù)據(jù)就不說了,跟插入數(shù)據(jù)一樣 自己研究
  • 書寫格式幾乎相同 就是返回結(jié)果是FMResultSet類型(結(jié)果集), 這時候根據(jù)遍歷結(jié)果集取出每一條數(shù)據(jù)
    /**此種方式后面拼接的參數(shù)必須為對象 不可以為int double等基本數(shù)據(jù)類型*/
    [dataBase executeQuery:@"select *From t_table;"];
    /**此種方式后面拼接的參數(shù)可以為int double等基本數(shù)據(jù)類型 因為是使用的占位符*/
    [dataBase executeQueryWithFormat:@"SELECT name, age, score from t_table where name = %@", @"jake"];
    /**此種方式后面拼接的參數(shù)必須為對象 不可以為int double等基本數(shù)據(jù)類型 將對象依次防近視數(shù)組*/
    [dataBase executeQuery:@"select *from t_table where age > ?" withArgumentsInArray:@[@12]];
  • 拿查整個表的全部數(shù)據(jù)為例
 FMResultSet * resultSet = [dataBase executeQuery:@"select *From t_table;"];
    while ([resultSet next]) {
        // 通過字段獲取 文本數(shù)據(jù)
        [resultSet stringForColumn:@"name"];
        // 也可以通過Column來獲取
        [resultSet stringForColumnIndex:2];
        
        // 通過字段獲取 對象數(shù)據(jù)
        [resultSet objectForColumnName:@"dict"];
        
    }
  • 關(guān)于FMResultSet使用結(jié)合如下
/* 獲取下一個記錄 */
       - (BOOL)next;
       /* 獲取記錄有多少列 */
       - (int)columnCount;
       /* 通過列名得到列序號,通過列序號得到列名 */
       - (int)columnIndexForName:(NSString *)columnName;
       - (NSString *)columnNameForIndex:(int)columnIdx;
       /* 獲取存儲的整形值 */
       - (int)intForColumn:(NSString *)columnName;
       - (int)intForColumnIndex:(int)columnIdx;
       /* 獲取存儲的長整形值 */
       - (long)longForColumn:(NSString *)columnName;
       - (long)longForColumnIndex:(int)columnIdx;
       /* 獲取存儲的布爾值 */
       - (BOOL)boolForColumn:(NSString *)columnName;
       - (BOOL)boolForColumnIndex:(int)columnIdx;
       /* 獲取存儲的浮點值 */
       - (double)doubleForColumn:(NSString *)columnName;
       - (double)doubleForColumnIndex:(int)columnIdx;
       /* 獲取存儲的字符串 */
       - (NSString *)stringForColumn:(NSString *)columnName;
       - (NSString *)stringForColumnIndex:(int)columnIdx;
       /* 獲取存儲的日期數(shù)據(jù) */
       - (NSDate *)dateForColumn:(NSString *)columnName;
       - (NSDate *)dateForColumnIndex:(int)columnIdx;
       /* 獲取存儲的二進制數(shù)據(jù) */
       - (NSData *)dataForColumn:(NSString *)columnName;
       - (NSData *)dataForColumnIndex:(int)columnIdx;
       /* 獲取存儲的UTF8格式的C語言字符串 */
       - (const unsigned cahr *)UTF8StringForColumnName:(NSString *)columnName;
       - (const unsigned cahr *)UTF8StringForColumnIndex:(int)columnIdx;
       /* 獲取存儲的對象,只能是NSNumber脆粥、NSString译荞、NSData本砰、NSNull */
       - (id)objectForColumnName:(NSString *)columnName;
       - (id)objectForColumnIndex:(int)columnIdx;

FMDatabaseQueue

  • 如果項目中開啟多個線程同時訪問一個數(shù)據(jù)庫的時候,需要考慮到線程安全的問題了,那么就要使用這個類來對數(shù)據(jù)庫操作了, 那么我們還要理解一個概念 事物 常說開啟事物 提交事物 回滾事物 是什么意思呢? 為什么需要開啟事物呢

  • 說個情形就明白了,加入我們像一個數(shù)據(jù)庫表中插入一百條數(shù)據(jù), 我們可能會執(zhí)行一百條SQLite語句,如果當(dāng)我們執(zhí)行到一半的時候出錯了,那么我們需要回滾, 讓之前執(zhí)行的的數(shù)據(jù)恢復(fù)之前數(shù)據(jù),也就是一句話,我們需要所有的語句都執(zhí)行成功才生效,那么我們就需要開啟事物,當(dāng)確定所有的語句都執(zhí)行成功就提交事物, 如果中途出錯,那么就回滾事物

  • 首先我們不開啟事物,就線程安全來使用FMDB

// 1.獲得數(shù)據(jù)庫路徑
    NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"daba.sqlist"];
    
    // 創(chuàng)建FMDatabaseQueue 同時會創(chuàng)建數(shù)據(jù)庫 如果數(shù)據(jù)庫不存在
    FMDatabaseQueue *baseQueue = [FMDatabaseQueue databaseQueueWithPath:path];
  • 當(dāng)我們對數(shù)據(jù)庫進行CRUDde的時候調(diào)用- (void)inDatabase:(void (^)(FMDatabase *db))block, 在block回調(diào)給我的FMDatabase對象進行操作 ,操作跟上面一樣的 例如
[baseQueue inDatabase:^(FMDatabase *db) {
        // 打開數(shù)據(jù)庫 創(chuàng)建表
        BOOL isSuccess = [db open];
        if (!isSuccess) {
            NSLog(@"打開數(shù)據(jù)庫失敗");
        }else{
            NSLog(@"打開數(shù)據(jù)庫成功");
            
            // 插入數(shù)據(jù)
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        }
        
    }];
  • 使用一下開啟事物, 加入我們插入同時插入十條數(shù)據(jù)
// 1.獲得數(shù)據(jù)庫路徑
    NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"daba.sqlist"];
    
    // 創(chuàng)建FMDatabaseQueue 同時會創(chuàng)建數(shù)據(jù)庫 如果數(shù)據(jù)庫不存在
    FMDatabaseQueue *baseQueue = [FMDatabaseQueue databaseQueueWithPath:path];
    
    [baseQueue inDatabase:^(FMDatabase *db) {
        // 打開數(shù)據(jù)庫 創(chuàng)建表
        BOOL isSuccess = [db open];
        if (!isSuccess) {
            NSLog(@"打開數(shù)據(jù)庫失敗");
        }else{
            NSLog(@"打開數(shù)據(jù)庫成功");
            
            // 開啟事物
            [db beginTransaction];
            
            // 插入數(shù)據(jù)
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            // 也可以在中途回滾 就是該次對數(shù)據(jù)庫的操作不生效 通常中途一般不回滾
            [db rollback];
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            
            // 提交事物
            [db commit];
            
        }
        
    }];
  • 其實FMDB內(nèi)部已經(jīng)幫我們封裝好,只需要調(diào)用FMDatabaseQueue對象方法 - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block
[baseQueue inTransaction:^(FMDatabase *db, BOOL *rollback) {

        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        // 如果中途想回滾 就這樣操作
        *rollback = YES;
        [db rollback];
        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
    }];
  • 下班了,不寫了,大家如果發(fā)現(xiàn)有誤,謝謝反饋給我????
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末刨晴,一起剝皮案震驚了整個濱河市薇芝,隨后出現(xiàn)的幾起案子霹琼,更是在濱河造成了極大的恐慌务傲,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件枣申,死亡現(xiàn)場離奇詭異售葡,居然都是意外死亡,警方通過查閱死者的電腦和手機忠藤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進店門挟伙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人模孩,你說我怎么就攤上這事尖阔。” “怎么了瓜贾?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵诺祸,是天一觀的道長。 經(jīng)常有香客問我祭芦,道長筷笨,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任龟劲,我火速辦了婚禮胃夏,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘昌跌。我一直安慰自己仰禀,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布蚕愤。 她就那樣靜靜地躺著答恶,像睡著了一般饺蚊。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上悬嗓,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天污呼,我揣著相機與錄音,去河邊找鬼包竹。 笑死燕酷,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的周瞎。 我是一名探鬼主播苗缩,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼声诸!你這毒婦竟也來了酱讶?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤彼乌,失蹤者是張志新(化名)和其女友劉穎浴麻,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體囤攀,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年宫纬,在試婚紗的時候發(fā)現(xiàn)自己被綠了焚挠。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡漓骚,死狀恐怖蝌衔,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蝌蹂,我是刑警寧澤噩斟,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站孤个,受9級特大地震影響剃允,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜齐鲤,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一斥废、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧给郊,春花似錦牡肉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽毛俏。三九已至,卻和暖如春饲窿,著一層夾襖步出監(jiān)牢的瞬間煌寇,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工免绿, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留唧席,地道東北人。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓嘲驾,卻偏偏與公主長得像淌哟,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子辽故,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,440評論 2 348

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