C++封装sqlite3库

#ifndef _SMART_DB_H
#define _SMART_DB_H

#include "sqlite3.h"
#include <string>
#include <iostream>
#include <vector>

/*
* function:封装的sqlite类,具备链接,查询,关闭功能
* des:sql用字符串拼接方式,会有sql注入的风险
*/
class SmartDB
{
public:

    SmartDB();

    /*
    * @function: 创建或打开数据库,如果数据库不存在,
    * 则数据库将被创建并打开,如果创建失败则设置失败标志
    * @param[in] fileName: 数据库文件的位置
    */
    SmartDB(const std::string &fileName);

    /*
    * @des: 析构函数, 释放资源,关闭数据库
    */
    ~SmartDB();

    /*
    * @function: 打开数据库
    * @param[in] fileName: 数据库文件的位置
    * @return bool: 成功打开数据库true, 否则false
    */
    bool Open(const std::string &fileName);

    /*
    * @function: 释放资源,关闭数据库
    * @return bool: 成功关闭数据库true, 否则false
    */
    bool Close();

    /*
    * @function: 得到最后一次错误码
    * @return int: 返回最近一次错误码
    */
    int GetLastErrorCode();

    /*
    * @function: 解析和保存sql语句
    * @des: 不许用拼接字符串,因为有sql注入的安全问题
    * @param[in] strSql: 需要执行的sql语句, 可能带占位符?
    * @return bool: 成功返回true, 否则false
    */
    bool Prepare(const std::string& strSql);

    /*
    * @function: 绑定SQL语句预编译时把一些参数使用占位符(这里是?号)来代替
    * @param[in] current: 占位符的索引
    * @param[in] strData: 占位符问号的具体内容
    */
    void BindValue(int current, const std::string &strData);


    /*
    * @function: 执行sql, 返回函数执行的一个值,执行简单的汇聚函数,如select cout(*), select max(*)等
    * @param[in] strSql: sql语句,有可能占位符"?"
    * @param[in] strArgs: 参数列表,用来填充占位符, 变参
    * @param[out] vecData: 查询出来的全部数据
    * @return int: 最近一次错误码
    */
    int ExecuteScalar(const std::string &strSql, std::vector<std::vector<std::string>>& vecData, const int num, const std::string strFirst, ...);

private:
    /*
    * @function: 将单行所有列数据插入vector中
    * @param[in] iCount: 单行列数
    * @param[out] vecData: 单行数据集
    */
    void InsertLine(std::vector<std::string>& vecData, const int& iCount);

    /*
    * @function: 关闭sqlite句柄
    * @return int: 返回最近一次错误码
    */
    int CloseDBHandle();

private:
    sqlite3 *m_dbHandle = NULL;         // sqlite3数据库句柄
    sqlite3_stmt *m_statement = NULL;   // 一条SQL语句的实例
    int m_code;                         // 记录最近一次的错误码
};

#endif
#include "smartdb.h"
#include <stdarg.h>

SmartDB::SmartDB()
{

}

/*
* @function: 创建或打开数据库,如果数据库不存在,
* 则数据库将被创建并打开,如果创建失败则设置失败标志
* @param[in] fileName: 数据库文件的位置
*/
SmartDB::SmartDB(const std::string &fileName)
{
    this->Open(fileName);
}

/*
* @des: 析构函数, 释放资源,关闭数据库
*/
SmartDB::~SmartDB()
{
    this->Close();
}

/*
* @function: 打开数据库
* @param[in] fileName: 数据库文件的位置
* @return bool: 成功打开数据库true, 否则false
*/
bool SmartDB::Open(const std::string &fileName)
{
    // 打开对应fileName的sqlie数据库
    this->m_code = sqlite3_open(fileName.data(), &m_dbHandle);
    return (SQLITE_OK == this->m_code);     // 是否正常打开
}

/*
* @function: 关闭sqlite句柄
* @return int: 返回最近一次错误码
*/
int SmartDB::CloseDBHandle()
{
    this->m_code = sqlite3_close(this->m_dbHandle);

    while (this->m_code == SQLITE_BUSY)     // 如果sqlite状态繁忙
    {
        this->m_code = SQLITE_OK;
        // 循环取得sql语句实例
        sqlite3_stmt *stmt = sqlite3_next_stmt(this->m_dbHandle, NULL);
        if (stmt == NULL)
        {
            break;
        }

        // 销毁sql语句实例,防止内存泄漏
        this->m_code = sqlite3_finalize(stmt);
        if (this->m_code == SQLITE_OK)          // 成功销毁
        {
            // 关闭sqlite句柄
            this->m_code = sqlite3_close(this->m_dbHandle);
        }
    }
    return this->m_code;
}

/*
* @function: 释放资源,关闭数据库
* @return bool: 成功关闭数据库true, 否则false
*/
bool SmartDB::Close()
{
    if (this->m_dbHandle == NULL)
    {
        return true;
    }

    sqlite3_finalize(this->m_statement);    // 销毁sql语句实例,防止内存泄漏
    this->m_code = this->CloseDBHandle();         // 关闭sqlite句柄
    this->m_statement = nullptr;
    this->m_dbHandle = nullptr;
    return (SQLITE_OK == this->m_code);     // 是否正常关闭
}

/*
* @function: 得到最后一次错误码
* @return int: 返回最近一次错误码
*/
int SmartDB::GetLastErrorCode()
{
    return this->m_code;
}


/*
* @function: 解析和保存sql语句
* @des: 不许用拼接字符串,因为有sql注入的安全问题
* @param[in] strSql: 需要执行的sql语句, 可能带占位符?
* @return bool: 成功返回true, 否则false
*/
bool SmartDB::Prepare(const std::string& strSql)
{
    // 执行sql脚本语句
    this->m_code = sqlite3_prepare_v2(this->m_dbHandle, strSql.data(), strlen(strSql.data()), &this->m_statement, NULL);
    if (m_code != SQLITE_OK)
    {
        return false;
    }
    return true;
}


/*
* @function: 绑定SQL语句预编译时把一些参数使用占位符(这里是?号)来代替
* @param[in] current: 占位符的索引
* @param[in] strData: 占位符问号的具体内容
*/
void SmartDB::BindValue(int current, const std::string &strData)
{
    // 绑定参数
    this->m_code = sqlite3_bind_text(this->m_statement, current, strData.data(), strlen(strData.data()), NULL);
}



/*
* @function: 执行sql, 返回函数执行的一个值,执行简单的汇聚函数,如select cout(*), select max(*)等
* @param[in] strSql: sql语句,有可能占位符"?"
* @param[in] strArgs: 参数列表,用来填充占位符, 变参
* @param[out] vecData: 查询出来的全部数据
* @return int: 最近一次错误码
*/
int SmartDB::ExecuteScalar(const std::string &strSql, std::vector<std::vector<std::string>>& vecData, const int num, const std::string strFirst, ...)
{
    // 准备执行sql脚本语句
    if (this->Prepare(strSql) == false)
    {
        return this->m_code;
    }
    
    if (num > 0) {
        int current = 1;
        BindValue(current, strFirst);
        if (this->m_code != SQLITE_OK)
        {
            return this->m_code;
        }

        // 绑定参数
        va_list ap;
        va_start(ap, strFirst);
        std::string strSrc = "";
        for (int i = 1; i < num; ++i)
        {
            current += 1;
            strSrc = va_arg(ap, const std::string);
            BindValue(current, strSrc);
            if (this->m_code != SQLITE_OK)
            {
                return this->m_code;
            }
        }
        va_end(ap);
    }
    

    // 获取列数
    int iCount = sqlite3_column_count(this->m_statement);
    
    while (true)
    {
        // 执行sql语句,获取每行的数据
        this->m_code = sqlite3_step(this->m_statement);          
        if (this->m_code == SQLITE_ROW)
        {
            // 插入每一列的值
            std::vector<std::string> vecTmp;
            this->InsertLine(vecTmp, iCount);
            vecData.push_back(vecTmp);
        }
        else if (this->m_code == SQLITE_DONE)    // 数据行都已经获取,跳出循环
        {
            break;
        }
        else       // 出错
        {
            break;
        }            
        
    }

    // 重置一个准备语句对象到它的初始状态,然后准备被重新执行
    sqlite3_reset(this->m_statement);

    return this->m_code;
}

/*
* @function: 将单行数据插入vector中
* @param[in] iCount: 单行列数
* @param[out] vecData: 单行数据集
*/
void SmartDB::InsertLine(std::vector<std::string>& vecData, const int& iCount)
{
    for (int i = 0; i < iCount; ++i)
    {
        // 这里需要先判断当前列的类型,列的类型不同,调用的api函数不同
        // 获取实际的数据值
        int coltype = sqlite3_column_type(this->m_statement, i);
        if (coltype == SQLITE_TEXT)
        {
            const char* val = (const char*)sqlite3_column_text(this->m_statement, i);
            vecData.push_back(std::string(val));
        }
        else if (coltype == SQLITE_NULL)
        {
            vecData.push_back(std::string(""));
        }
        std::cout << sqlite3_column_name(this->m_statement, i) << "\n";
    }
}

因为sqlite是utf-8编码,需要转码,vs

#include "smartdb.h"
#include <vector>
#include <stdio.h>
#include <windows.h>


void ConvertGBKToUtf8(std::string& amp, std::string strGBK)
{
    int len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)strGBK.c_str(), -1, NULL, 0);
    unsigned short * wszUtf8 = new unsigned short[len + 1];
    memset(wszUtf8, 0, len * 2 + 2);
    MultiByteToWideChar(CP_ACP, 0, (LPCSTR)strGBK.c_str(), -1, (LPWSTR)wszUtf8, len);
    len = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)wszUtf8, -1, NULL, 0, NULL, NULL);
    char *szUtf8 = new char[len + 1];
    memset(szUtf8, 0, len + 1);
    WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)wszUtf8, -1, szUtf8, len, NULL, NULL);
    //strGBK = szUtf8; 
    amp = szUtf8;
    delete[] szUtf8;
    delete[] wszUtf8;
}


void ConvertUtf8ToGBK(std::string&amp, std::string strUtf8)
{
    int len = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)strUtf8.c_str(), -1, NULL, 0);
    unsigned short * wszGBK = new unsigned short[len + 1];
    memset(wszGBK, 0, len * 2 + 2);
    MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)strUtf8.c_str(), -1, (LPWSTR)wszGBK, len);
    len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)wszGBK, -1, NULL, 0, NULL, NULL);
    char *szGBK = new char[len + 1];
    memset(szGBK, 0, len + 1);
    WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)wszGBK, -1, szGBK, len, NULL, NULL);
    //strUtf8 = szGBK; 
    amp = szGBK;
    delete[] szGBK;
    delete[] wszGBK;
}

int main()
{
    SmartDB dB;
    if (!dB.Open("FastFile.db"))
    {
        return 0;
    }

    std::string strSql = "select cn, funcname from typelanguage where funcname = ?;";
    ConvertGBKToUtf8(strSql, strSql);
    std::vector<std::vector<std::string>> vecDst;
    std::string str = "car_mode";
    ConvertGBKToUtf8(str, str);
    std::string str2 = "1";
    dB.ExecuteScalar(strSql, vecDst, 1, str);

    for (int i = 0; i < vecDst.size(); ++i)
    {
        for (int j = 0; j < vecDst[i].size(); ++j)
        {
            std::string strDst = "";
            ConvertUtf8ToGBK(strDst, vecDst[i][j]);
            std::cout << strDst << "\n";
        }
    }



    getchar();
}

 

  • 0
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQLite是一种轻型的嵌入式关系型数据,它不需要独立的服务器进程,以文件的形式存储数据,因此非常适合嵌入到其他应用程序中使用。在C++中,我们可以通过SQLite提供的C接口来操作SQLite数据,也可以通过封装SQLite的方式来简化操作。 下面是一个简单的C++封装SQLite3的示例: ```cpp #include <sqlite3.h> #include <string> class SQLiteDB { public: SQLiteDB(const std::string& dbPath) : dbPath_(dbPath), db_(nullptr) {} ~SQLiteDB() { close(); } bool open() { if (db_) { return true; } int result = sqlite3_open(dbPath_.c_str(), &db_); if (result != SQLITE_OK) { return false; } return true; } void close() { if (db_) { sqlite3_close(db_); db_ = nullptr; } } bool exec(const std::string& sql) { char* error = nullptr; int result = sqlite3_exec(db_, sql.c_str(), nullptr, nullptr, &error); if (result != SQLITE_OK) { sqlite3_free(error); return false; } return true; } private: std::string dbPath_; sqlite3* db_; }; ``` 以上代码定义了一个SQLiteDB类,它包含了打开和关闭数据的方法,以及执行SQL语句的方法。在构造函数中,我们需要传入数据文件的路径,通过sqlite3_open函数打开数据,如果打开失败则返回false。在析构函数中,我们需要关闭数据。在exec方法中,我们通过sqlite3_exec函数执行SQL语句,如果执行失败则返回false。 使用示例: ```cpp int main() { SQLiteDB db("test.db"); if (!db.open()) { return -1; } if (!db.exec("CREATE TABLE IF NOT EXISTS user (id INTEGER PRIMARY KEY, name TEXT)")) { return -1; } if (!db.exec("INSERT INTO user (name) VALUES ('Tom')")) { return -1; } db.close(); return 0; } ``` 以上代码创建了一个名为test.db的SQLite数据文件,并在其中创建了一个名为user的表,然后插入了一行数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值