目录
- 效果图
- 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:通常设置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函数是用来替换占位符的
下面是修改操作
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);
}