Qt之数据库编程

一、简介

1、Qt SQL模块使用驱动程序插件操作不同的数据库。支持连接常用的数据库:MySQL、Oracle、SQL Server、SQLite。

其中,由于SQLite是轻量级的数据库,所以Qt支持创建生成本地SQLite数据库并管理。

2、QtSQL模块的api主要分为三层:

    1)驱动层:包括类QSqlDriver、QSqlDriverCreator、QSqlDriverCreatorBase、QSqlDriverPlugin和QSqlResult。

    2)数据库API层:这些类提供对数据库的访问。使用QSqlDatabase类进行连接。数据库交互是通过使用QSqlQuery类实现的。除了QSqlDatabase和QSqlQuery之外,QSqlError、QSqlField、QSqlIndex和QSqlRecord还支持SQL API层。

    3)用户交互层:这些类将数据从数据库链接到数据库控件。它们包括QSqlQueryModel、QSqlTableModel和QSqlRelationalTableModel。

二、连接数据库

数据库连接通常由连接名标识,而不是由数据库名。可以有多个连接到同一个数据库。qt_sql_default_connection是默认的连接。

1、连接本地数据库:SQLite

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QAction *action = menuBar()->addAction("连接数据库");
    connect(action,&QAction::triggered,[=]{
        QSqlDatabase db;
        //检测连接
        if(QSqlDatabase::contains("qt_sql_default_connection")){
            db = QSqlDatabase::database("qt_sql_default_connection");
        }else{
            //创建连接
            db = QSqlDatabase::addDatabase("QSQLITE","qt_sql_default_connection");
            db.setDatabaseName("F:/qtTest.db");
        }
        if(db.open()){
            QMessageBox::information(this,"提示","数据库连接成功!");
            db.close();
        }else{
            qDebug() << db.lastError().text();
        }
    });
}

2、连接远程数据库:MYSQL

遇到的问题:QSqlDatabase: QMYSQL driver not loaded 这是因为缺少libmysql.lib和libmysql.dll。网上给的链接已经下不到库了,只能自己去下载mysql的zip安装包,然后解压拿到这两个文件。当然release和debug版本都copy出来,然后放到QT的bin目录下即可。

MainWindow::MainWindow(QWidget *parent)
    : QWidget(parent)
{
    QFormLayout *mainLayout = new QFormLayout;
    QLineEdit *host = new QLineEdit("localhost");
    mainLayout->addRow("Host:",host);
    QLineEdit *port = new QLineEdit("3306");
    mainLayout->addRow("Port:",port);
    QPushButton *login = new QPushButton("登录");
    mainLayout->addWidget(login);
    setLayout(mainLayout);

    connect(login,&QPushButton::clicked,[=]{
        connectToMySQL(host->text().trimmed(),port->text().trimmed().toInt());
    });
}

MainWindow::~MainWindow()
{

}

void MainWindow::connectToMySQL(const QString &host, const int port)
{
    QSqlDatabase db;
    //检测是否已经存在默认连接了
    if(QSqlDatabase::contains("qt_sql_default_connection")){
        db = QSqlDatabase::database("qt_sql_default_connection");
    }else{
        //使用默认连接 创建一个sql对象
        db = QSqlDatabase::addDatabase("QMYSQL","qt_sql_default_connection");
        db.setDatabaseName("qtTest");
        db.setHostName(host);
        db.setPort(port);
        db.setUserName("xxxx");
        db.setPassword("xxxx");
    }
    bool ok = db.open();
    if(ok){
        qDebug() << "数据库连接成功";
        //然后就可以操作数据库完成增删改查了
        QSqlQuery query(db);
        //开启事务
        db.transaction();
        QString sql = QString("CREATE TABLE IF NOT EXISTS Test (test VARCHAR(200))");
        if(query.exec(sql)){
            sql = QString("INSERT INTO Test VALUE('hello Qt!')");
            if(query.exec(sql)){
                db.commit();
                qDebug() << "插入数据成功";
                //关闭数据库连接
                db.close();
            }else{
                db.rollback();
                qDebug() << "插入数据失败:" << query.lastError().text();
            }
        }else{
            qDebug() << "创建表失败:" << query.lastError().text();
            db.rollback();
        }
    }else{
        qDebug() << db.lastError().text();
    }
}

3、优雅的删除多条数据库连接。

MainWindow::MainWindow(QWidget *parent)
    : QWidget(parent)
{
    QGridLayout *mainLayout = new QGridLayout;
    mainLayout->addWidget(new QLabel("firstConnection"),0,0);
    mainLayout->addWidget(new QLabel("secondConnection"),1,0);
    mainLayout->addWidget(new QLabel("thirdConnection"),2,0);

    QPushButton *connectBtn = new QPushButton("连接");
    QPushButton *connectBtn1 = new QPushButton("连接1");
    QPushButton *connectBtn2 = new QPushButton("连接2");
    mainLayout->addWidget(connectBtn,0,1);
    mainLayout->addWidget(connectBtn1,1,1);
    mainLayout->addWidget(connectBtn2,2,1);

    QPushButton *disconnectBtn = new QPushButton("断开连接");
    QPushButton *disconnectBtn1 = new QPushButton("断开连接1");
    QPushButton *disconnectBtn2 = new QPushButton("断开连接2");
    mainLayout->addWidget(disconnectBtn,0,2);
    mainLayout->addWidget(disconnectBtn1,1,2);
    mainLayout->addWidget(disconnectBtn2,2,2);

    QLabel *label = new QLabel("当前数据库连接条数:0");
    mainLayout->addWidget(label,3,0,1,2);

    connect(connectBtn,&QPushButton::clicked,[=]{
        db = getDatabase("firstConnection");
        if(db.open()){
            QMessageBox::information(this,"提示","连接数据库成功");
            label->setText(QString("当前数据库连接条数:%1").arg(QSqlDatabase::connectionNames().count()));
            query = QSqlQuery(db);
            QString  sql = QString("CREATE TABLE IF NOT EXISTS Test (test VARCHAR(200))");
            query.exec(sql);
        }else{
            QMessageBox::critical(this,"错误",db.lastError().text());
        }
    });

    connect(connectBtn1,&QPushButton::clicked,[=]{
        db1 = getDatabase("secondConnection");
        if(db1.open()){
            QMessageBox::information(this,"提示","连接数据库成功");
            label->setText(QString("当前数据库连接条数:%1").arg(QSqlDatabase::connectionNames().count()));
            query1 = QSqlQuery(db1);
            QString  sql = QString("CREATE TABLE IF NOT EXISTS Test1 (test VARCHAR(200))");
            query1.exec(sql);
        }else{
            QMessageBox::critical(this,"错误",db1.lastError().text());
        }
    });

    connect(connectBtn2,&QPushButton::clicked,[=]{
        db2 = getDatabase("thirdConnection");
        if(db2.open()){
            QMessageBox::information(this,"提示","连接数据库成功");
            label->setText(QString("当前数据库连接条数:%1").arg(QSqlDatabase::connectionNames().count()));
            query2 = QSqlQuery(db2);
            QString  sql = QString("CREATE TABLE IF NOT EXISTS Test2 (test VARCHAR(200))");
            query2.exec(sql);
        }else{
            QMessageBox::critical(this,"错误",db2.lastError().text());
        }
    });

    connect(disconnectBtn,&QPushButton::clicked,[=]{
        //错误写法 会被Qt警告 因为 连接是被引用计数的 在db 和 query那里还有计数 所以不会删除掉
//        QSqlDatabase::removeDatabase("firstConnection");
        //正确的写法
        db = QSqlDatabase();
        query = QSqlQuery();
        QSqlDatabase::removeDatabase("firstConnection");
    });

    connect(disconnectBtn1,&QPushButton::clicked,[=]{
        //错误写法 会被Qt警告 因为 连接是被引用计数的 在db1 和 query1那里还有计数 所以不会删除掉
//        QSqlDatabase::removeDatabase("secondConnection");
        //正确的写法
        db1 = QSqlDatabase();
        query1 = QSqlQuery();
        QSqlDatabase::removeDatabase("secondConnection");
    });

    connect(disconnectBtn2,&QPushButton::clicked,[=]{
        //错误写法 会被Qt警告 因为 连接是被引用计数的 在db2 和 query2那里还有计数 所以不会删除掉
//        QSqlDatabase::removeDatabase("thirdConnection");
        //正确的写法
        db2 = QSqlDatabase();
        query2 = QSqlQuery();
        QSqlDatabase::removeDatabase("thirdConnection");
    });

    setLayout(mainLayout);
}

MainWindow::~MainWindow()
{
    db.close();
    db1.close();
    db2.close();
}

QSqlDatabase MainWindow::getDatabase(const QString &connection)
{
    QSqlDatabase db;
    if(QSqlDatabase::contains(connection)){
        QMessageBox::warning(this,"警告",QString("连接:%1 ,已经存在,请勿重复连接").arg(connection));
        db = QSqlDatabase::database(connection);
    }else{
        db = QSqlDatabase::addDatabase("QSQLITE",connection);
        db.setDatabaseName("F:/qtTest.db");
    }
    return db;
}

三、操作数据库

两种方式:

第一种:自己写sql,然后用QSqlQuery执行,之后的结果用QSqlQuery::next(),QSqlQuery::value()来获取sql结果值

第二种:自己写sql,然后用QSqlQuery执行,之后的结果用QSqlQuery::next(),QSqlField, QSqlIndex, and QSqlRecord.来获取

具体操作的用法详见:https://www.cnblogs.com/xia-weiwen/archive/2017/05/04/6806709.html

批量操作也比较常用:https://blog.csdn.net/phenixyf/article/details/70598244

四、访问数据库的方便控件类。

猜你喜欢

转载自blog.csdn.net/wei375653972/article/details/86623291
今日推荐