cocos2dx之引入Sqlite3資料庫

_Proxy發表於2020-04-07
從效能上說,XML方式的儲存基本可以滿足1 MB以下的儲存要求。但在更復雜的情景中,我們可能需要儲存多種不同的類,每個類也需要儲存不同的物件,此時XML儲存的速度就將成為瓶頸。即便分檔案儲存,管理起來也很麻煩,這個時候可以引入資料庫來提升儲存效率。
 關聯式資料庫是一種經典的資料庫,其中的資料被組織成表的形式,具有相同形式的資料存放在同一張表中,表內每一行代表一個資料。在表的基礎上,資料庫為我們提供增、刪、改、查等操作,這些操作通常採用SQL(結構化查詢語言)表達。這種格式化、集中的儲存再加上結構化的操作語言帶來一個非常大的好處:可以進行深度的優化,大大提升儲存和操作的效率。
 SQLite是移動裝置上常用的一個嵌入式資料庫,具有開源、輕量等特點,其原始碼只有兩個".c"檔案和兩個".h"檔案,並且已經包括了充分的註釋說明。相比MySQL或者SQL Server這樣的專業級資料庫,甚至是比起同樣輕量級的Access,SQLite的部署都可謂非常簡單,只要將這4個檔案匯入工程中即可,這使得編譯之後的SQLite非常小。

 SQLite將資料庫的資料儲存在磁碟的單一檔案中,並通過簡單的外部介面提供SQL支援。由於其設計之初即是針對小規模資料的操作,在查詢優化、高併發讀寫等方面做了極簡化的處理,可以保證不佔用系統額外的資源,因此,在大多數的嵌入式開發中,會比專業資料庫有更快速、高效的執行效率。


好了,看看如何加入Sqlite3吧,先從官網http://www.sqlite.org/download.html,下載你所想要的版本的sqlite,我這下的是3.8.2的,在解壓後,只有4個檔案,沒有.def或者是什麼dll,lib,這個是要自己生成的。


解壓後,將這四個檔案新增到你的當前工程中,然後進行編譯一下就可以了。


好了,先看個如何建立一個表:

回撥函式的格式如下:
int sqlite_callback(
    void* pv,    /* 由 sqlite3_exec() 的第四個引數傳遞而來 */
    int argc,        /* 表的列數 */
    char** argv,    /* 指向查詢結果的指標陣列, 可以由 sqlite3_column_text() 得到 */
    char** col        /* 指向表頭名的指標陣列, 可以由 sqlite3_column_name() 得到 */
);

引數格式:
    傳給sqlite3_exec的回撥函式,用來顯示查詢結果
    對每一條查詢結果呼叫一次該回撥函式
引數:
    pv:由sqlite3_exec傳遞的初始化引數
    argc:表頭的列數
    col:表頭的名字陣列指標
    argv:表頭的資料陣列指標
返回值:
    1:中斷查詢
    0:繼續列舉查詢到的資料
示例表:
+-----------------------------------+
|  id  |  pic   |  data(16進位制資料)  |
|-----------------------------------|
|   1  |  a.jpg |      00 00 00 ... |
|-----------------------------------|
|   2  |  b.jpg |     XX XX XX      |
+-----------------------------------+
對第一行資料:
    argc=3 即 [0]...[2]
    argv[0]="1",argv[1]="a.jpg",argv[2]="00 00 00..."(實際16進位制資料,非這裡顯示的字串形式)
    col[0]="id",col[1]="pic",col[2]="data"
 
說明:
    sqlite3_exec() 的回撥函式必須按照此格式, 當然形參的名字任意.
    如果某列的資料型別不是char*, 則可以對結果執行相關的轉換, 如:用atoi()把結果轉換為整數(integer), 如果是二進位制資料, 則可以直接強制型別轉換, 如:(void*)argv[i].
    該回撥函式有兩種返回值型別.
        1.返回零:sqlite3_exec() 將繼續執行查詢.
        2.返回非零:sqlite3_exec()將立即中斷查詢, 且 sqlite3_exec() 將返回 SQLITE_ABORT.
示例:
    int i;
    for(i=0; i<argc; i++)
    {
        printf("%s\t%s\n\n", col[i], argv[i]);
    }

例子:
    m_pGameDataBase = prepareTableInDB( "MyGame2", "E:\\database\\MyGame");

    std::string insert_sql_("insert into MyGame2 values(123, \"aaa\", 26, \"man\")");
    insertRecordIntoSqlite(insert_sql_);
    
    readRecord();// read the record


//
int  readFromSQLite(void *anyParam, int iColumn, char **pColumnValue, char **pColumnName ) {
    int icolumenCount = iColumn;
    for(int i = 0; i < icolumenCount; ++i) {
        CCLOG("%s: %s \n", pColumnName[i], pColumnValue[i]);
    }
    return 0;
}

void GameController::readRecord() {
    std::string read_sql_("select * from MyGame2");
    char *perrMsg = 0;
    sqlite3_exec( m_pGameDataBase,
                        read_sql_.c_str(),
                        readFromSQLite,
                        NULL,
                        &perrMsg);
}

sqlite3* GameController::prepareTableInDB(const char* table, const char* dbFilename) {
    sqlite3 *splite2Data = 0;
    char *errMsg = 0;

    if(SQLITE_OK != sqlite3_open(dbFilename, &splite2Data)) {
        CCLOG("Open the Game Data Table falied\n");
        return 0;
    }

    std::string string_sql = "create table if not exists " + std::string(table) + "(  id int unsigned auto_increment primary key,  name varchar(50),  age int,  sex varchar(10))";

    sqlite3_exec(splite2Data,
                       string_sql.c_str(),
                       NULL,
                       NULL,
                       &errMsg); // create a table;

    if(errMsg != 0) {
        CCLOG("Create the Data table failed\n");
        sqlite3_close(splite2Data);
        return 0;
    }

    return splite2Data;
}

void GameController::insertRecordIntoSqlite(std::string &r_stringOrder) {
    char *perrMsg = 0;
    int info =  sqlite3_exec(  m_pGameDataBase,
                                        r_stringOrder.c_str(),
                                       0,
                                       0,
                                       &perrMsg);
   do{
       if(perrMsg != 0) { // execute the instruct failed
           CCLOG("insert a record into the table failed\n");
           CCLOG("reason: %d, Error Message: %s \n", info, perrMsg);
           break;
       }

   } while(0);  
   sqlite3_close(m_pGameDataBase); // 
}


相關文章