zoukankan      html  css  js  c++  java
  • FMDB一个sqlite的封装

    转:http://blog.csdn.net/workhardupc100/article/details/6830754

    首先到這裡下載FMDB的source code,接著在解開的檔案裡,把src資料夾下除了fmdb.m的檔案加入到自己的iOS專案,最後在專案中加入libsqlite3.dylib這個函式庫就可以了。啥?有人問為什麼不用加入fmdb.m?簡單講,這個檔案是fmdb的使用說明。裡面的註解清楚,範例又簡單,如果有興趣,直接看fmdb.m,大概就會用fmdb了。


    以下介紹幾個常用的指令,分享給大家:

    -開啟/關閉資料庫

    使用資料庫的第一件事,就是建立一個資料庫。要注意的是,在iOS環境下,只有document directory 是可以進行讀寫的。在寫程式時用的那個Resource資料夾底下的東西都是read-only。因此,建立的資料庫要放在document 資料夾下。方法如下:

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

    NSString *documentDirectory = [paths objectAtIndex:0];

    NSString *dbPath = [documentDirectory stringByAppendingPathComponent:@"MyDatabase.db"];

    FMDatabase

    *db = [FMDatabase databaseWithPath:dbPath] ;

    if (![db open]) {

    NSLog(@“Could not open db.”);

    return ;

    }

    通常這段程式碼會放在UIViewController中viewDidLoad的函式裡。指定路徑後,用[FMDatabase databaseWithPath:]回傳一個FMDatabase物件,如果該路徑本來沒有檔案,會新增檔案,不然會開啟舊檔。最後呼叫[db open]可以開啟該資料庫檔案,[db close]則關閉該檔案。

    -建立table

    如果是新建的資料庫檔,一開始是沒有table的。建立table的方式很簡單:

    [db executeUpdate:@"CREATE TABLE PersonList (Name text, Age integer, Sex integer, Phone text, Address text, Photo blob)"];

    這是FMDB裡很常用的指令,[FMDatabase_object executeUpdate:]後面用NSString塞入SQLite語法,就解決了。因為這篇主要是在講FMDB,所以SQLite的語法就不多說了,上述程式碼建立了一個名為PersonList的table,裡面有姓名、年齡、性別、電話、地址和照片。(嗯….很範例的一個table)

    -插入資料

    插入資料跟前面一樣,用executeUpdate後面加語法就可以了。比較不同的是,因為插入的資料會跟Objective-C的變數有關,所以在string裡使用?號來代表這些變數。

    [db executeUpdate:@"INSERT INTO PersonList (Name, Age, Sex, Phone, Address, Photo) VALUES (?,?,?,?,?,?)",

    @"Jone", [NSNumber numberWithInt:20], [NSNumber numberWithInt:0], @“091234567”, @“Taiwan, R.O.C”, [NSData dataWithContentsOfFile:filepath]];

    其中,在SQLite中的text對應到的是NSString,integer對應NSNumber,blob則是NSData。該做的轉換FMDB都做好了,只要了解SQLite語法,應該沒有什麼問題才是。

    -更新資料

    太簡單了,不想講,請看範例:

    [db executeUpdate:@"UPDATE PersonList SET Age = ? WHERE Name = ?",[NSNumber numberWithInt:30],@“John”];

    -取得資料

    取得特定的資料,則需使用FMResultSet物件接收傳回的內容:

    FMResultSet *rs = [db executeQuery:@"SELECT Name, Age, FROM PersonList"];

    while ([rs next]) {

    NSString *name = [rs stringForColumn:@"Name"];

    int age = [rs intForColumn:@"Age"];

    }

    [rs close];

    用[rs next]可以輪詢query回來的資料,每一次的next可以得到一個row裡對應的數值,並用[rs stringForColumn:]或[rs intForColumn:]等方法把值轉成Object-C的型態。取用完資料後則用[rs close]把結果關閉。

    -快速取得資料

    在有些時候,只會query某一個row裡特定的一個數值(比方只是要找John的年齡),FMDB提供了幾個比較簡便的方法。這些方法定義在FMDatabaseAdditions.h,如果要使用,記得先import進來。

    //找地址

    NSString *address = [db stringForQuery:@"SELECT Address FROM PersonList WHERE Name = ?",@"John”];

    //找年齡

    int age = [db intForQuery:@"SELECT Age FROM PersonList WHERE Name = ?",@"John”];

    大概就是這樣囉~對於在Objective-C上使用SQLite有困難的朋友,看完之後是不是覺得一切都變的很簡單呢?趕快去試試吧~



    以下内容转载自:http://psvsps2.blogspot.com/2010/06/sqlite-in-iphone.html

    簡易教學

    這個 Project 真的是簡單不囉說,和sqlite一樣輕巧好用簡單,簡單到沒有說明文件 沒有 API 檔案,作者也叫你自己看原始碼,當然真的很簡單才敢這樣(或是很懶..)

    在解釋細節前要先介紹兩個 Class 一個是 FMDatabase 包裝所有 sqlite 相關的操作,一個是 FMResultSet 包裝查詢回來的結果。

    接下來直接看範例就很容易理解運作方式了。

    讀取/建立/關閉database以及執行沒有傳回值的SQL命令

    FMDatabase databaseWithPath: 傳回來的物件和 stringWithString: arrayWithObjects: 這些便利工廠函式 (factroy method) 一樣,傳回來的物件 已經有對他送出 autorelease message,所以不需要明確的呼叫 release 釋放物件。

    setShouldCacheStatements: 會把編譯過的 sql 敘述存起來供以後使用,對於 效率有所幫助。

    executeUpdate: 用來執行沒有返回資料的sql命令,如 create table, insert into, alter table 等等, executeUpdate: 支援了類似stringWithFormate: 的 語法,相當方便。

    beginTransaction commit 是一對的,不要單獨使用。

    最後我們不會忘記在 sqlite C/C++ API 中開啟資料庫用完後是要關閉釋放出資源的, ( sqlite_close(db) ),在 FMDB 中直接傳送 close message 給 FMDatabase 物件。

    FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];
    // open 和 close 是成對的 method
    if (![db open]) {
      //Error handling -- can't open database
    }
    
    // 設定儲存 prepared statements
    [db setShouldCacheStatements:YES];
    
    // executeUpdate 用來執行
    [db executeUpdate:@"create table test (a text, b text, c integer, d double, e double)"];
    
    // 會執行 BEGIN EXCLUSIVE TRANSACTION 命令鎖住資料庫。
    [db beginTransaction];
    int i = 0;
    while (i++ < 20) {
      // 類似 stringWithFormat: 的語法!
      [db executeUpdate:@"insert into test (a, b, c, d, e) values (?, ?, ?, ?, ?)" ,
             @"hi'", // 不需要把'寫成\'或是''
             [NSString stringWithFormat:@"number %d", i],
             [NSNumber numberWithInt:i],
             [NSDate date],
             [NSNumber numberWithFloat:2.2f]];
     }
     [db commit];
     [db close];
    

    處理查詢結果

    接者介紹如果有查詢結果的處理方式: executeQuery: 會傳回 FMResultSet 物件, FMResultSet 可以非常方便 的取得傳回值,使用 next 取得每個完整的row並透過一組 xxxxForColumn: 的 method 存取 column 資料。

    columnNameForIndex: 可以快速查詢 column 的名稱。

    熟悉 sqlite C/C++ API 的話會知道, 執行 sql 命令的 function:

    int sqlite3_step(sqlite3_stmt*);
    

    是依據一個 prepared statement 來進行處理,在 FMDB 包裝好的 FMResultSet 物件 也有保存對應的 statement 物件,大家都知道物件沒用了就要釋放, FMResultSet 在執行 dealloc 會釋放保存的 statement 如果想明確釋放(比如想重複使用FMResultSet物件於不同的查詢) 需執行:

    [ResultSet close];
    

    下面是較為完整的範例程式片段,繼續承接上面的範例。

    FMResultSet *rs = [db executeQuery:@"select rowid,* from test where a = ?", @"hi'"];
    while ([rs next]) {
    
        NSLog(@"%d %@ %@ %@ %@ %f %f",
              [rs intForColumn:@"c"],
              [rs stringForColumn:@"b"],
              [rs stringForColumn:@"a"],
              [rs stringForColumn:@"rowid"],
              [rs dateForColumn:@"d"],
              [rs doubleForColumn:@"d"],
              [rs doubleForColumn:@"e"]);
    
    
        if (!([[rs columnNameForIndex:0] isEqualToString:@"rowid"] &&
              [[rs columnNameForIndex:1] isEqualToString:@"a"])
              ) {
            NSLog(@"WHOA THERE BUDDY, columnNameForIndex ISN'T WORKING!");
            return 7;
        }
    }
    [rs close];
    

    Blob 處理範例

    // blob support.
    // blob 處理的範例,這邊使用NSData包裝資料。
    [db executeUpdate:@"create table blobTable (a text, b blob)"];
    
    // let's read in an image from safari's app bundle.
    NSData *safariCompass = [NSData dataWithContentsOfFile:@"/Applications/Safari.app/Contents/Resources/compass.icns"];
    if (safariCompass) {
        [db executeUpdate:@"insert into blobTable (a, b) values (?,?)", @"safari's compass", safariCompass];
    
        rs = [db executeQuery:@"select b from blobTable where a = ?", @"safari's compass"];
        if ([rs next]) {
            safariCompass = [rs dataForColumn:@"b"];
            [safariCompass writeToFile:@"/tmp/compass.icns" atomically:NO];
    
            // let's look at our fancy image that we just wrote out..
            system("/usr/bin/open /tmp/compass.icns");
    
            // ye shall read the header for this function, or suffer the consequences.
            safariCompass = [rs dataNoCopyForColumn:@"b"];
            [safariCompass writeToFile:@"/tmp/compass_data_no_copy.icns" atomically:NO];
            system("/usr/bin/open /tmp/compass_data_no_copy.icns");
        }
        else {
            NSLog(@"Could not select image.");
        }
    
        [rs close];
    
    }
    else {
        NSLog(@"Can't find compass image..");
    }
    

    錯誤處理

    FMDB 的錯誤處理機制也相當容易, FMDatabase 提供3個 methods 供我們存取 錯誤狀態:

    - (BOOL)hadError; - (int)lastErrorCode; - (NSString*)lastErrorMessage;

    概念類似 Win32 API 的 GetLastError() ,系統幫你保存最後一個錯誤碼,當要檢查 有無發生錯的時候直接透過 hadError 判斷,在由lastErrorCodelastErrorMessage 取得相關資訊。

    if ([db hadError]) {
      NSLog(@"Err %d: %@", [db lastErrorCode], [db lastErrorMessage]);
    }
    

    快速查詢第一個

    FMDB 依照不同的資料型態還提供一組便利 methods xxxForQuery: ,其中xxx表示資料型態 如 intForQuery: 就會傳回查詢後第一個結果並轉成 int type (row at index:0)

    [db executeUpdate:@"create table t1 (a integer)"];
    [db executeUpdate:@"insert into t1 values (?)", [NSNumber numberWithInt:5]];
    int a = [db intForQuery:@"select a from t1 where a = ?", [NSNumber numberWithInt:5]];
    if (a != 5) {
      NSLog(@"intForQuery didn't work (a != 5)");
    }
  • 相关阅读:
    新手第一次联系oracle的碰到的触发器不能创建的问题
    dubbo注册中心占位符无法解析问题(二)
    dubbo注册中心占位符无法解析问题(一)
    .
    Ubuntu16 安装后配置
    TiDB-----使用 TiUP cluster 在单机上模拟生产环境部署步骤
    TiDB 单机安装(在 Linux OS 上部署本地测试环境)
    WPF查找子控件和父控件方法
    Java基础相关
    C++ namespace浅析
  • 原文地址:https://www.cnblogs.com/jackljf/p/3588953.html
Copyright © 2011-2022 走看看