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 范例下载