MFC中sqlite3的使用

  • sqlite3介绍
  • sqlite3安装
  • 常用API函数
    • 操作流程
    • 接口函数
      • 执行sql语句函数
      • 回调函数
  • MFC中案例实践
  • 控制台实践

sqlite3介绍

SQLite 是一个软件库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。SQLite 是在世界上最广泛部署的 SQL 数据库引擎。SQLite引擎不是个程序与之通信的独立进程,而是连接到程序中成为它的一个主要部分。所以主要的通信协议是在编程语言内的直接API调用。这在消耗总量、延迟时间和整体简单性上有积极的作用。整个数据库(定义、表、索引和数据本身)都在宿主主机上存储在一个单一的文件中。它的简单的设计是通过在开始一个事务的时候锁定整个数据文件而完成的。

sqlite3安装

查看我的另一篇文章:传送链接:

常用API函数

sqlite提供的是一些C函数接口,你可以用这些函数操作数据库。通过使用这些接口,传递一些标准 sql 语句(以 char * 类型)给 sqlite 函数,sqlite 就会为你操作数据库。

sqlite 跟微软的access一样是文件型数据库,就是说,一个数据库就是一个文件,此数据库里可以建立很多的表,可以建立索引、触发器等等,但是,它实际上得到的就是一个文件。备份这个文件就备份了整个数据库。

sqlite 不需要任何数据库引擎,这意味着如果你需要 sqlite 来保存一些用户数据,不需要安装数据库,只需要对你需要使用的数据库进行拷贝就行了。

数据库定义、操作、查询等操作;
DDL - 数据定义语言
CREATE 创建一个新的表,一个表的视图,或者数据库中的其他对象。
ALTER 修改数据库中的某个已有的数据库对象,比如一个表。
DROP 删除整个表,或者表的视图,或者数据库中的其他对象。
DML - 数据操作语言

INSERT 创建一条记录。
UPDATE 修改记录。
DELETE 删除记录。
DQL - 数据查询语言

SELECT 从一个或多个表中检索某些记录。

操作流程

  1. 定义 sqlit3 *数据

sqlite 里最常用到的是 sqlite3 * 类型。从数据库打开开始,sqlite就要为这个类型准备好内存,直到数据库关闭,整个过程都需要用到这个类型。当数据库打开时开始,这个类型的变量就代表了你要操作的数据库。

  1. 打开数据库

int sqlite3_open( 数据库文件名, sqlite3 ** );
用这个函数开始数据库操作。需要传入两个参数,一是数据库文件名,比如:Database.db。
文件名不需要一定存在,如果此文件不存在,sqlite 会自动建立它。如果它存在,就尝试把它当数据库文件来打开。
sqlite3 ** 参数即前面提到的关键数据结构。这个结构底层细节如何,你不要关它。

函数返回值表示操作是否正确,如果是 SQLITE_OK 则表示操作正常。相关的返回值sqlite定义了一些宏。具体这些宏的含义可以参考 sqlite3.h 文件。里面有详细定义(顺便说一下,sqlite3 的代码注释率自称是非常高的,实际上也的确很高。只要你会看英文,sqlite 可以让你学到不少东西)。

  1. 关闭数据库
    int sqlite3_close(sqlite3 *);
    这个函数经常和sqlite3_open成对使用,当前面打开一个数据库时这里一定要记得关闭;
    整个过程演示:
 #include "sqlite3.h"
int main( int , char** )
{sqlite3 * db = NULL; //声明sqlite关键结构指针int result;
//打开数据库
//需要传入 db 这个指针的指针,因为 sqlite3_open 函数要为这个指针分配内存,还要让db指针指向这个内存区
result = sqlite3_open( “database.db”, &db );
if( result != SQLITE_OK )
{//数据库打开失败
return -1;
}
//数据库操作代码
//…
//数据库打开成功
//关闭数据库
sqlite3_close( db );
return 0;
}

接口函数

执行sql语句函数

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

这就是执行一条 sql 语句的函数。
第1个参数是前面open函数得到的指针。说了是关键数据结构。
第2个参数const char sql 是一条 sql 语句,以\0结尾。
第3个参数sqlite3_callback 是回调,当这条语句执行之后,sqlite3会去调用你提供的这个函数。
第4个参数void * 是你所提供的指针,你可以传递任何一个指针参数到这里,这个参数最终会传到回调函数里面,如果不需要传递指针给回调函数,可以填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**);
回调函数必须定义成上面这个函数的类型,每查到符合sql语句的结果就执行一次回调函数。
回调函数必须定义成上面这个函数的类型,每查到符合sql语句的结果就执行一次回调函数。
回调函数必须定义成上面这个函数的类型,每查到符合sql语句的结果就执行一次回调函数。
回调函数必须定义成上面这个函数的类型,每查到符合sql语句的结果就执行一次回调函数。

//sqlite3的回调函数 //sqlite 每查到一条记录,就调用一次这个回调 int LoadMyInfo(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是对应的,表示这个字段的字段名称

下面给个简单的例子:

//sqlite3的回调函数
// sqlite 每查到一条记录,就调用一次这个回调
int LoadMyInfo( void * para, int n_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( “c:\\Dcg_database.db”, &db );
if( result != SQLITE_OK )
{//数据库打开失败
return -1;
}//数据库操作代码
//创建一个测试表,表名叫 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( “创建表失败,错误码:%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 );
}
//开始查询数据库
result = sqlite3_exec( db, “select * from MyTable_1”, LoadMyInfo, NULL, errmsg );
//关闭数据库
sqlite3_close( db );
return 0;
}

通过上面的例子,应该可以知道如何打开一个数据库,如何做数据库基本操作。

有这些知识,基本上可以应付很多数据库操作了。

不适用回调函数查询数据库参考链接:https://www.cnblogs.com/ransn/p/8063962.html

MFC中案例实践

MFC案例:


//将wchar_t* 转成char*的实现函数如下:char *w2c(char *pcstr, wchar_t *pwstr, size_t len){int nlength = wcslen(pwstr);//获取转换后的长度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;// 通过以上得到的结果,转换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: 在此处添加实现代码.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<<"打开数据库失败:"<<sqlite3_errmsg(db)<<endl;return 0;}else{cout<<"数据库打开成功"<<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表格数据
MFC ListControl与SQLite(四)List Control与SQLite结合实例

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

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

  1. 0基础快速入门CSS技术栈(5)—图解详细阐述说透CSS的盒子模型(超级重要)、圆角边框、盒子阴影及相关重要的笔试题——css的核心中的核心(附详细案例源码解析过程)2021.01.07更新

    文章目录 1. 盒子模型(CSS重点) 1.1 看透网页布局的本质 1.2 盒子模型(Box Model) 1.3 盒子边框(border) 1.3.1 边框综合设置 1.3.2 example01 ...

  2. MFC中使用TAB Control控件

    2019独角兽企业重金招聘Python工程师标准>>> MFC中使用TAB Control控件 MFC中使用TAB Control控件(转) 假如我现在有个SDI程序,View是Fo ...

  3. MFC中使用Sqllite数据库

    1.今天已经10.24号了,最近一个半月一直忙其它的工作了,正好今天是程序员节,记录一下MFC中Sqllite数据库的使用,之前在QT中已经使用过Sqllite数据库了. 封装类: #pragma o ...

  4. MFC Windows 程序设计(三)-锦上添花(附源码)

    MFC Windows 程序设计(三)-锦上添花(附源码) 程序之美 所话说,爱美之心人皆有之,不管是对于男人,女人,还是小孩,都有对美的一种向往,美好的事物,给人一种动力,一种希望,一种期盼,一种留 ...

  5. MFC中快速应用OpenCV(转)

    转载链接:http://wiki.opencv.org.cn/index.php/MFC%E4%B8%AD%E5%BF%AB%E9%80%9F%E5%BA%94%E7%94%A8OpenCV 简介和缘 ...

  6. 如何在MFC中使用cout和printf,输出到控制台

    在MFC中使用cout和printf,输出到控制台   在GUI程序中使用printf函数以及cout函数的方法: #include <io.h> #include <fcntl.h ...

  7. vs2019 MFC 中 cannot open include file 'afxres.h' 问题解决方法

    vs2019 MFC 中 cannot open include file 'afxres.h' 问题解决方法 使用Everything查找afxres.h文件,如果没有everything的,可以到 ...

  8. MFC中制作一个似命令行的输入框

    在做一个MFC软件的时候有一个这样的需求,就是要有类似与AutoCad的命令输入框,如下图所示: 本着不重写已有功能的原则,在MFC中发掘了一圈,没发现有可用的现成控件,上网搜了一下,发现有人做过,但 ...

  9. MFC中的几个常用类——CWnd

    2019独角兽企业重金招聘Python工程师标准>>> 1 窗口类 1.1 概述 CObject └CCmdTarget └CWnd CWnd是MFC窗口类的 基类,提供了微软基础类 ...

最新文章

  1. 使用 jQuery 简化 Ajax 开发
  2. spring计算方圆300km内其它城市(附完整代码)
  3. iOS AVAudioPlayer和AVAudioPlayerDelegate-音频播放处理中断
  4. Newbe.Claptrap 0.10.2 发布,Blazor 演示
  5. windows系统OLLVM + NDK 混淆编译环境搭建
  6. 4.UiCollection API 详细介绍
  7. fate框架找不到 flow 命令
  8. 世粮署:马斯克、贝索斯等富豪应捐出部分资产缓解全球饥饿
  9. commit git 删除文件夹_从Git提交中删除文件
  10. 【编辑器】在VSCode中使用JetBrains Clion主题
  11. 2016年计算机一级excel试题及答案,2016年计算机一级试题加答案
  12. ubuntu下载安装nginx+nginx-rtmp-module
  13. Win10常用Win快捷键
  14. 广州地铁公厕(洗手间)和母婴室信息汇总
  15. 「硬见小百科」很全的二极管干货
  16. 「沙龙回顾」从技术演进角度看猫眼电影
  17. 第一性原理分子动力学(AIMD)结果分析教程
  18. JAVA版本8u171与8u172的区别
  19. 解决complex转int的问题
  20. COOC软件一款用于文献计量和知识图谱绘制的新软件

热门文章

  1. Error:Cannot build artifact ‘ssm:war exploded‘ because it is included into a circular dependency
  2. 蓝桥杯练习系统习题-算法提高2
  3. Activity的生命周期理解
  4. String类为什么是final
  5. 大数据算法:对5亿数据进行排序
  6. 请检查网站服务器是否正常.,网站访问不了?如何做自我检查?
  7. sm4 的s盒_SM4国密算法Java版
  8. python里的关键字有哪些_Python中的yield关键字做了什么?
  9. python爬虫基础教程115_Python解析网页源代码中的115网盘链接实例
  10. mysql列名可以用中文吗_用了这么久的MySQL,你知道它的存储引擎吗?