sqlit3使用知識

SQLite3的確很好用。小巧、速度快。這些天正在研究它,將它移植到ARM系統裏面,又有一些收穫,這裏把我對sqlite3的研究列出來,以備忘記。【其中有摘抄自互聯網】
SQLite3提供的是一些C函數接口,你可以用這些函數操作數據庫。通過使用這些接口,傳遞一些標準sql語句(以char *類型)給SQLite3函數,SQLite3就會爲你操作數據庫。
SQLite3跟MS的access一樣是文件型數據庫,就是說,一個數據庫就是一個文件,此數據庫裏可以建立很多的表,可以建立索引、觸發器等等,但是,它實際上得到的就是一個文件。備份這個文件就備份了整個數據庫。
SQLite3不需要任何數據庫引擎,這意味着如果你需要SQLite3來保存一些用戶數據,甚至都不需要安裝數據庫。

打開數據庫
int sqlite3_open(const char *zFilename, sqlite3 **ppDb)
需要傳入兩個參數,一是數據庫文件名,比如:"/flash/mydb1.db"。文件名不需要一定存在,如果此文件不存在,SQLite3會自動建立它。如果它存在,就嘗試把它當數據庫文件來打開。sqlite3 **ppDb參數是關鍵數據結構。這個結構底層細節如何,你不要關它。
函數返回值表示操作是否正確,如果是SQLITE_OK則表示操作正常。相關的返回值sqlite定義了一些宏。具體這些宏的含義可以參考sqlite3.h文件。裏面有詳細定義(順便說一下,SQLite3的代碼註釋率自稱是非常高的,實際上也的確很高。只要你會看英文,SQLite3可以讓你學到不少東西)。

關閉數據庫
int sqlite3_close(sqlite3 *db)
如果用sqlite3_open開啓了一個數據庫,結尾時不要忘了用這個函數關閉數據庫。
使用例題:
{
  sqlite3 *db;
  int res;
  res = sqlite3_open("/flash/db1.db", &db);
  if(res != SQLITE_OK) {
    return -1;
  }
  sqlite3_close(db);
}

執行sql語句
int sqlite3_exec(sqlite3 *db,const char *zSql,sqlite3_callback xCallback,void *pArg,char **pzErrMsg)
這就是執行一條sql語句的函數。
第1個參數不再說了,是前面open函數得到的指針。說了是關鍵數據結構。
第2個參數const char *sql是一條sql語句,以/0結尾。
第3個參數sqlite3_callback是回調,當這條語句執行之後,sqlite3會去調用你提供的這個函數。
第4個參數void *pArg是你所提供的指針,你可以傳遞任何一個指針參數到這裏,這個參數最終會傳到回調函數裏面,如果不需要傳遞指針給回調函數,可以填NULL。等下我們再看回調函數的寫法,以及這個參數的使用。
第5個參數char ** errmsg是錯誤信息。注意是指針的指針。sqlite3裏面有很多固定的錯誤信息。執行sqlite3_exec之後,執行失敗時可以查閱這個指針(直接printf(“%s/n”,errmsg))得到一串字符串信息,這串信息告訴你錯在什麼地方。sqlite3_exec函數通過修改你傳入的指針的指針,把你提供的指針指向錯誤提示信息,這樣sqlite3_exec函數外面就可以通過這個char*得到具體錯誤提示。
說明:通常,sqlite3_callback和它後面的void *這兩個位置都可以填NULL。填NULL表示你不需要回調。比如你做insert操作,做delete操作,就沒有必要使用回調。而當你做select時,就要使用回調,因爲sqlite3把數據查出來,得通過回調告訴你查出了什麼數據。

exec的回調
typedef int(*sqlite3_callback)(void *,int,char**,char**);
你的回調函數必須定義成上面這個函數的類型。下面給個簡單的例子:
//sqlite3的回調函數       
// sqlite每查到一條記錄,就調用一次這個回調
intLoadMyInfo(void* para,intn_column,char** column_value,char** column_name ) {
//para是你在sqlite3_exec裏傳入的void *參數
//通過para參數,你可以傳入一些特殊的指針(比如類指針、結構指針),然後在這裏面強制轉換成對應的類型(這裏面是void*類型,必須強制轉換成你的類型纔可用)。然後操作這些數據
//n_column是這一條記錄有多少個字段(即這條記錄有多少列)
// char ** column_value是個關鍵值,查出來的數據都保存在這裏,它實際上是個1維數組(不要以爲是2維數組),每一個元素都是一個char *值,是一個字段內容(用字符串來表示,以/0結尾)
//char ** column_name跟column_value是對應的,表示這個字段的字段名稱
//這裏,我不使用para參數。忽略它的存在.
 int i;
 printf(“記錄包含%d個字段/n”, n_column );
 for( i = 0 ; i < n_column; i ++ ) {
  printf(“字段名:%s ß>字段值:%s/n”, column_name[i], column_value[i] );
 }
 printf(“------------------/n“);       
 return 0;
}
int main( int , char ** )
{
 sqlite3 * db;
 int result;
 char * errmsg = NULL;
 result = sqlite3_open("/flash/db1.db", &db);
//數據庫操作代碼
//創建一個測試表,表名叫MyTable_1,有2個字段:ID和name。其中ID是一個自動增加的類型,以後insert時可以不去指定這個字段,它會自己從0開始增加
 result = sqlite3_exec( db,“create table MyTable_1( ID integer primary key autoincrement, name nvarchar(32) )”, NULL, NULL, errmsg );
//插入一些記錄
result = sqlite3_exec( db,“insert into MyTable_1( name ) values (‘走路’)”, 0, 0, errmsg );
result = sqlite3_exec( db,“insert into MyTable_1( name ) values (‘騎單車’)”, 0, 0, errmsg );
result = sqlite3_exec( db,“insert into MyTable_1( name ) values (‘坐汽車’)”, 0, 0, errmsg );
//開始查詢數據庫
result = sqlite3_exec( db,“select * from MyTable_1”, LoadMyInfo, NULL, errmsg );
//關閉數據庫
sqlite3_close( db );
return0;
}
通過上面的例子,應該可以知道如何打開一個數據庫,如何做數據庫基本操作。有這些知識,基本上可以應付很多數據庫操作了。

不使用回調查詢數據庫
上面介紹的sqlite3_exec是使用回調來執行select操作。還有一個方法可以直接查詢而不需要回調。但是,我個人感覺還是回調好,因爲代碼可以更加整齊,只不過用回調很麻煩,你得聲明一個函數,如果這個函數是類成員函數,你還不得不把它聲明成static的(要問爲什麼?這又是C++基礎了。C ++成員函數實際上隱藏了一個參數:this,C++調用類的成員函數的時候,隱含把類指針當成函數的第一個參數傳遞進去。結果,這造成跟前面說的 sqlite回調函數的參數不相符。只有當把成員函數聲明成static時,它纔沒有多餘的隱含的this參數)。
雖然回調顯得代碼整齊,但有時候你還是想要非回調的select查詢。這可以通過sqlite3_get_table函數做到。
intsqlite3_get_table(sqlite3*,constchar*sql,char***resultp,int*nrow,int*ncolumn,char**errmsg );
第1個參數不再多說,看前面的例子。
第2個參數是sql語句,跟sqlite3_exec裏的sql是一樣的。是一個很普通的以/0結尾的char *字符串。
第3個參數是查詢結果,它依然一維數組(不要以爲是二維數組,更不要以爲是三維數組)。它內存佈局是:第一行是字段名稱,後面是緊接着是每個字段的值。下面用例子來說事。
第4個參數是查詢出多少條記錄(即查出多少行)。
第5個參數是多少個字段(多少列)。
第6個參數是錯誤信息,跟前面一樣,這裏不多說了。
下面給個簡單例子:
int main( int , char ** )
{
         sqlite3 * db;
         int result;
         char * errmsg = NULL;
char **dbResult;//是char **類型,兩個*號
        int nRow, nColumn;
         int i , j;
         int index;
 
         result = sqlite3_open(/flash/db1.db", &db);
//數據庫操作代碼
//假設前面已經創建了MyTable_1表
//開始查詢,傳入的dbResult已經是char **,這裏又加了一個&取地址符,傳遞進去的就成了char ***
result = sqlite3_get_table( db,“select * from MyTable_1”, &dbResult, &nRow, &nColumn, &errmsg );
if(SQLITE_OK== result )
{
    //查詢成功
   index = nColumn;//前面說過dbResult前面第一行數據是字段名稱,從nColumn索引開始纔是真正的數據
    printf(“查到%d條記錄/n”, nRow );
    for( i = 0; i < nRow ; i++ )
    {
        printf(“第%d條記錄/n”, i+1 );
        for( j = 0 ; j < nColumn; j++ )
        {
             printf(“字段名:%s ß>字段值:%s/n”, dbResult[j], dbResult [index] );
             ++index;// dbResult的字段值是連續的,從第0索引到第nColumn - 1索引都是字段名稱,從第nColumn索引開始,後面都是字段值,它把一個二維的表(傳統的行列表示法)用一個扁平的形式來表示
        }
        printf(“-------/n”);
    }
}
//到這裏,不論數據庫查詢是否成功,都釋放char**查詢結果,使用sqlite提供的功能來釋放
sqlite3_free_table( dbResult );
//關閉數據庫
sqlite3_close( db );
return0;
}
 
到這個例子爲止,sqlite3的常用用法都介紹完了。
用以上的方法,再配上sql語句,完全可以應付絕大多數數據庫需求
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章