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

3 篇文章 0 订阅

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 conversion

		0,         // no special flags to handle unmapped characters

		pwstr,     // wide character string to convert

		nlength,   // the number of wide characters in that string

		NULL,      // no output buffer given, we just want to know how long it needs to be

		0,

		NULL,      // no replacement character given

		NULL);    // 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 necessary

	if (nbytes > len)   nbytes = len;

	// 通过以上得到的结果,转换unicode 字符为ascii 字符

	WideCharToMultiByte(0, // specify the code page used to perform the conversion

		0,         // no special flags to handle unmapped characters

		pwstr,   // wide character string to convert

		nlength,   // the number of wide characters in that string

		pcstr, // put the output ascii characters at the end of the buffer

		nbytes,                           // there is at least this much space there

		NULL,      // no replacement character given

		NULL);

	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

SQLite是一种嵌入式的关系型数据库管理系统,MFC是微软基于C++的图形用户界面开发框架。将SQLiteMFC结合使用可以实现在Windows操作系统下开发具有图形界面的应用程序,并通过SQLite来管理和操作数据。 SQLite作为一个轻量级的数据库系统,可以直接嵌入到应用程序,无需单独部署数据库服务器。它以一个独立的文件形式存储数据,支持标准的SQL语法,具备完整的事务支持和ACID特性,能够高效地处理大规模的数据,并且非常稳定可靠。同时,SQLite还提供了多种编程语言的接口,包括C/C++,方便开发人员使用MFC作为一个成熟的图形用户界面开发框架,提供了丰富的类库和功能,可用于开发Windows平台的桌面应用程序。通过MFC,开发人员可以方便地创建窗口、按钮、对话框等UI元素,并处理用户的输入和事件触发等操作。MFC还提供了数据存储和访问的类库,其包括了一些数据库操作相关的类。 将SQLiteMFC结合使用,可以在MFC应用程序嵌入SQLite数据库,通过MFC提供的类库操作数据库,实现数据的增删改查等功能。开发人员可以使用MFC创建带有图形界面的数据输入和显示界面,通过SQLite提供的SQL语句将数据存储到数据库,或者从数据库检索数据并在应用程序展示。同时,通过事务处理与ACID特性,确保数据的完整性和一致性。 总而言之,通过将SQLiteMFC结合使用,可以开发出功能完善、界面友好的Windows应用程序,实现方便的数据管理和操作。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

时间之里

好东西就应该拿出来大家共享

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值