【MFC】vs2019中使用sqlite3完成学生管理系统

目录

效果图

使用sqlite3完成简单的数据库操作。

list Contral 控件的简单使用

本章只介绍基本应用

	添加表头:

语法

cpp 复制代码
int InsertColumn(int nCol, LPCTSTR lpszColumnHeading, int nFormat = LVCFMT_LEFT, int nWidth = -1, int nSubItem = -1);

nCol:表示列
lpszColumnHeading:表示常量字符串指针
nFormat:表示样式,LVCFMT_LEFT(左对齐)
nWidth:列宽度
nSubItem:指定列对应的子项索引,默认值-1

使用:
//设置样式
m_listCtrl.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
m_listCtrl.InsertColumn(0, _T("学号"), LVCFMT_LEFT, 80);
m_listCtrl.InsertColumn(1, _T("姓名"), LVCFMT_LEFT, 80);
m_listCtrl.InsertColumn(2, _T("年龄"), LVCFMT_LEFT, 80);
m_listCtrl.InsertColumn(3, _T("成绩"), LVCFMT_LEFT, 80);
	添加子项

语法

cpp 复制代码
int InsertItem(int nItem, LPCTSTR lpszItem);
bool SetItemText(int nItem, int nSubItem, LPCTSTR lpszText);

nItem:索引 行,默认-1会插到末尾
nSubItem:索引 列
lpszItem:常量字符串指针

使用:
InsertItem(i, _T(""));
SetItemText(i, j, str);
	清空列表
cpp 复制代码
DeleteAllItems();
这个函数没有参数,它会直接删除CListCtrl控件中的所有项目。
当调用这个函数后,列表视图将变为空的状态,之前所有插入的行都将被清除。

使用sqlite3

环境:vs2019

使用sqlite3主要是通过以下函数

语法:sqlite3_open

cpp 复制代码
int sqlite3_open(const char *filename, sqlite3 **ppDb);

作用:打开或者创建一个数据库
filename: 路径 。如果不存在则创建数据库
ppDb: 指向sqlite3 类型指针的指针。创建成功后会指向一个sqlite3 对象,通过这个对象对数据库进行操作

使用:
	sqlite3* db=NULL;
	int rc = sqlite3_open("./db/text.db", &db);
	if (rc != SQLITE_OK)
	{
		AfxMessageBox(_T("链接数据库失败"));
		return;
	}

int sqlite3_close(sqlite3*);

作用:关闭数据库
使用:
	sqlite3_close(db);

语法:sqlite3_exec

cpp 复制代码
int sqlite3_exec(sqlite3 *db, const char *sql, 
	int (*callback)(void*, int, char**, char**), 
	void *arg, char **errmsg);

sql: 需要执行的sql语句

参数三: 回调函数,看这个回调函数的参数类型,不难猜出,这个函数
是用来处理查询语句(select)的结果的。如果不是查询语句,设置NULL即可

arg是sqlite3_exec函数的arg参数传递过来的值;
nCol是查询结果中的列数;
colVal是一个指向字符数组的指针,用于存储每一列的值;
colName是一个指向字符数组的指针,用于存储每一列的名称。

arg:这是一个void类型的指针,用于传递给回调函数的额外参数。

可以是任何类型的数据,通过这个参数可以在回调函数中获取外部传递进来的信息。
errmsg: 用来存储错误信息的,执行成功会被设置NULL,失败会有错误信息

使用:
	const std::string str = "CREATE TABLE IF NOT EXISTS Students("
				"id TEXT PRIMARY KEY,"
				"name TEXT,"
				"age INTEGER,"
				"grades REAL);";

	sqlite3_exec(db, str.c_str(), NULL, NULL, NULL);
	if (rc != SQLITE_OK) {
		AfxMessageBox(_T("创建表失败"));
		return;
	}

语法:sqlite3_get_table

cpp 复制代码
int sqlite3_get_table(sqlite3* db, const char* zSql, 
	char*** pazResult, int* pnRow, int* pnColumn, 
	char** pzErrmsg);
	
作用: 和sqlite3_exec的回调函数相似

pazResult: 存放的是查询后的结果集
pnRow: 行
pnColumn: 列

使用:
	char** mResult;//结果集
	int mRow;//行数
	int mCol;//列数
	int nResult = sqlite3_get_table(Cdb.db, sql, &mResult, &mRow, &mCol, NULL);
	int nIndex = mCol;
	if (nResult == SQLITE_OK)
	{
		for (int i = 0; i < mRow; i++)
		{
			m_listCtrl.InsertItem(i, _T(""));
			for (int j = 0; j < mCol; j++)
			{
				CString str;
				str = mResult[nIndex];

				if (!strcmp("id", mResult[j]))
				{
					m_listCtrl.SetItemText(i, j, str);
				}
				else if (!strcmp("name", mResult[j]))
				{
					m_listCtrl.SetItemText(i, j, str);
				}
				else if (!strcmp("age", mResult[j]))
				{
					m_listCtrl.SetItemText(i, j, str);
				}
				else if (!strcmp("grades", mResult[j]))
				{
					m_listCtrl.SetItemText(i, j, str);
				}
				nIndex++;
			}
		}

要深刻理解mResult 才可以理解代码

配套使用的还有
void sqlite3_free_table(char **result);
用来释放存储结果集的空间,防止内存泄漏

使用:
	sqlite3_free_table(mResult);

语法:sqlite3_prepare_v2

cpp 复制代码
int sqlite3_prepare_v2(sqlite3 *db, const char *zSql, int nByte, 
sqlite3_stmt **ppStmt, const char **pzTail);

nByte:表示sql字符的长度,通常设置-1,编辑器自动计算长度
ppStmt:这是一个指向sqlite3_stmt类型指针的指针。
用于存储预处理后的 SQL 语句对象。
在成功预处理 SQL 语句后,*ppStmt会指向一个有效的sqlite3_stmt对象,
这个对象在后续的sqlite3_step函数执行过程中会被使用。
pzTail:通常设置NULL


int sqlite3_step(sqlite3_stmt *pStmt);
返回值:SQLITE_DONE:表示非查询语句已经成功执行完毕。
例如,插入一条记录成功、更新或删除指定数据成功后,都会返回SQLITE_DONE。
SQLITE_ERROR:错误
SQLITE_NOMEM:内存不足
SQLITE_ROW:用于查询,当返回这个说明还没有执行完

配套使用的还有
int sqlite3_finalize(sqlite3_stmt *pStmt);
释放存放sql语句的内存

使用:
	sqlite3_stmt* stmt = NULL;        //stmt语句句柄
	int result = sqlite3_prepare_v2(Cdb.db, sql, -1, &stmt, NULL);
	if (result == SQLITE_OK)
	{
		int stepResult = sqlite3_step(stmt);
		if (stepResult == SQLITE_DONE)
		{
			AfxMessageBox(_T("删除成功"));
			OnBnClickedButton1();
		}
		else
		{
			AfxMessageBox(_T("执行 SQL 语句失败"));
		}
	}
	else
	{
		AfxMessageBox(_T("准备 SQL 语句失败"));
	}

	if (stmt != NULL)
	{
		sqlite3_finalize(stmt);
	}

SQLite 库中一个用于将 SQL 语句编译为字节码程序的函数,它是执行 SQL 语句(特别是那些带有参数或者需要更精细控制执行过程的语句)的重要前置步骤。通过这个函数,可以对 SQL 语句进行预处理,之后可以使用sqlite3_step函数来逐步执行预处理后的语句。这种方式比直接使用sqlite3_exec函数更灵活,适用于复杂的数据库操作,如带有参数绑定的插入、更新、删除操作以及需要逐行处理的查询操作等。
sqlite3_step,用于执行在sqlite3_prepare_v2中已经准备好的 SQL 语句的下一个步骤。对于查询语句,它会逐行获取结果;对于非查询语句(如插入、更新、删除),它会执行语句直到完成相应的操作。

语法:sqlite3_bind_text

再使用sqlite3_prepare_v2执行相对复杂的语句时,需要用到占位符

sqlite3_bind_text函数是用来替换占位符的

下面是修改操作

cpp 复制代码
	sqlite3_stmt* stmt = NULL;        //stmt语句句柄
	const char* str = "update Students set name = ?, age = ?,grades = ? where id=?;";
	int result = sqlite3_prepare_v2(Cdb.db, str, -1, &stmt, NULL);
	if (result == SQLITE_OK)
	{
		std::string id = (CT2A(m_strId));
		std::string name = (CT2A(m_strName));
		sqlite3_bind_text(stmt, 1, name.c_str(), -1, SQLITE_TRANSIENT);
		sqlite3_bind_int(stmt, 2, m_strAge);
		sqlite3_bind_double(stmt, 3, m_iGrades);
		sqlite3_bind_text(stmt, 4, id.c_str(), -1, SQLITE_TRANSIENT);
		int stepResult = sqlite3_step(stmt);
		if (stepResult == SQLITE_DONE)
		{
			AfxMessageBox(_T("修改成功"));
		}
		else
		{
			AfxMessageBox(_T("执行 SQL 语句失败"));
		}
	}
	else
	{
		AfxMessageBox(_T("准备 SQL 语句失败"));
	}

	if (stmt != NULL)
	{
		sqlite3_finalize(stmt);
	}
相关推荐
Android_chunhui24 分钟前
向量检索原理
c++·搜索引擎·全文检索
一行玩python44 分钟前
Xerces-C,一个成熟的 C++ XML 解析库!
xml·c语言·开发语言·c++
Octopus20772 小时前
【C++】AVL树
开发语言·c++·笔记·学习
荒古前2 小时前
小发现,如何高级的顺序输出,逆序输出整数的每一位(栈,队列)
数据结构·c++·算法
奶香臭豆腐2 小时前
C++ 泛编程 —— 函数模板(中)
开发语言·c++·学习
蜗牛hb2 小时前
C++是如何工作的?
开发语言·c++
Rossy Yan2 小时前
【数据结构——查找】顺序查找(头歌实践教学平台习题)【合集】
数据结构·c++·算法·查找
m0_748240543 小时前
WebView2教程(基于C++)【一】环境初始化
开发语言·c++
炸鸡配泡面3 小时前
12.10 C语言作业3
c语言·c++·算法
汝即来归4 小时前
什么是运算符重载?如何在 C++ 中进行运算符重载?运算符重载在面向对象编程中的好处是什么?
开发语言·c++