iOS開發之FMDB

  sqlite做爲一個輕量級的數據庫,因爲它佔用的內存不多,所以在不少的嵌入式設備中獲得普遍的使用。iOS的SDK很早就開始支持了SQLite,咱們只須要加入 libsqlite3.dylib 以及引入 sqlite3.h 頭文件便可,但因爲原生sqlite的API不是很友好,所以使用的話通常會對其作一層封裝,其中以開源的FMDB最爲流行。sql

FMDB主要的類

1.FMDatabase – 表示一個單獨的SQLite數據庫。 用來執行SQLite的命令。數據庫

2.FMResultSet – 表示FMDatabase執行查詢後結果集安全

3.FMDatabaseQueue – 當你在多線程中執行操做,使用該類能確保線程安全。多線程

 

FMDB的使用

數據庫的建立app

建立FMDatabase對象時須要參數爲SQLite數據庫文件路徑。該路徑能夠是如下三種之一:spa

1..文件路徑。該文件路徑無需真實存,若是不存在會自動建立。線程

2..空字符串(@」")。表示會在臨時目錄建立一個臨時數據庫,當FMDatabase 連接關閉時,文件也被刪除。code

3.NULL. 將建立一個內存數據庫。一樣的,當FMDatabase鏈接關閉時,數據會被銷燬。sqlite

內存數據庫:對象

  一般數據庫是存放在磁盤當中的。然而咱們也可讓存放在內存當中的數據庫,內存數據庫的優勢是對其操做的速度較快,畢竟訪問內存的耗時低於訪問磁盤,但內存數據庫有以下缺陷:因爲內存數據庫沒有被持久化,當該數據庫被關閉後就會馬上消失,斷電或程序崩潰都會致使數據丟失;不支持讀寫互斥處理,須要本身手動添加鎖;沒法被別的進程訪問。

臨時數據庫:

  臨時數據庫和內存數據庫很是類似,兩個數據庫鏈接建立的臨時數據庫也是各自獨立的,在鏈接關閉後,臨時數據庫將自動消失,其底層文件也將被自動刪除。儘管磁盤文件被建立用於存儲臨時數據庫中的數據信息,可是實際上臨時數據庫也會和內存數據庫同樣一般駐留在內存中,惟一不一樣的是,當臨時數據庫中數據量過大時,SQLite爲了保證有更多的內存可用於其它操做,所以會將臨時數據庫中的部分數據寫到磁盤文件中,而內存數據庫則始終會將數據存放在內存中。

 

建立數據庫:FMDatabase *db= [FMDatabase databaseWithPath:dbPath] ;

在進行數據庫的操做以前,必需要先把數據庫打開,若是資源或權限不足沒法打開或建立數據庫,都會致使打開失敗。

以下爲建立和打開數據庫的示例:

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [paths objectAtIndex:0];

//dbPath: 數據庫路徑,存放在Document中。
NSString *dbPath = [documentDirectory stringByAppendingPathComponent:@"MYTest.db"];

//建立數據庫實例 db  這裏說明下:若是路徑中不存在"MYTest.db"的文件,sqlite會自動建立"MYTest.db"
FMDatabase *db= [FMDatabase databaseWithPath:dbPath] ;
if (![db open]) {
NSLog(@"Could not open db.");
return ;
}

 

更新操做

一切不是SELECT命令都視爲更新操做,包括CREATE, UPDATE, INSERT,ALTER,COMMIT, BEGIN, DETACH, DELETE, DROP, END, EXPLAIN, VACUUM和REPLACE等。

 建立表:

[db executeUpdate:@"CREATE TABLE myTable (Name text,Age integer)"];

插入

[db executeUpdate:@"INSERT INTO myTable (Name,Age) VALUES (?,?)",@"jason",[NSNumber numberWithInt:20]];

更新

[db executeUpdate:@"UPDATE myTable SET Name = ? WHERE Name = ? ",@"john",@"jason"];.

刪除

[db executeUpdate:@"DELETE FROM myTable WHERE Name = ?",@"jason"];

查詢操做

SELECT命令就是查詢,執行查詢的方法是以 -excuteQuery開頭的。執行查詢時,若是成功返回FMResultSet對象, 錯誤返回nil. 讀取信息的時候須要用while循環:

FMResultSet *s = [db executeQuery:@"SELECT * FROM myTable"];   
while ([s next]) {   
    //從每條記錄中提取信息

}   

 

關閉數據庫

當使用完數據庫,你應該 -close 來關閉數據庫鏈接來釋放SQLite使用的資源。

 [db close];  

參數

一般狀況下,你能夠按照標準的SQL語句,用?表示執行語句的參數,如:

INSERT INTO myTable VALUES (?, ?, ?)

而後,能夠咱們能夠調用executeUpdate方法來將?所指代的具體參數傳入,一般是用變長參數來傳遞進去的,以下:

NSString *sql = @"insert into myTable (name, password) values (?, ?)";
[db executeUpdate:sql, user.name, user.password];

這裏須要注意的是,參數必須是NSObject的子類,因此象int,double,bool這種基本類型,須要進行相應的封裝

[db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:42]];

 

多線程操做

  因爲FMDatabase對象自己不是線程安全的,所以爲了不在多線程操做的時候出錯,須要使用 FMDatabaseQueue來執行相關操做。只須要利用一個數據庫文件地址來初使化FMDatabaseQueue,而後傳入一個block到inDatabase中,即便是多個線程同時操做,該queue也會確保這些操做能按序進行,保證線程安全。

建立隊列:

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]];      
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 (somethingWrongHappened) {
         *rollback = YES;
return; } // etc… [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:4]]; }];
相關文章
相關標籤/搜索