日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

c++:MFC中sqlite3的使用(附实际案例)

發(fā)布時間:2025/3/20 c/c++ 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c++:MFC中sqlite3的使用(附实际案例) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

MFC中sqlite3的使用

  • sqlite3介紹
  • sqlite3安裝
  • 常用API函數(shù)
    • 操作流程
    • 接口函數(shù)
      • 執(zhí)行sql語句函數(shù)
      • 回調(diào)函數(shù)
  • MFC中案例實踐
  • 控制臺實踐

sqlite3介紹

SQLite 是一個軟件庫,實現(xiàn)了自給自足的、無服務(wù)器的、零配置的、事務(wù)性的 SQL 數(shù)據(jù)庫引擎。SQLite 是在世界上最廣泛部署的 SQL 數(shù)據(jù)庫引擎。SQLite引擎不是個程序與之通信的獨立進程,而是連接到程序中成為它的一個主要部分。所以主要的通信協(xié)議是在編程語言內(nèi)的直接API調(diào)用。這在消耗總量、延遲時間和整體簡單性上有積極的作用。整個數(shù)據(jù)庫(定義、表、索引和數(shù)據(jù)本身)都在宿主主機上存儲在一個單一的文件中。它的簡單的設(shè)計是通過在開始一個事務(wù)的時候鎖定整個數(shù)據(jù)文件而完成的。

sqlite3安裝

查看我的另一篇文章:傳送鏈接:

常用API函數(shù)

sqlite提供的是一些C函數(shù)接口,你可以用這些函數(shù)操作數(shù)據(jù)庫。通過使用這些接口,傳遞一些標(biāo)準(zhǔn) sql 語句(以 char * 類型)給 sqlite 函數(shù),sqlite 就會為你操作數(shù)據(jù)庫。

sqlite 跟微軟的access一樣是文件型數(shù)據(jù)庫,就是說,一個數(shù)據(jù)庫就是一個文件,此數(shù)據(jù)庫里可以建立很多的表,可以建立索引、觸發(fā)器等等,但是,它實際上得到的就是一個文件。備份這個文件就備份了整個數(shù)據(jù)庫。

sqlite 不需要任何數(shù)據(jù)庫引擎,這意味著如果你需要 sqlite 來保存一些用戶數(shù)據(jù),不需要安裝數(shù)據(jù)庫,只需要對你需要使用的數(shù)據(jù)庫進行拷貝就行了。

數(shù)據(jù)庫定義、操作、查詢等操作;
DDL - 數(shù)據(jù)定義語言
CREATE 創(chuàng)建一個新的表,一個表的視圖,或者數(shù)據(jù)庫中的其他對象。
ALTER 修改數(shù)據(jù)庫中的某個已有的數(shù)據(jù)庫對象,比如一個表。
DROP 刪除整個表,或者表的視圖,或者數(shù)據(jù)庫中的其他對象。
DML - 數(shù)據(jù)操作語言

INSERT 創(chuàng)建一條記錄。
UPDATE 修改記錄。
DELETE 刪除記錄。
DQL - 數(shù)據(jù)查詢語言

SELECT 從一個或多個表中檢索某些記錄。

操作流程

  • 定義 sqlit3 *數(shù)據(jù)
  • sqlite 里最常用到的是 sqlite3 * 類型。從數(shù)據(jù)庫打開開始,sqlite就要為這個類型準(zhǔn)備好內(nèi)存,直到數(shù)據(jù)庫關(guān)閉,整個過程都需要用到這個類型。當(dāng)數(shù)據(jù)庫打開時開始,這個類型的變量就代表了你要操作的數(shù)據(jù)庫。

  • 打開數(shù)據(jù)庫
  • int sqlite3_open( 數(shù)據(jù)庫文件名, sqlite3 ** );
    用這個函數(shù)開始數(shù)據(jù)庫操作。需要傳入兩個參數(shù),一是數(shù)據(jù)庫文件名,比如:Database.db。
    文件名不需要一定存在,如果此文件不存在,sqlite 會自動建立它。如果它存在,就嘗試把它當(dāng)數(shù)據(jù)庫文件來打開。
    sqlite3 ** 參數(shù)即前面提到的關(guān)鍵數(shù)據(jù)結(jié)構(gòu)。這個結(jié)構(gòu)底層細節(jié)如何,你不要關(guān)它。

    函數(shù)返回值表示操作是否正確,如果是 SQLITE_OK 則表示操作正常。相關(guān)的返回值sqlite定義了一些宏。具體這些宏的含義可以參考 sqlite3.h 文件。里面有詳細定義(順便說一下,sqlite3 的代碼注釋率自稱是非常高的,實際上也的確很高。只要你會看英文,sqlite 可以讓你學(xué)到不少東西)。

  • 關(guān)閉數(shù)據(jù)庫
    int sqlite3_close(sqlite3 *);
    這個函數(shù)經(jīng)常和sqlite3_open成對使用,當(dāng)前面打開一個數(shù)據(jù)庫時這里一定要記得關(guān)閉;
    整個過程演示:
  • #include "sqlite3.h" int main( int , char** ) { sqlite3 * db = NULL; //聲明sqlite關(guān)鍵結(jié)構(gòu)指針int result; //打開數(shù)據(jù)庫 //需要傳入 db 這個指針的指針,因為 sqlite3_open 函數(shù)要為這個指針分配內(nèi)存,還要讓db指針指向這個內(nèi)存區(qū) result = sqlite3_open( “database.db”, &db ); if( result != SQLITE_OK ) { //數(shù)據(jù)庫打開失敗 return -1; } //數(shù)據(jù)庫操作代碼 //… //數(shù)據(jù)庫打開成功 //關(guān)閉數(shù)據(jù)庫 sqlite3_close( db ); return 0; }

    接口函數(shù)

    執(zhí)行sql語句函數(shù)

    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),當(dāng)這條語句執(zhí)行之后,sqlite3會去調(diào)用你提供的這個函數(shù)。
    第4個參數(shù)void * 是你所提供的指針,你可以傳遞任何一個指針參數(shù)到這里,這個參數(shù)最終會傳到回調(diào)函數(shù)里面,如果不需要傳遞指針給回調(diào)函數(shù),可以填NULL。
    第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)。

    而當(dāng)做 select 時,就要使用回調(diào),因為 sqlite3 把數(shù)據(jù)查出來,得通過回調(diào)告訴你查出了什么數(shù)據(jù)。

    回調(diào)函數(shù)

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

    typedef int (sqlite3_callback)(void,int,char**, char**);
    回調(diào)函數(shù)必須定義成上面這個函數(shù)的類型,每查到符合sql語句的結(jié)果就執(zhí)行一次回調(diào)函數(shù)。
    回調(diào)函數(shù)必須定義成上面這個函數(shù)的類型,每查到符合sql語句的結(jié)果就執(zhí)行一次回調(diào)函數(shù)。
    回調(diào)函數(shù)必須定義成上面這個函數(shù)的類型,每查到符合sql語句的結(jié)果就執(zhí)行一次回調(diào)函數(shù)。
    回調(diào)函數(shù)必須定義成上面這個函數(shù)的類型,每查到符合sql語句的結(jié)果就執(zhí)行一次回調(diào)函數(shù)。

    //sqlite3的回調(diào)函數(shù) //sqlite 每查到一條記錄,就調(diào)用一次這個回調(diào) int LoadMyInfo(void* para,intn_column,char** column_value,char** column_name);
    //para是你在sqlite3_exec 里傳入的void參數(shù)通過para參數(shù),你可以傳入一些特殊的指針(比如類指針、結(jié)構(gòu)指針),
    //然后在這里面強制轉(zhuǎn)換成對應(yīng)的類型(這里面是void類型,必須強制轉(zhuǎn)換成你的類型才可用)。
    //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)的,表示這個字段的字段名稱

    下面給個簡單的例子:

    //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ù)庫操作了。

    不適用回調(diào)函數(shù)查詢數(shù)據(jù)庫參考鏈接:https://www.cnblogs.com/ransn/p/8063962.html

    MFC中案例實踐

    MFC案例:

    //將wchar_t* 轉(zhuǎn)成char*的實現(xiàn)函數(shù)如下:char *w2c(char *pcstr, wchar_t *pwstr, size_t len){int nlength = wcslen(pwstr);//獲取轉(zhuǎn)換后的長度int nbytes = WideCharToMultiByte(0, // specify the code page used to perform the conversion0, // no special flags to handle unmapped characterspwstr, // wide character string to convertnlength, // the number of wide characters in that stringNULL, // no output buffer given, we just want to know how long it needs to be0,NULL, // no replacement character givenNULL); // we don't want to know if a character didn't make it through the translation// make sure the buffer is big enough for this, making it larger if necessaryif (nbytes > len) nbytes = len;// 通過以上得到的結(jié)果,轉(zhuǎn)換unicode 字符為ascii 字符WideCharToMultiByte(0, // specify the code page used to perform the conversion0, // no special flags to handle unmapped characterspwstr, // wide character string to convertnlength, // the number of wide characters in that stringpcstr, // put the output ascii characters at the end of the buffernbytes, // there is at least this much space thereNULL, // no replacement character givenNULL);return pcstr;}int callback(void* para, int ncount, char** col_value, char** col_name) {TRACE("total column is %d\n", ncount);TRACE("start>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>", ncount);for (int i = 0; i < ncount; i++){password = col_value[0];select_name = col_name[0];TRACE("col_name:%s----> clo_value:%s\n", col_name[i], col_value[i]);}return 0; }bool UserPermission::UserInformationSelect() {// TODO: 在此處添加實現(xiàn)代碼.sqlite3 * pDB = NULL;char* cErrMsg;int ret = sqlite3_open("test.db", &pDB);if (ret == SQLITE_OK){MessageBox(TEXT("test.db打開成功!"));}else{MessageBox(TEXT("test.db打開失敗!"));return false;}CString sqlcommand;CString test,current_username;GetDlgItem(IDC_EDIT1)->GetWindowText(test);int user_index;user_index = m_ctrlUserName.GetCurSel();switch (user_index){case 0:{current_username = "manager";break;}case 1:{current_username = "operater";break;}case 3:{current_username = "server";break;}default:break;}/*string strSql;strSql = "select * from userinfo";int res = sqlite3_exec(pDB, strSql.c_str(), callback, NULL, &cErrMsg);*/char sqlcommand1[1280];memset(sqlcommand1, 0, sizeof(sqlcommand1));sqlcommand.Format(_T("SELECT * FROM user where id = 1")) ;//strcpy(sqlcommand1, sqlcommand.GetBuffer(sqlcommand.GetLength()));w2c(sqlcommand1, sqlcommand.GetBuffer(), 1280);int res = sqlite3_exec(pDB, sqlcommand1, callback, NULL, &cErrMsg);if (res != SQLITE_OK){CString msg;msg.Format(_T("ret=%d\n sql=[%s]\n"), ret, sqlcommand);MessageBox(msg);MessageBox(TEXT("select fail:"));return false;}//delete[] sqlcommand1;sqlite3_close(pDB);return true; }

    控制臺實踐

    #include <iostream> using namespace std; #include "sqlite/sqlite3.h" int callback(void*,int,char**,char**); int main() {sqlite3* db;int nResult = sqlite3_open("test.db",&db);if (nResult != SQLITE_OK){cout<<"打開數(shù)據(jù)庫失敗:"<<sqlite3_errmsg(db)<<endl;return 0;}else{cout<<"數(shù)據(jù)庫打開成功"<<endl;}char* errmsg;nResult = sqlite3_exec(db,"create table fuck(id integer primary key autoincrement,name varchar(100))",NULL,NULL,&errmsg);if (nResult != SQLITE_OK){sqlite3_close(db);cout<<errmsg;sqlite3_free(errmsg);return 0;}string strSql;strSql+="begin;\n";for (int i=0;i<100;i++){strSql+="insert into fuck values(null,'heh');\n";}strSql+="commit;";//cout<<strSql<<endl;nResult = sqlite3_exec(db,strSql.c_str(),NULL,NULL,&errmsg);if (nResult != SQLITE_OK){sqlite3_close(db);cout<<errmsg<<endl;sqlite3_free(errmsg);return 0;}strSql = "select * from fuck";nResult = sqlite3_exec(db,strSql.c_str(),callback,NULL,&errmsg);if (nResult != SQLITE_OK){sqlite3_close(db);cout<<errmsg<<endl;sqlite3_free(errmsg);return 0;}sqlite3_close(db);return 0; }int callback(void* ,int nCount,char** pValue,char** pName) {string s;for(int i=0;i<nCount;i++){s+=pName[i];s+=":";s+=pValue[i];s+="\n";}cout<<s<<endl;return 0; }

    鏈接:

    MFC ListControl與SQLite系列
    MFC ListControl與SQLite(一)SQLite的使用
    MFC ListControl與SQLite(二)用C++讀SQLite
    MFC ListControl與SQLite(三)用C++增刪改查SQLite表格數(shù)據(jù)
    MFC ListControl與SQLite(四)List Control與SQLite結(jié)合實例

    原文鏈接:https://blog.csdn.net/shanbadizun/article/details/113535468

    總結(jié)

    以上是生活随笔為你收集整理的c++:MFC中sqlite3的使用(附实际案例)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。