目录
- 效果图
- list Contral 控件的简单使用
- 使用sqlite3
效果图
使用sqlite3完成简单的数据库操作。
list Contral 控件的简单使用
本章只介绍基本应用
添加表头:
语法:
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);
添加子项
语法:
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);
清空列表
DeleteAllItems();
这个函数没有参数,它会直接删除CListCtrl控件中的所有项目。
当调用这个函数后,列表视图将变为空的状态,之前所有插入的行都将被清除。
使用sqlite3
环境:vs2019
使用sqlite3主要是通过以下函数
语法:sqlite3_open
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
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
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
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:通常设置NULLint 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函数是用来替换占位符的
下面是修改操作
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);}