在《VS2019下Sqlite3数据库的环境搭建及简单应用》,这篇中描述了第三方sqlite3库的环境配置和简单使用,重新整理下操作类的逻辑;
其实就是增删改查。
基本功能实现如下:
// WSqlite.h #ifndef WSQLITE_H_ #define WSQLITE_H_ #include#include #include #include "sqlite3.h" #pragma comment(lib, "sqlite3.lib") using namespace std; class WSqlite { public: WSqlite(); ~WSqlite(); int CreateDbFile(const string &path); // 创建数据库文件 int CreateTable(const string& sqlCreatetable); // 创建数据库表 int Opendb(const string& path); // 连接数据库 int Insert(const string& sqlInsert); // 增 int Delete(const string& sqlDelete); // 删 int Update(const string& sqlUpdate); // 改 int QueryData(const string& sqlQuery, vector &arrKey, vector > &arrValue); // 查 private: sqlite3* pDb = NULL; private: //sqlie对象的销毁放在析构里,不需要用户关心 void Destory(); }; #endif
// WSqlite.cpp #include#include #include #include #include "sqlite3.h" #include "WSqlite.h" using namespace std; #pragma comment(lib, "sqlite3.lib") WSqlite::WSqlite(){ pDb = NULL; } WSqlite::~WSqlite(){ Destory(); } void WSqlite::Destory() { if (pDb) { sqlite3_close(pDb); pDb = NULL; } } int WSqlite::CreateDbFile(const string& path) { return sqlite3_open(path.c_str(), &pDb); } int WSqlite::CreateTable(const string& sqlCreatetable) { char* szMsg = NULL; return sqlite3_exec(pDb, sqlCreatetable.c_str(), NULL, NULL, &szMsg); } int WSqlite::Opendb(const string& path) { return sqlite3_open(path.c_str(), &pDb); } int WSqlite::Insert(const string& sqlInsert) { if (sqlInsert.empty()) { return -1; } char* zErrMsg = NULL; int ret = sqlite3_exec(pDb, sqlInsert.c_str(), NULL, NULL, &zErrMsg); if (zErrMsg) { sqlite3_free(zErrMsg); } return ret; } int WSqlite::Delete(const string& sqlDelete) { int nCols = 0; int nRows = 0; char** azResult = NULL; char* errMsg = NULL; int res = sqlite3_get_table(pDb, sqlDelete.c_str(), &azResult, &nRows, &nCols, &errMsg); if (res != SQLITE_OK) { return false; } if (azResult) { sqlite3_free_table(azResult); } if (errMsg) { sqlite3_free(errMsg); } return true; } int WSqlite::Update(const string& sqlUpdate) { char* zErrMsg = NULL; int ret = sqlite3_exec(pDb, sqlUpdate.c_str(), NULL, NULL, &zErrMsg); if (zErrMsg) { sqlite3_free(zErrMsg); } return ret; } int WSqlite::QueryData(const string& sqlQuery, vector & arrKey, vector >& arrValue) { if (sqlQuery.empty()) { return -1; } int nCols = -1; int nRows = -1; char** azResult = NULL; char* errMsg = NULL; int index = 0; const int ret = sqlite3_get_table(pDb, sqlQuery.c_str(), &azResult, &nRows, &nCols, &errMsg); index = nCols; arrKey.clear(); arrKey.reserve(nCols);// 改变容器容量,避免内存重新分配 arrValue.clear(); arrValue.reserve(nRows); bool bKeyCaptured = false; for (int i = 0; i < nRows; i++) { vector temp; for (int j = 0; j < nCols; j++) { if (!bKeyCaptured) { arrKey.push_back(azResult[j]); } temp.push_back(azResult[index]); index++; } bKeyCaptured = true; arrValue.push_back(temp); } if (azResult) { sqlite3_free_table(azResult); } if (errMsg) { sqlite3_free(errMsg); } return ret; }
dbName: run.db;
sheetName: myfriends;
| ID | Name | Age | Major |
|---|---|---|---|
| 1 | xiaohuoche | 9 | sing |
| 2 | xiaoshuai | 8 | dance |
| 3 | xiaomei | 7 | rap |
2.2.1 创建数据库文件和表格
void crteateTable() {
// 获取path
char buffer[MAX_PATH];
_getcwd(buffer, MAX_PATH);
string path = buffer;
path += "\run.db";
cout << path << endl;
// 创建db数据库文件
WSqlite sqlOperate;
int result = sqlOperate.CreateDbFile(path);
if (result != SQLITE_OK){
cout << "文件创建失败!" << endl;
}
else
{
// 创建数据库表
const char* sql = "create table myfriends(ID integer primary key autoincrement,Name string,Age integer,Major string)";
result = sqlOperate.CreateTable(sql);
if (result != SQLITE_OK)
{
cout << "表创建失败!" <
运行结果如下:

2.2.2 增
void test_addData() {
// 获取path
char buffer[MAX_PATH];
_getcwd(buffer, MAX_PATH);
string path = buffer;
path += "\run.db";
// 连接数据库
WSqlite sqlOperate;
int result = sqlOperate.Opendb(path);
if (result != SQLITE_OK)
{
cout<<"文件打开失败"<
运行结果如下:

2.2.3 删
void test_deleteData() {
// 获取path
char buffer[MAX_PATH];
_getcwd(buffer, MAX_PATH);
string path = buffer;
path += "\run.db";
// 连接数据库
WSqlite sqlOperate;
int result = sqlOperate.Opendb(path);
if (result != SQLITE_OK)
{
cout<<"文件打开失败"<
运行结果如下:

2.2.4 改
void test_updateData() {
// 获取path
char buffer[MAX_PATH];
_getcwd(buffer, MAX_PATH);
string path = buffer;
path += "\run.db";
// 连接数据库
WSqlite sqlOperate;
int result = sqlOperate.Opendb(path);
if (result != SQLITE_OK)
{
cout<<"文件打开失败"<
回撤删除动作之后,运行结果如下,小帅开始major in math了:

2.2.5 查
void test_queryData() {
// 获取path
char buffer[MAX_PATH];
_getcwd(buffer, MAX_PATH);
string path = buffer;
path += "\\run.db";
// 连接数据库
WSqlite sqlOperate;
int result = sqlOperate.Opendb(path);
if (result != SQLITE_OK)
{
cout<<"文件打开失败"< arrKey;
vector> arrValue;
result = sqlOperate.QueryData(strSQL, arrKey, arrValue);
if (result == SQLITE_OK && !arrKey.empty() && !arrValue.empty())
{
cout << "单行查询结果:\n";
for(int i1=0;i1
运行结果如下:

三、其他
3.1 关于查询sql语句Select带参数的用法
当我们执行形如"select * from sheetname "时的sql查询语句时,默认是从第一行开始检索整个数据库信息,有时为了特定需求,可以指定限制检索起始位置及检索数量;
select * from sheetname limit parameter1, parameter2
上述sql语句的含义是,从第param1行开始,读取接下来的param2行,parameter2可以是负数,为负时检索所有行;如上param1和param2是用","分割的,若是用OFFSET分割,则限制值是第一个数字,而偏移量(offset)是第二个数字 ,两种情况是反着的!
3.2 数据库路径包含中文
需要注意,SqLite只支持UTF-8编码格式,所以无法识别包含汉字的多字符集。
//多字符集转换为Unicode
WCHAR *CDB::mbcsToUnicode(const char *zFilename)
{
int nByte;
WCHAR *zMbcsFilename;
int codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
nByte = MultiByteToWideChar(codepage, 0, zFilename, -1, NULL,0)*sizeof(WCHAR);
zMbcsFilename = (WCHAR *)malloc(nByte*sizeof(zMbcsFilename[0]));
if( zMbcsFilename==0 )
{
return 0;
}
nByte = MultiByteToWideChar(codepage, 0, zFilename, -1, zMbcsFilename, nByte);
if(nByte == 0)
{
free(zMbcsFilename);
zMbcsFilename = 0;
}
return zMbcsFilename;
}
//Unicode转为UTF-8
char *CDB::unicodeToUtf8(const WCHAR *zWideFilename)
{
int nByte; char *zFilename;
nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0);
zFilename = (char *)malloc(nByte);
if(zFilename == 0)
{
return 0;
}
nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte, 0, 0);
if( nByte == 0 )
{
free(zFilename);
zFilename = 0;
}
return zFilename;
}
// 调用
WCHAR* wcPath;
wcPath = mbcsToUnicode(pathStr.c_str());//paths即为带有中文的全路径字符串
char* path = unicodeToUtf8(wcPath);
参考链接:
C++使用Sqlite
vector的reserve的使用(避免内存重新分配以及内存分配的方式)
Sqlite3查询指定行数数据
C++ 获取当前路径
MFC操作SQlite,打开数据库路径存在中文,解决方案