SQLite入門使用教程(一)



  最近在做一個C++的項目,裏面用到了SQLIte數據庫。於是,到官網去查看SQLite 的C++接口,因爲到網上的博客去看別人寫的SQLite教程,有些看不太懂,所以只好到官網上去看。其實,我還是喜歡用Qt來操作SQLite,因爲Qt 對SQLite的接口函數進行了封裝,操作更方便。但是項目組裏的其他人用的是VS 2010,於是,不得不去看官網的英文文檔。             SQLite C/C++ 接口網址:http://www.sqlite.org/cintro.html點擊打開鏈接



      首先,只要是對數據庫操作有些瞭解的朋友都知道:數據庫操作無非就是增,刪,改,查,這些基本的操作。學習SQLite之前,首先要安裝好SQLite的庫文件,這個大家可以去官網上下。在Linux 下安裝SQLite是非常方便的,我是用新得立軟件包這個軟件一鍵安裝的,在Windows下,就需要sqlite3.dll,sqlite3.h,sqlite3.lib這三個文件,分別爲動態庫文件,頭文件和靜態庫文件。然後相應的進行配置,這個可以去網上查。


接下來我們就來看官網上的介紹:
(一) 核心對象和接口:
            1. 在SQLite中最核心的兩個對象是,database_connection和prepared_statement。database_connection對象是由sqlite3_open()接口函數創建並返回的,它是一個數據庫連接對象,在程序使用任何其他SQLite接口函數之前,必須先調用該函數以便獲得database connection 對象,否則不能打開一個數據庫。嚴格來講,prepared statement對象不是必須的,因爲有兩個更爲方便的包裝接口: sqlite3_exec和sqlite3_get_table,這兩個接口可以被方便的使用並且隱藏了 prepared statement對象。然而,對 prepared statement對象的理解對我們充分理解和使用SQLite數據庫有很大的幫助。這兩個接口函數在下一篇博文中講解。


            2.在SQLite中最核心的六個接口是:
sqlite3_open();
sqlite3_prepare();
sqlite3_step();
sqlite3_column();
sqlite3_finalize();
sqlite3_close();

                                          

下面對它們的用法進行說明:

2.0    打開數據庫:
int sqlite3_open(
  const char *filename,  /* Database filename (UTF-8) */待打開(創建)的數據庫文件名
  sqlite3 **ppDb         /* OUT: SQLite db handle */sqlite3數據庫句柄的指針
);
該接口打開一個數據庫文件,並與一個sqlite3句柄關聯。如果該文件不存在則創建它。返回值如果是SQLITE_OK則打開成功。

如:sqlite3 *mysqlite3;       //定義一個數據庫句柄,可以理解爲一個數據庫連接

           sqlite3_open("D:\\mysqlite\\mysqlite.db",&mysqlite3);


2.1 創建預處理語句對象:
int sqlite3_prepare(
  sqlite3 *db,            /* Database handle */  數據庫句柄
  const char *zSql,       /* SQL statement, UTF-8 encoded */  sql語句
  int nByte,              /* Maximum length of zSql in bytes. */sql語句長度,設置成-1,則自動按字符串計算sql語句長度
  sqlite3_stmt **ppStmt,  /* OUT: Statement handle */     prepared statement對象
  const char **pzTail     /* OUT: Pointer to unused portion of zSql */   一般爲NULL即可
);

該接口把一個SQL語句文本轉換成一個預處理語句對象並返回一個指向該對象的指針。這個接口需要一個由先前調用sqlite3_open()返回的數據庫連接對象指針以及一個預處理的SQL語句文本字符串爲參數。這個API並不實際解析SQL語句,僅僅是爲後續的解析而對SQL語句進行的預處理。也就是說,調用sqlite3_prepare()將SQL語句編譯爲sqlite內部一個結構體(sqlite3_stmt),該結構體中包含了將要執行的的SQL語句的信息。

如:sqlite3_prepare_v2(mysqlite3,"select * from friends",-1,&stmt,NULL);


2.2 執行SQL語句 
int sqlite3_step(sqlite3_stmt*);
該接口用於解析一個由先前通過sqlite3_prepare()接口創建的預處理語句,直至返回第一行結果爲止。通過再次調用sqlite3_step()可以返回下一行的結果,繼續不斷

地調用sqlite3_step()直至整個語句完成爲止。對於那些並不返回結果的語句(例如:insert,delete語句等)一次調用sqlite3_step()就完成了語句的處理。注意,調用sqlite3_step()這時候SQL語句才真正執行,一次它只返回一行數據。

返回值:SQLITE_BUSY:數據庫被鎖,可以等待釋放後重新調用該函數
       SQLITE_DONE:成功
       SQLITE_ROW:成功並且有數據返回,每查詢到一條數據都會返回該值
       SQLITE_ERROR:失敗
       SQLITE_MISUSE:錯誤的調用,比如已經返回了SQLITE_DONE或者SQLITE_ERROR後還繼續調用該函數

       如:sqlite3_step(stmt);

2.3 對返回的行數據中的每一列進行查詢:sqlite3_column_xxx, 其中blob,double,int,int64,text,text16表示的是要查詢的那一列的數據類型

const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);//其中參數iCol爲列號,從0開始,即第一列爲0
int sqlite3_column_bytes(sqlite3_stmt*, int iCol);      //sqlite3_stmt* 爲prepared statement對象的指針
int sqlite3_column_bytes16(sqlite3_stmt*, int iCol);
double sqlite3_column_double(sqlite3_stmt*, int iCol);
int sqlite3_column_int(sqlite3_stmt*, int iCol);
sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol);
const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);   
const void *sqlite3_column_text16(sqlite3_stmt*, int iCol);
int sqlite3_column_type(sqlite3_stmt*, int iCol);
sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol);
 
以上接口返回一個由sqlite3_step()解析的預處理語句結果集中當前行的某一列數據。每次執行sqlite3_step()都返回一個新的結果集中的一行。可以多次調用sqlite3_column_xxx()接口返回那一行中所有列的數據。sqlite3_column_xxx是一組用於從結果集中查詢出各個列項各種數據類型數據的函數接口。在這組函數接口中,有些接口返回結果集的大小,有些返回結果集的列數。

如:
int ID = sqlite3_column_int( stmt, 0 );
char * IP = sqlite3_column_text(stmt,1 );
char *name  = sqlite3_column_text( stmt, 2 );


2.4 銷燬預處理語句sqlite3_finalize() 

 int sqlite3_finalize(sqlite3_stmt *pStmt); 

sqlite3_finalize()釋放之前調用sqlite3_prepare()創建的預處理語句stmt佔用的內存,該內存是在sqlite3_prepare()時分配的,每一個預處理語句都必須調用這個接口進行銷燬以避免內存泄漏。

如:sqlite3_finalize(stmt);

2.5 關閉數據庫 sqlite3_close()
int sqlite3_close(sqlite3*);
  該接口關閉一個由之前調用sqlite3_open()創建的數據庫連接,所有與該連接相關的預處理語句都必須在關閉連接之前銷燬。

如:sqlite3_close(mysqlite3);



下面,通過一個實例代碼來演示它們的用法:


void Talk()   //根據ID號204,查詢其IP爲多少
{
    sqlite3 *mysqlite3;     //SQLite 連接對象
    int reopen;
    reopen = sqlite3_open("D:\\mysqlite\\mysqlite.db",&mysqlite3);//返回值如果是SQLITE_OK,則打開成功,SQLITE_OK爲sqlite3.h中的宏定義
   if(reopen != SQLITE_OK )               //#define SQLITE_OK     0 /* Successful result */               {
      cout<<"it failed to open mysqlite.db"<<endl;
   }else
   {
      cout<<"it success to open mysqlite.db"<<endl;
    }
    sqlite3_stmt *stmt;//prepare_statment 對象
    char *sql="select IP from userInfo where ID = 204";   //SQL語句,表示查詢ID=204所在的那行的IP那一列的數據                                                                    
    sqlite3_prepare_v2(mysqlite3,sql,-1,&stmt,NULL); //把SQL語句作爲第二個參數傳入,第三個參數-1      表示自動按字符串計算sql語句長度,第五個一般爲NULL
    int restep = sqlite3_step(stmt)//返回值如果是SQLITE_ROW,表示成功並且有數據返回,SQLITE_ROW爲sqlite3.h中的宏定義                                                         
    if(restep == SQLITE_ROW)        //#define SQLITE_ROW  100  
    {
       char *IP= (char *)sqlite3_column_text(stmt,0); //因爲這裏只返回IP那一列的值,所以第二個參數爲0         cout << IP<<endl;
    }
    sqlite3_finalize(stmt);
    sqlite3_close(mysqlite3);
}


               通過上面的例子相信大家應該基本學會了SQLITE3的基本用法,再來分析上面的例子,相信大家會發現它的不靈活,因爲它查詢的ID是寫死的,如果我想查詢任一個ID的信息呢?那就需要把ID作爲形參傳入這個函數,這就是接下來要講的:


(二)參數綁定和重新執行已編譯語句

在上面的討論中,假定每個SQL語句一旦準備,然後就執行,最後被銷燬。然而,SQLite3允許相同的預處理語句執行多次。這時使用以下程序來完成:sqlite3_bind()       sqlite3_reset()

int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); //sqlite3_bind_  後面跟 着的大多是綁定的數據類型,有二進制對象,整形等
int sqlite3_bind_double(sqlite3_stmt*, int, double); //所有的這些函數第二個參數表示綁定SQL語句中的第幾 個參數,
最左邊的SQL參數的索引爲1
int sqlite3_bind_int(sqlite3_stmt*, int, int);  //
第三個參數爲綁定到佔位符的值,即SQL參數的值
int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);  

int sqlite3_bind_null(sqlite3_stmt*, int);
int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*));
int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);//第四個參數爲參數的字節數(注意不是字符數),如 果爲負,則把參數當作字符串輸入

int sqlite3_reset(sqlite3_stmt *pStmt);   //第一個參數是一個指向sqlite3_stmt對象的指針

         即sqlite3_bind_XXX()函數將對應的參數傳入,sqlite3_reset()來清除已經綁定的參數。當一個準備語句prepared statement)被執行通過一次或多次調用sqlite3_step ( ) ,它也可以調用sqlite3_reset ( )來重置。之所以調用sqlite3_reset()來重置而不是調用sqlite3_prepare()來重新創建,是因爲可以避免不必要的消耗。通常我們很少多次執行完全相同的SQL語句,更多的時候我們可能需要執行一個相似的語句,比如插入多條數據,執行的是相似的INSERT語句,只是其中包含的參數不同,這些參數可以在語句被執行之前綁定到一個變量上,我們只需要不斷的改變這個變量的值,然後執行相同的準備語句prepared statement)即可。

在SQLITE中可以使用以下幾種:
  ?    
    ?NNN  
    :AAA  
    $AAA  
    @AAA  
這些參數只是代表了一個佔位符,我們可以通過調用sqlite3_bind()來綁定具體的值到這個佔位符上。這幾個參數的具體用法與區別可以參考下面這個鏈接:點擊打開鏈接http://blog.csdn.net/klarclm/article/details/7527788


下面,通過一個實例代碼來演示它們的用法:還是上面那個圖中的數據
void Talk(int id)                           //根據ID號這個形參,查詢其IP爲多少
{
sqlite3 *mysqlite3;     //SQLite 連接對象
         int reopen;
         reopen = sqlite3_open("D:\\mysqlite\\mysqlite.db",&mysqlite3);
        if(reopen != SQLITE_OK )
        {
       cout<<"it failed to open mysqlite.db"<<endl;
        }else
       {
       cout<<"it success to open mysqlite.db"<<endl;
       }
        sqlite3_stmt *stmt;//prepare_statment 對象
        char *sql="select IP from userInfo where ID = @id"; //這裏用的是@AAA這個佔位符,也可以用其他的幾個                   
        sqlite3_prepare_v2(mysqlite3,sql,-1,&stmt,NULL);
        sqlite3_bind_int(stmt, 1, id);  //把id這個變量綁定到佔位符上,我們可以通過函數的形參把具體的值傳給id這個變量                 
        int restep = sqlite3_step(stmt);
        if(restep == SQLITE_ROW)    //查詢IP
         {
      char *IP= (char *)sqlite3_column_text(stmt,0);
       cout << IP<<endl;
                 }
        sqlite3_finalize(stmt);
        sqlite3_close(mysqlite3);
}


         sqlite3_reset()是來清除已經綁定的參數,比較簡單,這裏不多講它的用法了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章