SQLite Using C Library (1)

SQLite Using C Library(1)

NSString to C String

C語言所使用的字串方式是以char的類型去儲存內容,而Objective-C卻是用物件的方式去使用,所以字串方面需要轉換成C語言能接受的方式。

假設有個NSString名稱為 sqlitepath ,並將它轉成 databaseFileName 的char類型。

const char *databaseFileName =[sqlitepath UTF8String];

因為在NSString中是使用UTF8編碼進行儲存,利用這方式將字串的每個字取出並存入char的指標中。

引用SQLite C Library

標頭檔上必需要引用

#import <sqlite3.h>

並且必需要引用Library,在引用時先依照下圖到專案設定的 General ,並按下 +

之後到搜尋列輸入關鍵字 sqlite

選擇 libsqlite3.dylib 並按下 Add 將Library引入,引入成功會看到下圖

如此一來配合 sqlite3.h 才會發揮作用。

開啟資料庫

開啟資料的方式像下面般的格式:

returnCode= sqlite3_open(路徑, 資料庫指標);

範例中我們將 sqlitedata.db放在mainBundle之中,程式會先判斷檔案是否存在,不存在會有提示,

    char        *sqlStatement;
    sqlite3     *pDb;
    char        *errorMsg;
    int         returnCode;

    NSString *sqlitepath = [[NSBundle mainBundle] pathForResource:@"sqlitedata" ofType:@"db"];

    if ([[NSFileManager defaultManager] fileExistsAtPath:sqlitepath]){
        NSLog(@"檔案存在!");
        //這裡放置如果檔案存在時的程式
    }else{
        NSLog(@"檔案不存在!");
    }

    NSLog(@"%@",sqlitepath);

    const char *databaseFileName =[sqlitepath UTF8String];

    returnCode= sqlite3_open(databaseFileName, &pDb);
    if(returnCode!=SQLITE_OK) {
        fprintf(stderr, "Error in opening the database. Error: %s", sqlite3_errmsg(pDb));
        sqlite3_close(pDb);
        return;
    }

SQLITE_OK 代表整個SQLite命令是完成並且無問題產生。

執行SQL語法命令

在於整個SQL資料庫的操作是使用執行語法命令再加上回呼點(callback)設定的方式去操作:

返回碼 = sqlite3_exec(資料庫指標, 資料庫語法, callback名稱, NULL, 錯誤訊息);

原始標頭檔定義:

SQLITE_API int sqlite3_exec(
  sqlite3*,                                  /* An open database */
  const char *sql,                           /* SQL to be evaluated */
  int (*callback)(void*,int,char**,char**),  /* Callback function */
  void *,                                    /* 1st argument to callback */
  char **errmsg                              /* Error msg written here */
);

所以只要操作語法命令正確,就可以得到所預期的結果。

刪除資料表

我們在使用時先將建立好的資料表內容都刪除,避免在學習時會有重覆的資料產生,所以我們執行

DROP TABLE IF EXISTS  stocks

刪除 stocks 資料表,程式內容:

    sqlStatement =  "DROP TABLE IF EXISTS  stocks";
    returnCode = sqlite3_exec(pDb, sqlStatement, NULL, NULL, &errorMsg);
    if(returnCode!=SQLITE_OK) {
        fprintf(stderr, "Error in droping table stocks. Error: %s", errorMsg);
        sqlite3_free(errorMsg);
    }

刪除資料表只需要確定返回碼正確就可以,不需要設定callback,每次執行之後得到的結果是 SQLITE_OK 就代表整個過程是沒問題的,返回碼可以參照 sqlite3.h

新增資料表及資料庫格式

新增資料因重覆性很高,我將它寫成Function來使用:

void insertData(sqlite3 *pDb, const char*symbol, float price, int units, const char* date){
    char        *errorMsg;
    int         returnCode;
    char        *st;
    st  = sqlite3_mprintf("INSERT INTO stocks VALUES ('%q', %f, %d, '%q')",
                          symbol, price, units, date);
    returnCode = sqlite3_exec(pDb, st, NULL, NULL, &errorMsg);
    if(returnCode!=SQLITE_OK) {
        fprintf(stderr, "Error in inserting into the stocks table. Error: %s", errorMsg);
        sqlite3_free(errorMsg);
    }
    sqlite3_free(st);
}

程式碼中使用 sqlite3_mprintf 來建立執行的語法,這是利用格式化的方式來建立語法,這樣大大的改善可讀性及輸入可建立functaion的特性,然而 sqlite3_mprintf 功能就如同 sprintf 。 範例中連續建立很多筆的資料:

    insertData(pDb, "ALU",  14.23, 100, "03-17-2012");
    insertData(pDb, "GOOG",  600.77, 20, "01-09-2012");
    insertData(pDb, "NT",  20.23, 140, "02-05-2012");
    insertData(pDb, "MSFT",  30.23, 5, "01-03-2012");
    insertData(pDb, "中文測試!",  30.23, 5, "01-03-2012");


範例程式除了上述的提到的內容外,會在新增完將資料筆數顯示,來確定內容是否新增完成,顯示的技巧會在下次說明。

SQLite-Using-C-Library-1 範例下載