亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關(guān)于我們
? 蟲蟲下載站

?? zongjie(2.txt

?? sqlite 3.0使用方法
?? TXT
字號:
SQLITE3 使用總結(jié)

                   董淳光 42530 (老工號)

 dcg1981@163.com

                     2007年6月11日星期一

(2)              SQL語句操作
本節(jié)介紹如何用sqlite 執(zhí)行標準 sql 語法。

 

i.1            執(zhí)行sql語句

int sqlite3_exec(sqlite3*, const char *sql, sqlite3_callback, void *,  char **errmsg );

這就是執(zhí)行一條 sql 語句的函數(shù)。

第1個參數(shù)不再說了,是前面open函數(shù)得到的指針。說了是關(guān)鍵數(shù)據(jù)結(jié)構(gòu)。

第2個參數(shù)const char *sql 是一條 sql 語句,以\0結(jié)尾。

第3個參數(shù)sqlite3_callback 是回調(diào),當這條語句執(zhí)行之后,sqlite3會去調(diào)用你提供的這個函數(shù)。(什么是回調(diào)函數(shù),自己找別的資料學(xué)習(xí))

第4個參數(shù)void * 是你所提供的指針,你可以傳遞任何一個指針參數(shù)到這里,這個參數(shù)最終會傳到回調(diào)函數(shù)里面,如果不需要傳遞指針給回調(diào)函數(shù),可以填NULL。等下我們再看回調(diào)函數(shù)的寫法,以及這個參數(shù)的使用。

第5個參數(shù)char ** errmsg 是錯誤信息。注意是指針的指針。sqlite3里面有很多固定的錯誤信息。執(zhí)行 sqlite3_exec 之后,執(zhí)行失敗時可以查閱這個指針(直接 printf(“%s\n”,errmsg))得到一串字符串信息,這串信息告訴你錯在什么地方。sqlite3_exec函數(shù)通過修改你傳入的指針的指針,把你提供的指針指向錯誤提示信息,這樣sqlite3_exec函數(shù)外面就可以通過這個 char*得到具體錯誤提示。

說明:通常,sqlite3_callback 和它后面的 void * 這兩個位置都可以填 NULL。填NULL表示你不需要回調(diào)。比如你做 insert 操作,做 delete 操作,就沒有必要使用回調(diào)。而當你做 select 時,就要使用回調(diào),因為 sqlite3 把數(shù)據(jù)查出來,得通過回調(diào)告訴你查出了什么數(shù)據(jù)。

 

i.2            exec 的回調(diào)

typedef int (*sqlite3_callback)(void*,int,char**, char**);

你的回調(diào)函數(shù)必須定義成上面這個函數(shù)的類型。下面給個簡單的例子:

//sqlite3的回調(diào)函數(shù)         

// sqlite 每查到一條記錄,就調(diào)用一次這個回調(diào)

     int LoadMyInfo( void * para, int n_column, char ** column_value, char ** column_name )

{

          //para是你在 sqlite3_exec 里傳入的 void * 參數(shù)

          //通過para參數(shù),你可以傳入一些特殊的指針(比如類指針、結(jié)構(gòu)指針),然后在這里面強制轉(zhuǎn)換成對應(yīng)的類型(這里面是void*類型,必須強制轉(zhuǎn)換成你的類型才可用)。然后操作這些數(shù)據(jù)

          //n_column是這一條記錄有多少個字段 (即這條記錄有多少列)

          // char ** column_value 是個關(guān)鍵值,查出來的數(shù)據(jù)都保存在這里,它實際上是個1維數(shù)組(不要以為是2維數(shù)組),每一個元素都是一個 char * 值,是一個字段內(nèi)容(用字符串來表示,以\0結(jié)尾)

          //char ** column_name 跟 column_value是對應(yīng)的,表示這個字段的字段名稱

          

          //這里,我不使用 para 參數(shù)。忽略它的存在.

 

          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( “c:\\Dcg_database.db”, &db );

    if( result != SQLITE_OK )

    {

     //數(shù)據(jù)庫打開失敗

return -1;

}

//數(shù)據(jù)庫操作代碼

//創(chuàng)建一個測試表,表名叫 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 );

if(result != SQLITE_OK )

{

     printf( “創(chuàng)建表失敗,錯誤碼:%d,錯誤原因:%s\n”, result, errmsg );

}

//插入一些記錄

result = sqlite3_exec( db, “insert into MyTable_1( name ) values ( ‘走路’ )”, 0, 0, errmsg );

if(result != SQLITE_OK )

{

     printf( “插入記錄失敗,錯誤碼:%d,錯誤原因:%s\n”, result, errmsg );

}

result = sqlite3_exec( db, “insert into MyTable_1( name ) values ( ‘騎單車’ )”, 0, 0, errmsg );

if(result != SQLITE_OK )

{

     printf( “插入記錄失敗,錯誤碼:%d,錯誤原因:%s\n”, result, errmsg );

}

result = sqlite3_exec( db, “insert into MyTable_1( name ) values ( ‘坐汽車’ )”, 0, 0, errmsg );

if(result != SQLITE_OK )

{

     printf( “插入記錄失敗,錯誤碼:%d,錯誤原因:%s\n”, result, errmsg );

}

 

 

//開始查詢數(shù)據(jù)庫

result = sqlite3_exec( db, “select * from MyTable_1”, LoadMyInfo, NULL, errmsg );

 

//關(guān)閉數(shù)據(jù)庫

sqlite3_close( db );

return 0;

}

 

通過上面的例子,應(yīng)該可以知道如何打開一個數(shù)據(jù)庫,如何做數(shù)據(jù)庫基本操作。

有這些知識,基本上可以應(yīng)付很多數(shù)據(jù)庫操作了。

 

i.3            不使用回調(diào)查詢數(shù)據(jù)庫

上面介紹的 sqlite3_exec 是使用回調(diào)來執(zhí)行 select 操作。還有一個方法可以直接查詢而不需要回調(diào)。但是,我個人感覺還是回調(diào)好,因為代碼可以更加整齊,只不過用回調(diào)很麻煩,你得聲明一個函數(shù),如果這個函數(shù)是類成員函數(shù),你還不得不把它聲明成 static 的(要問為什么?這又是C++基礎(chǔ)了。C++成員函數(shù)實際上隱藏了一個參數(shù):this,C++調(diào)用類的成員函數(shù)的時候,隱含把類指針當成函數(shù)的第一個參數(shù)傳遞進去。結(jié)果,這造成跟前面說的 sqlite 回調(diào)函數(shù)的參數(shù)不相符。只有當把成員函數(shù)聲明成 static 時,它才沒有多余的隱含的this參數(shù))。

雖然回調(diào)顯得代碼整齊,但有時候你還是想要非回調(diào)的 select 查詢。這可以通過 sqlite3_get_table 函數(shù)做到。

int sqlite3_get_table(sqlite3*, const char *sql, char ***resultp, int *nrow, int *ncolumn, char **errmsg );

第1個參數(shù)不再多說,看前面的例子。

第2個參數(shù)是 sql 語句,跟 sqlite3_exec 里的 sql 是一樣的。是一個很普通的以\0結(jié)尾的char *字符串。

第3個參數(shù)是查詢結(jié)果,它依然一維數(shù)組(不要以為是二維數(shù)組,更不要以為是三維數(shù)組)。它內(nèi)存布局是:第一行是字段名稱,后面是緊接著是每個字段的值。下面用例子來說事。

第4個參數(shù)是查詢出多少條記錄(即查出多少行)。

第5個參數(shù)是多少個字段(多少列)。

第6個參數(shù)是錯誤信息,跟前面一樣,這里不多說了。

下面給個簡單例子:

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( “c:\\Dcg_database.db”, &db );

    if( result != SQLITE_OK )

    {

     //數(shù)據(jù)庫打開失敗

return -1;

}

//數(shù)據(jù)庫操作代碼

//假設(shè)前面已經(jīng)創(chuàng)建了 MyTable_1 表

//開始查詢,傳入的 dbResult 已經(jīng)是 char **,這里又加了一個 & 取地址符,傳遞進去的就成了 char ***

result = sqlite3_get_table( db, “select * from MyTable_1”, &dbResult, &nRow, &nColumn, &errmsg );

if( SQLITE_OK == result )

{

     //查詢成功

 

    index = nColumn; //前面說過 dbResult 前面第一行數(shù)據(jù)是字段名稱,從 nColumn 索引開始才是真正的數(shù)據(jù)

     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 的字段值是連續(xù)的,從第0索引到第 nColumn - 1索引都是字段名稱,從第 nColumn 索引開始,后面都是字段值,它把一個二維的表(傳統(tǒng)的行列表示法)用一個扁平的形式來表示

         }

         printf( “-------\n” );

     }

}

 

//到這里,不論數(shù)據(jù)庫查詢是否成功,都釋放 char** 查詢結(jié)果,使用 sqlite 提供的功能來釋放

sqlite3_free_table( dbResult );

 

//關(guān)閉數(shù)據(jù)庫

sqlite3_close( db );

return 0;

}

 

到這個例子為止,sqlite3 的常用用法都介紹完了。

用以上的方法,再配上 sql 語句,完全可以應(yīng)付絕大多數(shù)數(shù)據(jù)庫需求。

但有一種情況,用上面方法是無法實現(xiàn)的:需要insert、select 二進制。當需要處理二進制數(shù)據(jù)時,上面的方法就沒辦法做到。下面這一節(jié)說明如何插入二進制數(shù)據(jù)

(2)              操作二進制
sqlite 操作二進制數(shù)據(jù)需要用一個輔助的數(shù)據(jù)類型:sqlite3_stmt * 。

這個數(shù)據(jù)類型記錄了一個“sql語句”。為什么我把 “sql語句” 用雙引號引起來?因為你可以把 sqlite3_stmt * 所表示的內(nèi)容看成是 sql語句,但是實際上它不是我們所熟知的sql語句。它是一個已經(jīng)把sql語句解析了的、用sqlite自己標記記錄的內(nèi)部數(shù)據(jù)結(jié)構(gòu)。

正因為這個結(jié)構(gòu)已經(jīng)被解析了,所以你可以往這個語句里插入二進制數(shù)據(jù)。當然,把二進制數(shù)據(jù)插到 sqlite3_stmt 結(jié)構(gòu)里可不能直接 memcpy ,也不能像 std::string 那樣用 + 號。必須用 sqlite 提供的函數(shù)來插入。

 

i.1          寫入二進制

下面說寫二進制的步驟。

要插入二進制,前提是這個表的字段的類型是 blob 類型。我假設(shè)有這么一張表:

create table Tbl_2( ID integer, file_content  blob )

首先聲明 

sqlite3_stmt * stat;

然后,把一個 sql 語句解析到 stat 結(jié)構(gòu)里去:

sqlite3_prepare( db, “insert into Tbl_2( ID, file_content) values( 10, ? )”, -1, &stat, 0 );

上面的函數(shù)完成 sql 語句的解析。第一個參數(shù)跟前面一樣,是個 sqlite3 * 類型變量,第二個參數(shù)是一個 sql 語句。

這個 sql 語句特別之處在于 values 里面有個 ? 號。在sqlite3_prepare函數(shù)里,?號表示一個未定的值,它的值等下才插入。

第三個參數(shù)我寫的是-1,這個參數(shù)含義是前面 sql 語句的長度。如果小于0,sqlite會自動計算它的長度(把sql語句當成以\0結(jié)尾的字符串)。

第四個參數(shù)是 sqlite3_stmt 的指針的指針。解析以后的sql語句就放在這個結(jié)構(gòu)里。

第五個參數(shù)我也不知道是干什么的。為0就可以了。

如果這個函數(shù)執(zhí)行成功(返回值是 SQLITE_OK 且 stat 不為NULL ),那么下面就可以開始插入二進制數(shù)據(jù)。

sqlite3_bind_blob( stat, 1, pdata, (int)(length_of_data_in_bytes), NULL ); // pdata為數(shù)據(jù)緩沖區(qū),length_of_data_in_bytes為數(shù)據(jù)大小,以字節(jié)為單位

這個函數(shù)一共有5個參數(shù)。

第1個參數(shù):是前面prepare得到的 sqlite3_stmt * 類型變量。

第2個參數(shù):?號的索引。前面prepare的sql語句里有一個?號,假如有多個?號怎么插入?方法就是改變 bind_blob 函數(shù)第2個參數(shù)。這個參數(shù)我寫1,表示這里插入的值要替換 stat 的第一個?號(這里的索引從1開始計數(shù),而非從0開始)。如果你有多個?號,就寫多個 bind_blob 語句,并改變它們的第2個參數(shù)就替換到不同的?號。如果有?號沒有替換,sqlite為它取值null。

第3個參數(shù):二進制數(shù)據(jù)起始指針。

第4個參數(shù):二進制數(shù)據(jù)的長度,以字節(jié)為單位。

第5個參數(shù):是個析夠回調(diào)函數(shù),告訴sqlite當把數(shù)據(jù)處理完后調(diào)用此函數(shù)來析夠你的數(shù)據(jù)。這個參數(shù)我還沒有使用過,因此理解也不深刻。但是一般都填NULL,需要釋放的內(nèi)存自己用代碼來釋放。

bind完了之后,二進制數(shù)據(jù)就進入了你的“sql語句”里了。你現(xiàn)在可以把它保存到數(shù)據(jù)庫里:

int result = sqlite3_step( stat );

通過這個語句,stat 表示的sql語句就被寫到了數(shù)據(jù)庫里。

最后,要把 sqlite3_stmt 結(jié)構(gòu)給釋放:

sqlite3_finalize( stat ); //把剛才分配的內(nèi)容析構(gòu)掉

 

i.2          讀出二進制

下面說讀二進制的步驟。

跟前面一樣,先聲明 sqlite3_stmt * 類型變量:

sqlite3_stmt * stat;

然后,把一個 sql 語句解析到 stat 結(jié)構(gòu)里去:

sqlite3_prepare( db, “select * from Tbl_2”, -1, &stat, 0 );

當 prepare 成功之后(返回值是 SQLITE_OK ),開始查詢數(shù)據(jù)。

int result = sqlite3_step( stat );

這一句的返回值是 SQLITE_ROW 時表示成功(不是 SQLITE_OK )。

你可以循環(huán)執(zhí)行 sqlite3_step 函數(shù),一次 step 查詢出一條記錄。直到返回值不為 SQLITE_ROW 時表示查詢結(jié)束。

然后開始獲取第一個字段:ID 的值。ID是個整數(shù),用下面這個語句獲取它的值:

int id = sqlite3_column_int( stat, 0 ); //第2個參數(shù)表示獲取第幾個字段內(nèi)容,從0開始計算,因為我的表的ID字段是第一個字段,因此這里我填0

 

下面開始獲取 file_content 的值,因為 file_content 是二進制,因此我需要得到它的指針,還有它的長度:

         const void * pFileContent = sqlite3_column_blob( stat, 1 );

         int len = sqlite3_column_bytes( stat, 1 );

這樣就得到了二進制的值。

把 pFileContent 的內(nèi)容保存出來之后,不要忘了釋放 sqlite3_stmt 結(jié)構(gòu):

sqlite3_finalize( stat ); //把剛才分配的內(nèi)容析構(gòu)掉

 

i.3          重復(fù)使用 sqlite3_stmt 結(jié)構(gòu)

如果你需要重復(fù)使用 sqlite3_prepare 解析好的 sqlite3_stmt 結(jié)構(gòu),需要用函數(shù): sqlite3_reset。

result = sqlite3_reset(stat);

這樣, stat 結(jié)構(gòu)又成為 sqlite3_prepare 完成時的狀態(tài),你可以重新為它 bind 內(nèi)容。


?? 快捷鍵說明

復(fù)制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
在线一区二区三区四区| 欧美成人艳星乳罩| 成人高清av在线| 国产v综合v亚洲欧| 国产精品99久久久久久似苏梦涵| 激情偷乱视频一区二区三区| 蜜桃在线一区二区三区| 久久99国内精品| 国内精品伊人久久久久av一坑| 九九热在线视频观看这里只有精品| 美女国产一区二区| 国产又粗又猛又爽又黄91精品| 久草这里只有精品视频| 国产传媒欧美日韩成人| 成人一级片在线观看| av不卡在线播放| 欧洲亚洲国产日韩| 51精品国自产在线| 欧美大胆人体bbbb| 国产农村妇女精品| 亚洲人成亚洲人成在线观看图片| 亚洲人亚洲人成电影网站色| 一区二区成人在线视频| 偷拍一区二区三区四区| 久久99精品国产.久久久久| 高清不卡一区二区在线| 色综合一区二区| 91精品国产入口| 久久精品免视看| 亚洲欧美日本在线| 日本欧美韩国一区三区| 国产真实精品久久二三区| 波多野结衣91| 欧美日韩亚州综合| 欧美xfplay| 中日韩av电影| 婷婷国产在线综合| 国产乱一区二区| 欧美主播一区二区三区美女| 欧美一区二区大片| 国产精品麻豆网站| 日日夜夜精品视频免费| 国产不卡一区视频| 欧美性受xxxx| 久久久亚洲欧洲日产国码αv| 国产精品久久久久影院| 日韩av不卡一区二区| 成人性生交大片免费看中文网站| 在线观看日韩精品| 精品av久久707| 亚洲妇熟xx妇色黄| 国产不卡在线播放| 欧美一区二区黄色| 亚洲女人小视频在线观看| 麻豆91在线播放免费| 99国产精品国产精品毛片| 欧美一区二区在线免费播放| 国产精品久久久久久久久搜平片 | 精品少妇一区二区三区视频免付费| 欧美国产一区二区| 蜜臀av国产精品久久久久| 99精品视频在线播放观看| 亚洲一区二区三区小说| 国产在线精品视频| 91精品中文字幕一区二区三区 | 国产成+人+日韩+欧美+亚洲 | 亚洲一级片在线观看| 国产精品自拍av| 91精品视频网| 亚洲欧美日韩成人高清在线一区| 国产在线不卡一卡二卡三卡四卡| 欧美区在线观看| 亚洲欧美在线高清| 国产精品一区二区不卡| 日韩三级视频在线看| 亚洲精品国产第一综合99久久| 国产麻豆精品视频| 欧美一区二区三区日韩| 一区二区三区四区激情| 粉嫩绯色av一区二区在线观看| 欧美一区二区三区在线| 亚洲一区二区三区影院| 91麻豆.com| 亚洲欧美综合另类在线卡通| 国产91露脸合集magnet| 日韩一级二级三级| 同产精品九九九| 欧美探花视频资源| 一区二区三区小说| 91网页版在线| 国产精品网友自拍| 国产不卡在线视频| 国产欧美精品在线观看| 国产一区二区不卡| 精品国一区二区三区| 男女男精品网站| 制服.丝袜.亚洲.中文.综合| 亚洲小少妇裸体bbw| 欧洲生活片亚洲生活在线观看| 成人免费一区二区三区视频| 波多野结衣中文一区| 欧美国产日韩在线观看| 粉嫩嫩av羞羞动漫久久久| 2021国产精品久久精品| 久久黄色级2电影| 欧美r级电影在线观看| 韩国三级在线一区| 久久亚洲捆绑美女| 福利一区二区在线| 国产精品色哟哟| 91香蕉视频在线| 一区二区成人在线观看| 欧美色精品天天在线观看视频| 亚洲二区在线视频| 制服.丝袜.亚洲.另类.中文| 日本不卡一区二区三区| 日韩欧美久久久| 国产一区视频网站| 中文字幕人成不卡一区| 色综合久久久久| 亚洲成av人片| 日韩一区二区在线免费观看| 久久成人综合网| 国产精品美女一区二区在线观看| av电影天堂一区二区在线| 亚洲午夜久久久久久久久电影院| 欧美日韩在线一区二区| 奇米精品一区二区三区四区| 精品欧美黑人一区二区三区| 国产精品一区二区黑丝| 亚洲免费观看高清完整版在线观看熊| 色狠狠色狠狠综合| 日本最新不卡在线| 久久久久久综合| 91美女在线观看| 免费在线看成人av| www国产精品av| 91小视频在线| 蜜臀久久99精品久久久久宅男| 欧美精品一区二区三区一线天视频| 成人一区二区在线观看| 午夜精品aaa| 欧美国产日韩精品免费观看| 欧美午夜电影网| 国内成+人亚洲+欧美+综合在线| 国产精品女同一区二区三区| 欧洲激情一区二区| 国产一本一道久久香蕉| 亚洲一区影音先锋| 久久久久久一二三区| 在线观看免费一区| 国产成人综合网站| 亚洲成年人网站在线观看| 欧美成人r级一区二区三区| 不卡av电影在线播放| 日韩激情一区二区| 国产精品国产三级国产普通话99| 这里只有精品99re| 99国产精品国产精品毛片| 六月丁香综合在线视频| 亚洲最快最全在线视频| 久久久久久久久久久黄色 | 亚洲精品免费在线观看| 日韩一区二区三区电影| 色av综合在线| 国产成人在线观看| 免费观看成人鲁鲁鲁鲁鲁视频| 中文字幕日本不卡| 久久久国产精华| 欧美一区二区视频在线观看| 91免费国产在线观看| 精品一区免费av| 日韩va亚洲va欧美va久久| 亚洲免费视频成人| 中文字幕乱码一区二区免费| 日韩欧美一区二区免费| 色999日韩国产欧美一区二区| 麻豆成人免费电影| 性欧美疯狂xxxxbbbb| 亚洲男人的天堂一区二区| 久久久久久综合| 日韩午夜av一区| 欧美精选午夜久久久乱码6080| 91最新地址在线播放| 国产乱人伦偷精品视频不卡| 日本色综合中文字幕| 午夜电影一区二区三区| 亚洲精品视频在线观看网站| 久久久不卡影院| 久久蜜臀中文字幕| 精品少妇一区二区三区在线视频| 欧美另类videos死尸| 欧美性色黄大片| 欧美在线免费观看亚洲| 91免费国产视频网站| 成人av资源在线| 成人看片黄a免费看在线| 国产一区二区主播在线| 久99久精品视频免费观看| 久久精品国产亚洲一区二区三区|