【QT小作】封装一个基本的操作sqlite的类

背景

在QT开发的过程中,经常会使用到本地库sqlite,在操作sqlite的时候需要写一些简单的sql语句。所以,就想着封装一个简单的操作sqlite的类,就可以避免重复写简单的sql语句了,也可以省下一点点的时间来摸鱼了,哈哈哈!

源码
.h文件
#ifndef SQLOPERATOR_H
#define SQLOPERATOR_H

#include <QSqlDatabase>
#include <QSqlQuery>
#include <QHash>
#include <QString>
#include <QVariant>

/**
 * @brief The SqlOperator class 数据库基本操作类
 * 目前是使用于Sqlite。
 */
class SqlOperator
{
public:
    SqlOperator();

public:
    /**
     * @brief open 打开数据库
     * @param dbName 数据库名
     * @param connectName 连接名
     * @return
     */
    bool open(const QString &dbName, const QString &connectName);

    /**
     * @brief close 关闭数据库
     */
    void close();

    /**
     * @brief getConnectName 获取连接名
     * @return
     */
    QString getConnectName() const;

    /**
     * @brief isExistTable 判断数据表是否存在
     * @param tableName 数据表名
     * @return
     */
    bool isExistTable(const QString &tableName);

    /**
     * @brief createTable 创建数据表
     * @param tableName 数据表名
     * @param fields 字段(字段名和类型,如{"name", "varchar(5)"})
     * @param pks 主键
     * @return
     */
    bool createTable(const QString &tableName, const QHash<QString, QString> &fields, const QList<QString> &pks);

    /**
     * @brief selectData 选择数据(适用于单表选择)
     * @param tableName 数据表名
     * @param fields 选择字段
     * @param data [OUT]数据(按fields的顺序)
     * @return
     */
    bool selectData(const QString &tableName, const QList<QString> &fields, QList<QVariantList> &data);

    /**
     * @brief selectData 选择数据(适用于单表选择)
     * @param tableName 数据表名
     * @param fields 选择字段
     * @param whereConditions where条件
     * @param data [OUT]数据(按fields的顺序)
     * @return
     */
    bool selectData(const QString &tableName, const QList<QString> &fields, const QHash<QString, QVariant> &whereConditions,
                    QList<QVariantList> &data);

    /**
     * @brief selectDataBySql 选择数据(通过sql查询, 多表联合查询)
     * @param sql select语句
     * @param fields 选择字段
     * @param data [OUT]数据(按fields的顺序)
     * @return
     */
    bool selectDataBySql(const QString &sql, const QList<QString> &fields, QList<QVariantList> &data);

    /**
     * @brief insertRowData 插入行数据
     * @param tableName 数据表名
     * @param fields 插入字段
     * @param data 插入数据(数据与字段的顺序需一致)
     * @return
     */
    bool insertRowData(const QString &tableName, const QList<QString> &fields, const QVariantList &data);

    /**
     * @brief insertRowsData 插入多行数据
     * @param tableName 数据表名
     * @param fields 字段
     * @param data 插入数据(数据与字段的顺序需一致)
     * @return
     */
    bool insertRowsData(const QString &tableName, const QList<QString> &fields, const QList<QVariantList> &data);

    /**
     * @brief updateData 更新数据
     * @param tableName 数据表名
     * @param data 更新的字段数据(字段名和值,如{"age", 27})
     * @param whereConditions where条件(字段名和值,如{"age", 27})
     * @return
     */
    bool updateData(const QString &tableName, const QHash<QString, QVariant> &data,
                    const QHash<QString, QVariant> &whereConditions);

    /**
     * @brief deleteData 删除数据
     * @param tableName 数据表名
     * @param whereConditions where条件(字段名和值,如{"age", 27})
     * @return
     */
    bool deleteData(const QString &tableName, const QHash<QString, QVariant> &whereConditions);

    /**
     * @brief exec 执行sql语句
     * @param sql sql语句
     * @return 执行结果
     */
    bool exec(const QString &sql);

    /**
     * @brief hasTransactions 是否支持事务
     * @return
     */
    bool hasTransactions();

    /**
     * @brief transaction 开启事务
     * @return
     */
    bool transaction();

    /**
     * @brief commit 事务提交
     * @return
     */
    bool commit();

    /**
     * @brief rollback 事务回滚
     * @return
     */
    bool rollback();

    /**
     * @brief size 记录数量(在执行select语句后,可用该函数获取select的大小)
     * @return
     */
    int size();

    /**
     * @brief getTableFieldsInfo 获取数据表字段
     * @param tableName 数据表名
     * @param fieldsName [OUT]字段
     * @return
     */
    bool getTableFieldsInfo(const QString &tableName, QList<QString> &fieldsName);

    /**
     * @brief lastQuerySql 获取最新一次执行的sql语句
     * @return
     */
    QString lastQuerySql();

    /**
     * @brief lastError 获取最新的错误信息
     * @return 错误信息
     */
    QString lastError() const;

private:
    /**
     * @brief checkTableInfo 校验数据表信息(数据表和字段是否存在)
     * @param tableName 数据表名
     * @param fields 字段
     * @return
     */
    bool checkTableInfo(const QString &tableName, const QList<QString> &fields);

protected:
    QSqlDatabase m_db;
    QString m_connectName;
    QSqlQuery m_query;
    QString m_lastError;
};

#endif // SQLOPERATOR_H

.cpp文件
#include "sqloperator.h"
#include <QSqlError>
#include <QSqlDriver>

SqlOperator::SqlOperator()
{

}

bool SqlOperator::open(const QString &dbName, const QString &connectName)
{
    if (QSqlDatabase::connectionNames().contains(connectName)) {
        m_db = QSqlDatabase::database(connectName);
    } else {
        m_db = QSqlDatabase::addDatabase("QSQLITE", connectName);
    }

    m_connectName = connectName;

    if (m_db.isOpen()) {
        m_db.close();
    }

    m_db.setDatabaseName(dbName);
    if (m_db.open()) {
        m_query = QSqlQuery(m_db);
        return true;
    }

    m_lastError = m_db.lastError().text();
    return false;
}

void SqlOperator::close()
{
    m_db.close();
}

QString SqlOperator::getConnectName() const
{
    return m_connectName;
}

bool SqlOperator::isExistTable(const QString &tableName)
{
    return m_db.tables().contains(tableName);
}

bool SqlOperator::createTable(const QString &tableName, const QHash<QString, QString> &fields, const QList<QString> &pks)
{
    if (isExistTable(tableName)) {
        m_lastError = QString("Table [%1] is already exist").arg(tableName);
        return false;
    }

    QString sql = QString("create table %1 (").arg(tableName);
    for (auto iter = fields.begin(); iter != fields.end(); ++iter) {
        sql.append(QString("%1 %2, ").arg(iter.key(), iter.value()));
    }

    sql.append(QString("primary key ("));
    for (const auto &item : pks) {
        sql.append(QString("%1, ").arg(item));
    }

    sql.remove(sql.length() - 2, 2);
    sql.append("))");

    if (m_query.exec(sql)) {
        return true;
    }

    m_lastError = m_query.lastError().text();
    return false;
}

bool SqlOperator::selectData(const QString &tableName, const QList<QString> &fields, QList<QVariantList> &data)
{
    if (!checkTableInfo(tableName, fields)) {
        return false;
    }

    QString sql = QString("select ");
    for (const auto &item : fields) {
        sql.append(QString("%1, ").arg(item));
    }
    sql.remove(sql.length() - 2, 2);
    sql.append(QString(" from %1").arg(tableName));

    if (m_query.exec(sql)) {
        while (m_query.next()) {
            QVariantList temp;
            for (const auto &item : fields) {
                temp.append(m_query.value(item));
            }
            data.append(temp);
        }
        return true;
    }

    m_lastError = m_query.lastError().text();
    return false;
}

bool SqlOperator::selectData(const QString &tableName, const QList<QString> &fields,
                             const QHash<QString, QVariant> &whereConditions, QList<QVariantList> &data)
{
    QList<QString> tempFields;
    tempFields.append(fields);
    tempFields.append(whereConditions.keys());
    if (!checkTableInfo(tableName, tempFields)) {
        return false;
    }

    QString sql = QString("select ");
    for (const auto &item : fields) {
        sql.append(QString("%1, ").arg(item));
    }
    sql.remove(sql.length() - 2, 2);
    sql.append(QString(" from %1").arg(tableName));

    sql.append(QString(" where "));
    for (auto iter = whereConditions.begin(); iter != whereConditions.end(); ++iter) {
        sql.append(QString("%1 = ? and ").arg(iter.key()));
    }
    sql.remove(sql.length() - 5, 5);

    m_query.prepare(sql);
    for (auto iter = whereConditions.begin(); iter != whereConditions.end(); ++iter) {
        m_query.addBindValue(iter.value());
    }

    if (m_query.exec()) {
        while (m_query.next()) {
            QVariantList temp;
            for (const auto &item : fields) {
                temp.append(m_query.value(item));
            }
            data.append(temp);
        }
        return true;
    }

    m_lastError = m_query.lastError().text();
    return false;
}

bool SqlOperator::selectDataBySql(const QString &sql, const QList<QString> &fields, QList<QVariantList> &data)
{
    if (m_query.exec(sql)) {
        while (m_query.next()) {
            QVariantList temp;
            for (const auto &item : fields) {
                temp.append(m_query.value(item));
            }
            data.append(temp);
        }
        return true;
    }

    m_lastError = m_query.lastError().text();
    return false;
}

bool SqlOperator::insertRowData(const QString &tableName, const QList<QString> &fields, const QVariantList &data)
{
    if (!checkTableInfo(tableName, fields)) {
        return false;
    }

    QString sql = QString("insert into %1(").arg(tableName);
    for (const auto &item : fields) {
        sql.append(QString("%1, ").arg(item));
    }
    sql.remove(sql.length() - 2, 2);
    sql.append(QString(") values"));

    QString tempValue = QString("(");
    for (int i = 0; i < fields.count(); ++i) {
        tempValue.append(QString("?, "));
    }
    tempValue.remove(tempValue.length() - 2, 2);
    tempValue.append(QString(")"));

    sql.append(tempValue);

    m_query.prepare(sql);

    for (int i = 0; i < fields.count(); ++i) {
        m_query.addBindValue(data.at(i));
    }


    if (m_query.exec()) {
        return true;
    }

    m_lastError = m_query.lastError().text();
    return false;
}

bool SqlOperator::insertRowsData(const QString &tableName, const QList<QString> &fields, const QList<QVariantList> &data)
{
    if (!checkTableInfo(tableName, fields)) {
        return false;
    }

    QString sql = QString("insert into %1(").arg(tableName);
    for (const auto &item : fields) {
        sql.append(QString("%1, ").arg(item));
    }
    sql.remove(sql.length() - 2, 2);
    sql.append(QString(") values"));

    QString tempValue = QString("(");
    for (int i = 0; i < fields.count(); ++i) {
        tempValue.append(QString("?, "));
    }
    tempValue.remove(tempValue.length() - 2, 2);
    tempValue.append(QString(")"));

    for (int i = 0; i < data.count(); ++i) {
        sql.append(QString("%1, ").arg(tempValue));
    }
    sql.remove(sql.length() - 2, 2);

    m_query.prepare(sql);
    for (const auto &item : data) {
        for (int i = 0; i < fields.count(); ++i) {
            m_query.addBindValue(item.at(i));
        }
    }

    if (m_query.exec()) {
        return true;
    }

    m_lastError = m_query.lastError().text();
    return false;
}

bool SqlOperator::updateData(const QString &tableName, const QHash<QString, QVariant> &data,
                             const QHash<QString, QVariant> &whereConditions)
{
    QList<QString> fields;
    fields << data.keys() << whereConditions.keys();
    if (!checkTableInfo(tableName, fields)) {
        return false;
    }

    QString sql = QString("update %1 set ").arg(tableName);
    for (auto iter = data.begin(); iter != data.end(); ++iter) {
        sql.append(QString("%1 = ?, ").arg(iter.key()));
    }
    sql.remove(sql.length() - 2, 2);

    sql.append(" where ");
    for (auto iter = whereConditions.begin(); iter != whereConditions.end(); ++iter) {
        sql.append(QString("%1 = ? and ").arg(iter.key()));
    }
    sql.remove(sql.length() - 5, 5);

    m_query.prepare(sql);
    for (auto iter = data.begin(); iter != data.end(); ++iter) {
        m_query.addBindValue(iter.value());
    }
    for (auto iter = whereConditions.begin(); iter != whereConditions.end(); ++iter) {
        m_query.addBindValue(iter.value());
    }

    if (m_query.exec()) {
        return true;
    }

    m_lastError = m_query.lastError().text();
    return false;
}

bool SqlOperator::deleteData(const QString &tableName, const QHash<QString, QVariant> &whereConditions)
{
    QList<QString> fields = whereConditions.keys();
    if (!checkTableInfo(tableName, fields)) {
        return false;
    }

    QString sql = QString("delete from %1 where ").arg(tableName);
    for (auto iter = whereConditions.begin(); iter != whereConditions.end(); ++iter) {
        sql.append(QString("%1 = ? and ").arg(iter.key()));
    }
    sql.remove(sql.length() - 5, 5);

    m_query.prepare(sql);
    for (auto iter = whereConditions.begin(); iter != whereConditions.end(); ++iter) {
        m_query.addBindValue(iter.value());
    }

    if (m_query.exec()) {
        return true;
    }

    m_lastError = m_query.lastError().text();
    return false;
}

bool SqlOperator::exec(const QString &sql)
{
    if (m_query.exec(sql)) {
        return true;
    }

    m_lastError = m_query.lastError().text();
    return false;
}

bool SqlOperator::hasTransactions()
{
    if (m_query.driver()->hasFeature(QSqlDriver::Transactions)) {
        return true;
    }

    m_lastError = QString("This database don't support tasnsactions");
    return false;
}

bool SqlOperator::transaction()
{
    return m_db.transaction();
}

bool SqlOperator::commit()
{
    return m_db.commit();
}

bool SqlOperator::rollback()
{
    return m_db.rollback();
}

int SqlOperator::size()
{
    int count = -1;
    m_query.first();
    if (m_query.next()) {
        if (m_query.driver()->hasFeature(QSqlDriver::QuerySize)) {
            count = m_query.size();
        } else {
            m_query.last();
            // m_query.at()是返回当前记录的编号(从0开始),所以最后一条记录的编号 +1 就为记录数
            count = m_query.at() + 1;
        }
    }

    m_query.first();
    return count;
}

bool SqlOperator::getTableFieldsInfo(const QString &tableName, QList<QString> &fieldsName)
{
    QString sql = QString("PRAGMA table_info('%1')").arg(tableName);
    if (m_query.exec(sql)) {
        while (m_query.next()) {
            fieldsName.append(m_query.value(1).toString());
        }
        return true;
    }

    m_lastError = m_query.lastError().text();
    return false;
}

QString SqlOperator::lastQuerySql()
{
    return m_query.lastQuery();
}

QString SqlOperator::lastError() const
{
    return m_lastError;
}

bool SqlOperator::checkTableInfo(const QString &tableName, const QList<QString> &fields)
{
    if (!isExistTable(tableName)) {
        m_lastError = QString("Table [%1] is not exist").arg(tableName);
        return false;
    }

    QList<QString> fieldsName;
    QStringList noFieldsName;
    if (getTableFieldsInfo(tableName, fieldsName)) {
        for (const auto &item : fields) {
            if (!fieldsName.contains(item)) {
                noFieldsName << item;
            }
        }

        if (noFieldsName.count() > 0) {
            m_lastError = QString("Table [%1] have no fields [%2]").arg(tableName).arg(noFieldsName.join(','));
            return false;
        }
    } else {
        return false;
    }

    return true;
}

参考博客

https://qthub.blog.csdn.net/article/details/79650033

m_pDbProcPic = new CDBProcess("sqlserver"); m_pDbProc->openDB("mysvr", "mydb", "myusername", "mypwd"); m_pDbProcPic = new CDBProcess("mysql"); m_pDbProc->openDB("localhost", "mydb", "root", "password"); m_pDbProcPic = new CDBProcess("access"); m_pDbProc->openDB("", strMDB, "sa", "password"); m_pDbProcPic = new CDBProcess("sqlite"); m_pDbProcPic->openDB("", "mysqlitedb"); CDBProcess使用说明 构造函数: CDBProcess(const QString strType); 参数:为数据库型,不区分大小写,支持的型有 sqlite mysql access sqlserver 例: CDBProcess db("sqlite"); -------------------------------------------------- 打开数据库 bool openDB(const QString strSvrName, //服务器名 const QString strDBname, //数据库名 const QString strUserID="", //用户名 const QString strUserPwd=""); //密码 打开数据库成功,返回true,否则返回false 对于sqlite,只有strDBname有效,其它参数忽略,如db.openDB("", "mysqlite.db") 对于MS Access数据库,strSvrName为空,用户名默认为"sa",如db.openDB("", "myaccess.mdb"); 对MSAccess数据库,也可通过一个UDL文件,打开,如db.openDB("my.udl", ""); mysql和sqlserver,就是各个参数依次提供,如db.openDB("svr1", "mydb", "user1", "abcd"); ----------------------------------------------------- 关闭数据库,CDBProcess析构时,亦会自动关闭数据库 void closeDB(); //db.closeDB(); ------------------------------------------------------ 执行Sql语句 bool excuteSQL(const QString); ------------------------------------------------------- 打开记录集 bool openRecordsetBySql(const QString strSql, //Sql语句 int idx = -1); //记录集id,用于标识记录集,默认值为-1 例: db.openRecordsetBySql("SELECT * FROM TB1", 5); 打开一个记录集,标识号为5,后面操作这个记录集,也要提供这个标识号 -------------------------------------------------------- 关闭记录集 void closeRecordset(int idx = -1); 例: db.closeRecordset(5); 关闭之前打开的标识为5的记录集 ----------------------------------- 数据库是否处在打开状态 bool isOpen() const; ------------------------------------ 记录集游标是否在结尾,参数为记录集标识 bool recEOF(int idx = -1) const; 例:bool b = db.RecBOF(5); ------------------------------------ 记录集游标是否在第一条记录之前,参数为记录集标识 bool recBOF(int idx = -1) const; ---------------------------------------- 删除一个表 bool dropTable(const QString); --------------------------------------------- 读取标识为idx记录集的当前记录的各字段值,方法如示例: bool getFieldsValueFromRec(int idx, const char* szFldInfo, ...) const; int iSN; QString strName; double dHeight; QDateTime dt; QByteArray ba; db.getFieldsValueFromRec(5, //记录集id "sn%d", &iSN, //字段名加型 sn为字段名%d表示整型,&iSN传入指针,保存返回字段值 "name%s", &strName, //字段名加型 name为字段名%s表示字符串(QString) "height&f", &dHeight, //字段名加型 height为字段名%f表示小数(double) "birthday%t", &dt, //字段名加型 birthday为字段名%t表示时间(QDateTime) "photo%b", &ba, //字段名加型 photo为字段名%b表示二进制流(QByteArray) CDBProcess::szEnd); //结束标志,"|" 执行后,各字段值就保存在iSN, strName等变量中了。 参数:第一个参数为记录集id 后面可变参数,字段%型标识,用于保存返回值的指针, 型标识:%d-int %s-QString %f-double %t-QDateTime %b-QByteArray --------------------------------------------------------------------------- 向一个数据表中填加一条记录 bool addFieldsValueToTbl(const QString strTbl, const char* szFldInfo, ...); 参数:第一个参数strTbl,为表名 后面是可变参数,为"字段%型标识",值(或指针),注int,double型直接传值,其它传指针 例: db.addFieldsValueToTbl("TB1", //表名 "sn%d", iSN, //字段名加型 sn为字段名%d表示整型,iSN传入值 "name%s", &strName, //字段名加型 name为字段名%s表示字符串(QString), 传入QString变量指针 "height&f", dHeight, //字段名加型 height为字段名%f表示小数(double),dHeight传入值 "birthday%t", &dt, //字段名加型 birthday为字段名%t表示时间(QDateTime),传入指针 "photo%b", &ba, //字段名加型 photo为字段名%b表示二进制流(QByteArray),传入指针 CDBProcess::szEnd); //结束标志,"|" ----------------------------------------------------------- 修改表中符合WHERE子句条件的记录 bool updateTblFieldsValue(const QString strTbl, QString strWhere, const char * szFldInfo, ... ); strTbl表名 strWhere SQL WHERE子句,如"WHERE sn=20" const char * szFldInfo, ...可变参数,同addFieldsValueToTbl 例: db.updateTblFieldsValue("TB1", "WHERE sn=20", "height&f", dHeight, "photo%b", &ba, CDBProcess::szEnd); ---------------------------------------------------------------- 以下几个函数分别是获取记录数,和记录光标移动。参数为记录集标识 long getRecordCount(int idx = -1) const; bool moveFirst(int idx = -1) const; bool movePrevious(int idx = -1) const; bool moveNext(int idx = -1) const; bool moveLast(int idx = -1) const; bool moveTo(int n, int idx = -1) const; -------------------------------------------------------------------- 返回数据库名 QString getDbName() const; ------------------------ 以下几个函数未验证 bool execStoreProcOfArgList(int idx, const QString strStoreProc, const char* szFldsInfo, ...); bool exexProc(const QString strStoreProc, QString str1, QString& str2); bool transaction(); bool commit(); bool rollback();
以下是一个基于Qt操作SQLite数据库封装,可以实现将CSV文件导入到SQLite数据库中: ```cpp #include <QtSql> #include <QFile> class SqliteHelper { public: SqliteHelper(const QString& dbName) { db = QSqlDatabase::addDatabase("QSQLITE"); db.setDatabaseName(dbName); } bool open() { if (!db.open()) { return false; } return true; } bool execute(const QString& sql) { QSqlQuery query(db); if (!query.exec(sql)) { return false; } return true; } bool importCsv(const QString& tableName, const QString& csvFilePath) { QFile file(csvFilePath); if (!file.open(QIODevice::ReadOnly)) { return false; } QTextStream in(&file); QStringList fields; QString line = in.readLine(); fields = line.split(","); QString createSql = "CREATE TABLE " + tableName + " ("; for (int i = 0; i < fields.count(); i++) { createSql += fields.at(i) + " TEXT"; if (i != fields.count() - 1) { createSql += ","; } } createSql += ")"; if (!execute(createSql)) { return false; } QSqlQuery query(db); QString insertSql = "INSERT INTO " + tableName + " ("; for (int i = 0; i < fields.count(); i++) { insertSql += fields.at(i); if (i != fields.count() - 1) { insertSql += ","; } } insertSql += ") VALUES ("; for (int i = 0; i < fields.count(); i++) { insertSql += "?"; if (i != fields.count() - 1) { insertSql += ","; } } insertSql += ")"; while (!in.atEnd()) { line = in.readLine(); QStringList values = line.split(","); query.prepare(insertSql); for (int i = 0; i < values.count(); i++) { query.addBindValue(values.at(i)); } if (!query.exec()) { return false; } } return true; } private: QSqlDatabase db; }; ``` 使用该的示例代码如下: ```cpp SqliteHelper helper("test.db"); if (helper.open()) { if (helper.importCsv("my_table", "my_data.csv")) { qDebug() << "Import success!"; } else { qDebug() << "Import failed!"; } } else { qDebug() << "Open database failed!"; } ``` 其中,`test.db` 是数据库文件名,`my_table` 是将要创建的表名,`my_data.csv` 是CSV文件路径。 需要注意的是,上述代码中的CSV文件必须满足以下条件: - 文件第一行为表格字段名; - 文件中每行数据使用逗号分隔; - 文件编码为UTF-8。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值