iOS開發資料庫-FMDB

來源:互聯網
上載者:User

標籤:

 前言

FMDB是以OC的方式封裝了SQLite的C語言API,使用起來更加物件導向,省去了很多麻煩、冗餘的C語言代碼;對比蘋果內建的Core Data架構,更加輕量級和靈活;提供了多安全執行緒的資料庫操作方法,有效地防止資料混亂;FMDB同時相容ARC和非ARC工程,在編譯的時候會自動根據工程配置來調整相關的記憶體管理代碼。

使用方法

FMDB有三個主要的類

  • FMDatabase 表示一個單獨的SQLite資料庫。 用來執行SQLite的命令。
  • FMResultSet 表示FMDatabase執行查詢後的結果集
  • FMDatabaseQueue 如果你想在多線程中執行多個查詢或更新,你應該使用該類。這是安全執行緒的。
資料庫建立

通過指定SQLite資料庫檔案路徑來建立FMDatabase對象

FMDatabase *db = [FMDatabase databaseWithPath:path];if (![db open]) {  NSLog(@"資料庫開啟失敗!");}

 

建立FMDatabase對象時參數為SQLite資料庫檔案路徑。該路徑可以是以下三種之一:

1、具體檔案路徑

  • 該檔案路徑無需真實存,如果不存在會自動建立。

2、Null 字元串@""

  • 表示會在臨時目錄建立一個空的資料庫,當FMDatabase 連結關閉時,資料庫檔案也被刪除。

3、NULL

  • 會建立一個記憶體中臨時資料庫,當FMDatabase串連關閉時,資料庫會被銷毀
開啟資料庫

在和資料庫互動 之前,資料庫必須是開啟的。如果資源或許可權不足無法開啟或建立資料庫,都會導致開啟失敗,返回BOOL類型

if (![db open]) {            [db release];           return;     }

 

執行更新
  • 一切不是SELECT命令的命令都視為更新。這包括 CREATE, UPDATE, INSERT,ALTER,COMMIT, BEGIN, DETACH, DELETE, DROP, END, EXPLAIN, VACUUM, and REPLACE (等)。
    簡單來說,只要不是以SELECT開頭的命令都是UPDATE命令。
  • 執行更新返回一個BOOL值。YES表示執行成功,否則表示有那些錯誤 。你可以調用 -lastErrorMessage 和 -lastErrorCode方法來得到更多資訊。

使用executeUpdate:方法執行更新

- (BOOL)executeUpdate:(NSString*)sql, ...- (BOOL)executeUpdateWithFormat:(NSString*)format, ...- (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments

 

樣本

[db executeUpdate:@"UPDATE t_student SET age = ? WHERE name = ?;", @20, @"Jack"]
執行查詢

SELECT命令就是查詢,執行查詢的方法是以 -excuteQuery開頭的。

查詢方法

- (FMResultSet *)executeQuery:(NSString*)sql, ...- (FMResultSet *)executeQueryWithFormat:(NSString*)format, ...- (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments

 

執行查詢時,如果成功返回FMResultSet對象, 錯誤返回nil. 與執行更新相當,支援使用 NSError**參數。同時,你也可以使用 -lastErrorCode和-lastErrorMessage獲知錯誤資訊。

為了遍曆查詢結果,你可以使用while迴圈。你還需要知道怎麼跳到下一個記錄。使用FMDB,很簡單實現,就像這樣:

FMResultSet *s = [db executeQuery:@"SELECT * FROM myTable"];   while ([s next]) {       //retrieve values for each record   }

你必須一直調用 -[FMResultSet next] 在你訪問查詢傳回值之前,甚至你只想要一個記錄:
FMResultSet *s = [db executeQuery:@"SELECT COUNT(*) FROM myTable"];   if ([s next]) {        int totalCount = [s intForColumnIndex:0];   }

 

FMResultSet 提供了很多方法來獲得所需的格式的值:

intForColumn:longForColumn:longLongIntForColumn:boolForColumn:doubleForColumn:stringForColumn:dataForColumn:dataNoCopyForColumn:UTF8StringForColumnIndex:objectForColumn:

 

這些方法也都包括 {type}ForColumnIndex 的這樣子的方法,參數是查詢結果集的列的索引位置。
你無需調用 [FMResultSet close]來關閉結果集, 當新的結果集產生,或者其資料庫關閉時,會自動關閉。

關閉資料庫

當使用完資料庫,你應該 -close 來關閉資料庫連接來釋放SQLite使用的資源。
[db close];

使用FMDatabaseQueue 及安全執行緒

在多個線程中同時使用一個FMDatabase執行個體是不明智的。現在你可以為每個線程建立一個FMDatabase對象。 不要讓多個線程分享同一個執行個體,它無法在多個線程中同時使用。 若此,壞事會經常發生,程式會時不時崩潰,或者報告異常,或者隕石會從天空中掉下來砸到你Mac Pro. 總之很崩潰。所以,不要初始化FMDatabase對象,然後在多個線程中使用。請使用 FMDatabaseQueue,它是你的朋友而且會協助你。以下是使用方法:
首先建立隊列

FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath];

這樣使用

[queue inDatabase:^(FMDatabase *db) {          [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]];          [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]];          [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]];          FMResultSet *rs = [db executeQuery:@"select * from foo"];          while([rs next]) {            …          }    }];

 

像這樣,輕鬆地把簡單任務封裝到事務裡

[queue inTransaction:^(FMDatabase *db, BOOL *rollback) {            [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]];            [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]];            [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]];            if (whoopsSomethingWrongHappened) {                    *rollback = YES; return;            }           // etc…            [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:4]];    }];

 

FMDatabaseQueue將運行在一個序列化隊列塊。所以如果你從多個線程在同一時間調用FMDatabaseQueue的方法,他們將執行他們收到的指令。這樣查詢和更新不會相互影響,每一個都是快樂的。

程式碼範例

FMDBDataBase.h

//  FMDBDataBase.h#import <Foundation/Foundation.h>@interface FMDBDataBase : NSObject// 擷取資料庫管理對象單例的方法+ (FMDBDataBase *)sharedDataBase;// 關閉資料庫- (void)closeDataBase;// 清空資料庫- (BOOL)deleteDataBase;// 向搜尋記錄表中插入新紀錄- (BOOL)insertSearchText:(NSString *)searchText;// 查詢資料庫中是否包含當前搜尋記錄- (BOOL)isExistSearchText:(NSString *)searchText;// 擷取所有搜素記錄- (NSMutableArray *)getAllSearchText;// 刪除所有搜尋記錄- (BOOL)deleteAllSearchText;@end

 

FMDBDataBase.m

#import "FMDBDataBase.h"#import "FMDB.h"@interface FMDBDataBase ()@property (nonatomic, strong) FMDatabase *fmDataBase;@end@implementation FMDBDataBase+ (FMDBDataBase *)sharedDataBase{    static FMDBDataBase *fmdbDataBase = nil;    static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{        fmdbDataBase = [[FMDBDataBase alloc] init];    });    return fmdbDataBase;}- (instancetype)init{    if (self = [super init]) {        _fmDataBase = [FMDatabase databaseWithPath:[self getDataBasePath]];        // 如果資料庫開啟失敗返回空值        if (![_fmDataBase open]) {            return nil;        }    }    // 如果資料庫開啟成功 建立表    // 建立搜尋歷程記錄表    NSString *searchHistorySql = @"CREATE TABLE IF NOT EXISTS t_history(t_id integer PRIMARY KEY AUTOINCREMENT, searchText text NOT NULL, age integer NOT NULL)";    BOOL isSuc = [_fmDataBase executeUpdate:searchHistorySql];    if (isSuc) {        NSLog(@"建立成功!");    }    return self;}- (NSString *)getDataBasePath{    // 1.獲得資料庫檔案的路徑    NSString *doc = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];//    NSString *doc = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];    NSString *fileName = [doc stringByAppendingPathComponent:@"fmdb.sqlite"];    return fileName;}// 清空資料庫- (BOOL)deleteDataBase{    NSString *sql = @"DELETE FROM t_history";    BOOL isSuc = [_fmDataBase executeUpdate:sql];    if (isSuc) {        NSLog(@"刪除成功");        return YES;    }    NSLog(@"刪除失敗");    return NO;}// 關閉資料庫- (void)closeDataBase{    if (_fmDataBase) {        [_fmDataBase close];    }}// 查詢資料庫中是否包含當前搜尋記錄- (BOOL)isExistSearchText:(NSString *)searchText{    NSString *sql = @"SELECT * FROM t_history";    FMResultSet *results = [_fmDataBase executeQuery:sql];    while (results.next) {        if ([searchText isEqualToString:[results stringForColumn:@"searchText"]]) {            return YES;        }    }    return NO;}// 搜尋記錄表中插入新記錄- (BOOL)insertSearchText:(NSString *)searchText{    if (!searchText || [searchText isEqualToString:@""] || [self isExistSearchText:searchText]) {        NSLog(@"資料為空白或已存在");        return NO;    }    NSString *sql = @"INSERT INTO t_history(searchText) VALUES (?)";   // executeUpdate : 不確定的參數用?來佔位    BOOL isInsertSuc = [_fmDataBase executeUpdate:sql, searchText];    if (isInsertSuc) {        NSLog(@"%@插入成功", searchText);        return YES;    }    NSLog(@"%@插入失敗", searchText);    return NO;}// 擷取所有的搜尋記錄- (NSMutableArray *)getAllSearchText{    NSString *sql = @"SELECT * FROM t_history order by t_id desc";    // 儲存所有資料的數組    NSMutableArray *searchTests = [NSMutableArray array];    FMResultSet *results = [_fmDataBase executeQuery:sql];    while (results.next) {        NSString *result = [results stringForColumn:@"searchText"];        [searchTests addObject:result];    }    return searchTests;}// 刪除所有的搜尋記錄- (BOOL)deleteAllSearchText{    NSString *sql = @"DELETE FROM t_history";    BOOL isDeleteSuc = [_fmDataBase executeUpdate:sql];    if (isDeleteSuc) {        NSLog(@"刪除成功");        return YES;    }    return NO;}@end

 

注意
  • 如果ID設定為逐漸,且設定為自動成長的話,那麼把表中的資料刪除後,重新插入新的資料,ID的編號不是從0開始,而是接著之前的ID進行編號。
參考文章
  • FMDB官方使用文檔(翻譯)
  • iOS開發資料庫篇—FMDB簡單介紹
歡迎閱讀上一篇:
  • iOS資料存放區之歸檔
  • iOS資料存放區之喜好設定和屬性列表

iOS-Ant-Bang互助社區 426981364
iOS技術交流群 461069757 歡迎加入!

iOS開發資料庫-FMDB

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.