QSqlDatabase的进一步封装(多线程支持+更加简单的操作)——同时支持MySQL, SQL Server和Sqlite

111 篇文章 9 订阅

    只要简单的实例化,然后通过query()就可以拿到QSqlQuery的实例化对象。

    还自带计时,一段时间不用可自动关闭,既保证效率也不占用无用资源。

      注:需要C++11的支持

.h

#ifndef __JasonQt_Database_h__  
#define __JasonQt_Database_h__  
  
// C++ lib import  
#include <functional>  
  
// Qt lib import  
#include <QtCore>  
#include <QtSql>  
  
#define PropertyDeclare(Type, Name, setName, ...)                   \  
    private:                                                        \  
    Type m_ ## Name __VA_ARGS__;                                    \  
    public:                                                         \  
    inline const Type &Name(void) const { return m_ ## Name; }      \  
    inline void setName(const Type &Name) { m_ ## Name = Name; }    \  
    private:  
  
namespace JasonQt_Database  
{  
  
enum DatabaseModeEnum{ DatabaseNameMode, DatabaseHostMode };  
  
enum QueryMode { QueryAutoMode, QueryMultiMode, QuerySingleMode };  
  
class DatabaseSettings  
{  
private:  
    PropertyDeclare(DatabaseModeEnum, databaseMode, setDatabaseMode)  
  
    PropertyDeclare(QString, databaseType, setDatabaseType)  
    PropertyDeclare(QString, connectionName, setConnectionName)  
  
    // File mode  
    PropertyDeclare(QString, nameModeName, setNameModeName)  
  
    // Host mode  
    PropertyDeclare(QString, hostModeHostName, setHostModeHostName)  
    PropertyDeclare(QString, hostModeDatabaseName, setHostModeDatabaseName)  
    PropertyDeclare(QString, hostModeUserName, setHostModeUserName)  
    PropertyDeclare(QString, hostModePassword, setHostModePassword)  
  
private:  
    DatabaseSettings(const DatabaseModeEnum &databastMode, const QString &databaseType, const QString &connectionName);  
  
public:  
    DatabaseSettings(const QString &databaseType, const QString &connectionName, const QString &nameModeName);  
  
    DatabaseSettings(const QString &databaseType, const QString &connectionName, const QString &hostModeHostName, const QString &hostModeDatabaseName, const QString &hostModeUserName, const QString &hostModePassword);  
};  
  
class ConnectSettings  
{  
private:  
    PropertyDeclare(int, maxOpenTime, setMaxOpenTime)  
    PropertyDeclare(QueryMode, queryMode, setQueryMode)  
    PropertyDeclare(int, minWaitTime, setMinWaitTime)  
  
public:  
    ConnectSettings(const int &maxOpenTime = 60 * 1000, const QueryMode &queryMode = QueryAutoMode, const int &minWaitTime = -1);  
};  
  
class Query  
{  
private:  
    QSqlQuery *m_query;  
    QMutex *m_mutex = NULL;  
  
public:  
    Query(QSqlDatabase &dataBase, QMutex *mutex = NULL);  
  
    Query(Query &&other);  
  
    ~Query(void);  
  
    inline QSqlQuery *operator->(void) { return m_query; }  
  
    inline QSqlQuery *operator*(void) { return m_query; }  
  
    QSqlQuery *takeQuery(void);  
  
    QMutex *takeMutex(void);  
};  
  
class ConnectNode: public QObject  
{  
     Q_OBJECT  
  
private:  
    QSqlDatabase *m_database = NULL;  
    QString m_connectionName;  
  
    DatabaseSettings m_dataBaseSettings;  
    ConnectSettings m_connectSettings;  
  
    QTimer *m_autoClose = NULL;  
    QMutex *m_mutex = NULL;  
  
public:  
    ConnectNode(const DatabaseSettings &dataBaseSettings, const ConnectSettings &connectSettings);  
  
    ~ConnectNode(void);  
  
public:  
    Query query(void);  
  
public slots:  
    bool addDataBase(void);  
  
    void removeDataBase(void);  
  
    bool open(void);  
  
    void close(void);  
  
signals:  
    void controlStartAutoClose(void);  
  
    void controlStopAutoClose(void);  
};  
  
class Control  
{  
private:  
    DatabaseSettings m_databaseSettings;  
    ConnectSettings m_connectSettings;  
  
    QMap<qint64, ConnectNode *> m_node;  
  
    QMutex m_mutex;  
    QTime *m_wait = NULL;  
  
public:  
    Control(const DatabaseSettings &databaseSettings, const ConnectSettings &connectSettings = ConnectSettings());  
  
    Control(const Control &) = delete;  
  
    ~Control(void);  
  
public:  
    void removeAll(void);  
  
    Query query(void);  
  
private:  
    void insert(const qint64 &key);  
};  
  
}  
  
#endif//__JasonQt_Database_h__  

.cpp

#include "JasonQt_Database.h"  
  
using namespace JasonQt_Database;  
  
// DatabaseSettings  
DatabaseSettings::DatabaseSettings(const DatabaseModeEnum &databastMode, const QString &databaseType, const QString &connectionName)  
{  
    m_databaseMode = databastMode;  
    m_databaseType = databaseType;  
    m_connectionName = connectionName;  
}  
  
DatabaseSettings::DatabaseSettings(const QString &databaseType, const QString &connectionName, const QString &nameModeName):  
    DatabaseSettings(DatabaseNameMode, databaseType, connectionName)  
{  
    m_nameModeName = nameModeName;  
}  
  
DatabaseSettings::DatabaseSettings(const QString &databaseType, const QString &connectionName, const QString &hostModeHostName, const QString &hostModeDatabaseName, const QString &hostModeUserName, const QString &hostModePassword):  
    DatabaseSettings(DatabaseHostMode, databaseType, connectionName)  
{  
    m_hostModeHostName = hostModeHostName;  
    m_hostModeDatabaseName = hostModeDatabaseName;  
    m_hostModeUserName = hostModeUserName;  
    m_hostModePassword = hostModePassword;  
}  
  
// ConnectSettings  
ConnectSettings::ConnectSettings(const int &maxOpenTime, const QueryMode &queryMode, const int &minWaitTime)  
{  
    m_maxOpenTime = maxOpenTime;  
    m_queryMode = queryMode;  
    m_minWaitTime = minWaitTime;  
}  
  
// Query  
Query::Query(QSqlDatabase &dataBase, QMutex *mutex):  
    m_query(new QSqlQuery(dataBase))  
{  
    m_mutex = mutex;  
}  
  
Query::Query(Query &&other)  
{  
    m_query = other.takeQuery();  
    m_mutex = other.takeMutex();  
}  
  
Query::~Query(void)  
{  
    if(m_query)  
    {  
        delete m_query;  
    }  
    if(m_mutex)  
    {  
        m_mutex->unlock();  
    }  
}  
  
QSqlQuery *Query::takeQuery(void)  
{  
    auto buf = m_query;  
    m_query = NULL;  
    return buf;  
}  
  
QMutex *Query::takeMutex(void)  
{  
    auto buf = m_mutex;  
    m_mutex = NULL;  
    return buf;  
}  
  
// ConnectNode  
ConnectNode::ConnectNode(const DatabaseSettings &dataBaseSettings, const ConnectSettings &connectSettings):  
    m_dataBaseSettings(dataBaseSettings),  
    m_connectSettings(connectSettings)  
{  
    m_connectionName = QString("%1(%2)").arg(m_dataBaseSettings.connectionName()).arg(QString::number(qint64(QThread::currentThread()), 16));  
  
    m_mutex = new QMutex(QMutex::Recursive);  
  
    if(m_connectSettings.maxOpenTime())  
    {  
        m_autoClose = new QTimer;  
        m_autoClose->setSingleShot(true);  
        m_autoClose->setInterval(m_connectSettings.maxOpenTime());  
        m_autoClose->moveToThread(qApp->thread());  
        m_autoClose->setParent(qApp);  
  
        connect(m_autoClose, SIGNAL(timeout()), this, SLOT(close()), Qt::DirectConnection);  
        connect(this, SIGNAL(controlStartAutoClose()), m_autoClose, SLOT(start()));  
        connect(this, SIGNAL(controlStopAutoClose()), m_autoClose, SLOT(stop()));  
    }  
  
    this->addDataBase();  
}  
  
ConnectNode::~ConnectNode(void)  
{  
    if(m_mutex){ m_mutex->lock(); }  
  
    if(m_autoClose)  
    {  
        m_autoClose->deleteLater();  
    }  
  
    this->removeDataBase();  
  
    if(m_mutex){ m_mutex->unlock(); }  
    if(m_mutex){ delete m_mutex; }  
}  
  
Query ConnectNode::query(void)  
{  
    if(!m_database)  
    {  
        this->addDataBase();  
    }  
  
    if(!m_database->isOpen())  
    {  
        m_database->open();  
    }  
  
    if(m_mutex){ m_mutex->lock(); }  
  
    Query buf(*m_database, m_mutex);  
    emit controlStartAutoClose();  
    return buf;  
}  
  
bool ConnectNode::addDataBase(void)  
{  
    if(m_mutex){ m_mutex->lock(); }  
  
    if(m_database)  
    {  
        this->removeDataBase();  
    }  
  
    m_database = new QSqlDatabase(QSqlDatabase::addDatabase(m_dataBaseSettings.databaseType(), m_connectionName));  
  
    switch(m_dataBaseSettings.databaseMode())  
    {  
        case DatabaseNameMode:  
        {  
            m_database->setDatabaseName(m_dataBaseSettings.nameModeName());  
            break;  
        }  
        case DatabaseHostMode:  
        {  
            m_database->setHostName(m_dataBaseSettings.hostModeHostName());  
            m_database->setDatabaseName(m_dataBaseSettings.hostModeDatabaseName());  
            m_database->setUserName(m_dataBaseSettings.hostModeUserName());  
            m_database->setPassword(m_dataBaseSettings.hostModePassword());  
            break;  
        }  
        default:  
        {  
            if(m_mutex){ m_mutex->unlock(); }  
            return false;  
        }  
    }  
  
    const auto &&flag = this->open();  
  
    if(m_mutex){ m_mutex->unlock(); }  
  
    return flag;  
}  
  
void ConnectNode::removeDataBase(void)  
{  
    if(m_mutex){ m_mutex->lock(); }  
  
    delete m_database;  
    m_database = NULL;  
    QSqlDatabase::removeDatabase(m_connectionName);  
  
    if(m_mutex){ m_mutex->unlock(); }  
}  
  
bool ConnectNode::open(void)  
{  
    if(!m_database)  
    {  
        this->addDataBase();  
    }  
  
    if(m_mutex){ m_mutex->lock(); }  
  
    emit controlStartAutoClose();  
    const auto &&Flag = m_database->open();  
  
    if(m_mutex){ m_mutex->unlock(); }  
  
    return Flag;  
}  
  
void ConnectNode::close(void)  
{  
    if(m_mutex)  
    {  
        if(m_mutex->tryLock())  
        {  
            m_mutex->unlock();  
            emit controlStopAutoClose();  
            m_database->close();  
        }  
        else  
        {  
            emit controlStartAutoClose();  
        }  
    }  
    else  
    {  
        emit controlStopAutoClose();  
        m_database->close();  
    }  
}  
  
// Control  
Control::Control(const DatabaseSettings &databaseSettings, const ConnectSettings &connectSettings):  
    m_databaseSettings(databaseSettings),  
    m_connectSettings(connectSettings)  
{  
    if(m_connectSettings.queryMode() == QueryAutoMode)  
    {  
        if(databaseSettings.databaseType() == "QMYSQL")  
        {  
            m_connectSettings.setQueryMode(QueryMultiMode);  
        }  
        else if(databaseSettings.databaseType() == "QODBC")  
        {  
            m_connectSettings.setQueryMode(QueryMultiMode);  
        }  
        else  
        {  
            m_connectSettings.setQueryMode(QuerySingleMode);  
        }  
    }  
    if(m_connectSettings.queryMode() == QuerySingleMode)  
    {  
        this->insert(qint64(QThread::currentThread()));  
    }  
  
    if(m_connectSettings.minWaitTime() == -1)  
    {  
        if(databaseSettings.databaseType() == "QMYSQL")  
        {  
            m_connectSettings.setMinWaitTime(0);  
        }  
        else if(databaseSettings.databaseType() == "QODBC")  
        {  
            m_connectSettings.setMinWaitTime(0);  
        }  
        else  
        {  
            m_connectSettings.setMinWaitTime(5);  
            m_wait = new QTime;  
            m_wait->start();  
        }  
    }  
    else  
    {  
        m_wait = new QTime;  
        m_wait->start();  
    }  
}  
  
Control::~Control(void)  
{  
    for(auto &now: m_node)  
    {  
        now->deleteLater();  
    }  
    if(m_wait)  
    {  
        delete m_wait;  
    }  
}  
  
void Control::removeAll(void)  
{  
    m_mutex.lock();  
  
    for(auto &Now: m_node)  
    {  
        Now->removeDataBase();  
    }  
  
    m_mutex.unlock();  
}  
  
Query Control::query(void)  
{  
    if(m_wait)  
    {  
        const auto &&flag = m_connectSettings.minWaitTime() - m_wait->elapsed();  
        m_wait->restart();  
        if(flag > 0)  
        {  
            QThread::msleep(flag);  
        }  
    }  
  
    if(m_connectSettings.queryMode() == QueryMultiMode)  
    {  
        m_mutex.lock();  
  
        const auto &¤tThread = qint64(QThread::currentThread());  
        const auto &&now = m_node.find(currentThread);  
        if(now != m_node.end())  
        {  
            auto buf((*now)->query());  
  
            m_mutex.unlock();  
            return buf;  
        }  
        else  
        {  
            this->insert(qint64(QThread::currentThread()));  
  
            m_mutex.unlock();  
            return this->query();  
        }  
    }  
    else  
    {  
        return (*m_node.begin())->query();  
    }  
}  
  
void Control::insert(const qint64 &key)  
{  
    m_node[key] = new ConnectNode(m_databaseSettings, m_connectSettings);  
}  

使用

// Qt lib import  
#include <QCoreApplication>  
#include <QtConcurrent>  
#include <QSqlError>  
  
// JasonQt lib import  
#include "JasonQt/JasonQt_Database.h"  
  
int main(int argc, char *argv[])  
{  
    QCoreApplication a(argc, argv);  
  
    /* 
     * 注:关于附加参数 
     * 这是可以不写的,如果要写的话,可以参考这个: 
     * 
     * 单次打开数据库最大时间:也就是最大open的时间,对于某些数据库,长时间open但不使用,不仅会造成资源浪费还会意外断开。在设置了60 * 1000后,且60秒内未进行查询,就自动断开。 
     * 多线程支持:简单的说就是高级点的数据库,比如 MySql 写 JasonQt_Database::QueryMultiMode ;低级的,比如 Sqlite ,写 JasonQt_Database::QuerySingleMode ,就可以了。 
     * 最小等待时间:对于某些数据库,比如Sqlite,密集查询时可能出错,此时可以适当的提升两次查询之间的最小等待时间,比如10ms 
     */  
  
    // Sqlite的连接方式                    类型        连接名        Sqlite文件路径      单次打开数据库最大时间                多线程支持           最小等待时间  
    JasonQt_Database::Control control({ "QSQLITE", "TestDB", "/Users/Jason/test.db" }, { 60 * 1000,        JasonQt_Database::QuerySingleMode, 10});  
  
    // MySql的连接方式                      类型      连接名        IP        数据库    用户名        密码  
//  JasonQt_Database::Control control({ "QMYSQL", "TestDB", "localhost", "JasonDB", "root", "YourPassword" });  
  
  
    // SqlServer的连接方式                  类型      连接名                                    数据库              数据库名   用户名         密码  
//  JasonQt_Database::Control control({ "QODBC", "TestDB", "Driver={SQL SERVER};server=iZ23kn6vmZ\\TEST;database=test;uid=sa;pwd=YourPassword;" });  
  
    auto insert = [&]()  
    {  
        auto query(control.query()); // 这里的query在解引用( -> 或者 * )后返回的是 QSqlQuery ,直接用就可以了,不需要单独打开数据库或者其他的初始化  
  
        query->prepare("insert into Test1 values(?)"); // 模拟插入操作  
  
        query->addBindValue(rand() % 1280);  
  
        if(!query->exec())  
        {  
            qDebug() << "Error" << __LINE__;  
        }  
  
        query->clear();  
  
        query->prepare("insert into Test2 values(NULL, ?, ?)");  
  
        query->addBindValue(rand() % 1280);  
        QString buf;  
        for(int now = 0; now < 50; now++)  
        {  
            buf.append('a' + (rand() % 26));  
        }  
        query->addBindValue(buf);  
  
        if(!query->exec())  
        {  
            qDebug() << "Error" << __LINE__;  
        }  
    };  
    auto delete_ = [&]()  
    {  
        auto query(control.query());  
  
        query->prepare("delete from Test1 where data = ?");  
  
        query->addBindValue(rand() % 1280);  
  
        if(!query->exec())  
        {  
            qDebug() << "Error" << __LINE__;  
        }  
  
        query->clear();  
  
        query->prepare("delete from Test2 where data1 = ?");  
  
        query->addBindValue(rand() % 1280);  
  
        if(!query->exec())  
        {  
            qDebug() << "Error" << __LINE__;  
        }  
    };  
    auto update = [&]()  
    {  
        auto query(control.query());  
  
        query->prepare("update Test1 set data = ? where data = ?");  
  
        query->addBindValue(rand() % 1280);  
        query->addBindValue(rand() % 1280);  
  
        if(!query->exec())  
        {  
            qDebug() << "Error" << __LINE__;  
        }  
  
        query->clear();  
  
        query->prepare("update Test2 set data1 = ?, data2 = ? where data1 = ?");  
  
        query->addBindValue(rand() % 1280 + 1);  
        QString buf;  
        for(int now = 0; now < 50; now++)  
        {  
            buf.append('a' + (rand() % 26));  
        }  
        query->addBindValue(buf);  
        query->addBindValue(rand() % 1280 + 1);  
  
        if(!query->exec())  
        {  
            qDebug() << "Error" << __LINE__;  
        }  
    };  
    auto select = [&]()  
    {  
        auto query(control.query());  
  
        query->prepare("select * from Test1 where data = ?");  
  
        query->addBindValue(rand() % 1280);  
  
        if(!query->exec())  
        {  
            qDebug() << "Error" << __LINE__;  
        }  
  
        query->clear();  
  
        query->prepare("select * from Test2 where data1 = ?");  
  
        query->addBindValue(rand() % 1280);  
  
        if(!query->exec())  
        {  
            qDebug() << "Error" << __LINE__;  
        }  
    };  
  
    volatile int count = 0, last = 0;  
  
    QTime time;  
    time.start();  
  
    QThreadPool::globalInstance()->setMaxThreadCount(10);  
  
    for(int now = 0; now < 3; now++) // 开启3个线程测试  
    {  
        QtConcurrent::run([&]()  
        {  
            while(true)  
            {  
                count++;  
                if(!(count % 1000))  
                {  
                    const auto &&now = time.elapsed();  
                    qDebug() << now - last; // 打印每完成1000语句的时间  
                    last = now;  
                }  
  
                switch(rand() % 20)  
                {  
                    case 0:  { insert(); break; }  
                    case 1:  { delete_(); break; }  
                    case 2:  { update(); break; }  
                    default: { select(); break; }  
                }  
            }  
            QThread::msleep(10);  
        });  
    }  
  
    return a.exec();  

 

参考:

https://www.yuque.com/docs/share/66f2a342-a462-494f-8406-2b21867979a2

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", ""); mysqlsqlserver,就是各个参数依次提供,如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();
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值