
嘻道奇闻
- 文章199742
- 阅读14625734
MFC中使用C++操作SQLite数据库保存数据的详细步骤
各位刚入坑MFC的小伙伴们,是不是总觉得数据库操作像在迷宫里找出口?今天咱们就用人话唠唠怎么用C++玩转SQLite存数据。先问个扎心的问题:你写的程序关闭后,那些用户输入的重要数据是不是都像被黑洞吸走了?别慌,看完这篇包你存数据比存钱还稳当!
一、准备工具就像备年货
咱们得先整点家伙事儿。SQLite官网下个最新版的sqlite3.dll,这玩意儿就像数据库的发动机。重点来了!把下载的sqlite3.h、sqlite3.lib、sqlite3.dll三个文件分别扔到:
- 头文件放VS安装目录的VC\include文件夹
- lib文件放VC\lib文件夹
- dll文件放项目debug目录里
这时候可能有人要拍大腿:这配置也太麻烦了吧?其实就像装新游戏,把安装包放对位置就能启动。建议新手直接复制这三个文件到项目文件夹,保准编译器能找到。
二、连接数据库比连WiFi简单
打开VS新建个MFC对话框项目,先做件重要的事——在stdafx.h里加这句:
cpp复制#include "sqlite3.h" #pragma comment(lib, "sqlite3.lib")
这就好比给程序装上了数据库驱动。接着在按钮点击事件里写连接代码:
cpp复制sqlite3* db; int res = sqlite3_open("mydata.db", &db); if(res != SQLITE_OK) { MessageBox(_T("数据库连接失败!")); return; }
新手常见坑:数据库路径别写中文!有次我手贱用"测试数据.db"当文件名,结果程序直接罢工给你看。
三、建表就像搭积木
存数据得先有地方放对吧?咱们建个学生信息表练手:
cpp复制char* sql = "CREATE TABLE IF NOT EXISTS students(" "id INTEGER PRIMARY KEY AUTOINCREMENT," "name TEXT NOT NULL," "score REAL);"; char* errMsg = 0; res = sqlite3_exec(db, sql, 0, 0, &errMsg);
这里有几个重点:
- ??IF NOT EXISTS?? 防止重复建表报错
- ??AUTOINCREMENT?? 让ID自动增长
- ??TEXT和REAL?? 对应字符串和浮点数
有小白要问:为啥不用int存分数?因为可能有89.5这种带小数的情况啊!咱们得考虑实际情况。
四、存数据比发快递靠谱
最关键的插入操作来了!这里推荐用预处理语句,比直接拼接SQL语句安全十倍:
cpp复制sqlite3_stmt* stmt; const char* sql = "INSERT INTO students(name,score) VALUES(?,?);"; sqlite3_prepare_v2(db, sql, -1, &stmt, 0); // 绑定参数 CString strName = _T("张三"); double dScore = 88.5; sqlite3_bind_text(stmt, 1, CW2A(strName), -1, SQLITE_TRANSIENT); sqlite3_bind_double(stmt, 2, dScore); // 执行插入 res = sqlite3_step(stmt); if(res == SQLITE_DONE) { MessageBox(_T("存数据成功!")); } sqlite3_finalize(stmt);
注意这个问号占位符?就像快递单上的收件人信息栏,后面再填具体内容。这样做能防SQL注入攻击,比直接拼接字符串安全得多。
五、查数据比翻聊天记录容易
存进去的数据得能查出来才算数。咱们写个查询所有数据的例子:
cpp复制const char* sql = "SELECT * FROM students;"; sqlite3_stmt* stmt; sqlite3_prepare_v2(db, sql, -1, &stmt, 0); CString strResult; while(sqlite3_step(stmt) == SQLITE_ROW) { int id = sqlite3_column_int(stmt, 0); const char* name = (const char*)sqlite3_column_text(stmt, 1); double score = sqlite3_column_double(stmt, 2); strResult.Format(_T("学号:%d 姓名:%s 分数:%.1f\r\n"), id, CA2W(name), score); // 显示到列表框或文本框 } sqlite3_finalize(stmt);
新手容易栽跟头的地方:查完数据一定要调用sqlite3_finalize,不然内存泄漏能让你程序越跑越慢,最后直接卡成PPT。
六、避坑指南(血泪教训)
- 数据库操作完必须调用??sqlite3_close??,否则文件会被锁定打不开
- 多线程操作要加锁,建议新手先用单线程练手
- 遇到错误码别慌,用??sqlite3_errmsg(db)?? 能直接看到错误描述
- 重要数据记得定期备份,直接复制.db文件就行
有次我忘记关数据库连接,第二天发现程序启动就报错,最后发现是.db文件被锁住了。这教训值千金啊!
七、性能优化小妙招
当数据量超过1万条时,记得在插入前加上这两句:
cpp复制sqlite3_exec(db, "BEGIN TRANSACTION;", 0, 0, 0); // 批量插入操作... sqlite3_exec(db, "COMMIT TRANSACTION;", 0, 0, 0);
这样操作速度能提升几十倍!原理就像寄快递,把100个包裹打包一起寄,肯定比一个个寄快多了。
小编观点:新手刚开始建议先用SQLiteSpy这个可视化工具查看数据库,比纯代码调试直观十倍。记住,存数据就像存钱,既要存得进去,取得出来,更要保证安全。别总想着一步到位,先把基础操作玩溜了,再研究事务、触发器这些高级玩法更靠谱!