Qt连接并操作SQL数据库(Qt学习①)

初学者记录学习内容,如有错误请各位前辈指点。

DOS命令操作数据库

虽然在window下是可以用DOS命令建立并操作数据库,但是当涉及到一些比较复杂的数据操作的时候还是比较繁琐,这里做个简单的示例,这里对mySQL的Qt配置不做多言,贫道使用的Qt5.8已经自带配置文件了。
用DOS命令建立数据库,输入密码后,显示当前存在的数据库输入命令show databases;(命令后面一定要加“;”)
这里写图片描述
create database student;创建一个名叫student的数据库;
这里写图片描述
use student; 对数据库进行操作;
这里写图片描述
呃,黑色好难看,换个背景色,然后在数据库中创建表格,并查看表格详情。
这里写图片描述
在数据库中插入数据。
这里写图片描述
更多命令可自行查询,其实这些并没有什么卵用,不易于数据的修改,推荐使用SQL数据库可视化工具,贫道使用的是“Navicat for MySQL”。
我们在Navicat中建立表格information,用户密码设置为777777,然后就可以将Qt项目与数据库建立连接了。

Qt与SQL数据库

注意要在项目中加入数据库的应用,要先在.pro中加入sql,保存。

QT       += core gui sql

连接mySQL数据库

在构造函数中加入这段代码;

  QSqlDatabase dataBase=QSqlDatabase::addDatabase("QMYSQL");
    dataBase.setHostName("localhost");
    dataBase.setUserName("root");
    dataBase.setPassword("777777");
    dataBase.setDatabaseName("picturedata");
    dataBase.open();

第一句是我们所加入的数据库的驱动类型,使用mySQL写入"QMYSQL",如果是使用sqlite数据库写入"QSQLITE",使用Oracle数据库写入"QOICQ" 。如上的QSqlDatabase dataBase是定义了一个数据库的句柄,又addDatabase返回并加载mySQL的驱动。数据库支持远程连接,setHostName()设置数据库主机名,这里是本地数据库。然后是setUserName()设置数据库用户名,setPassword()设置密码,setDatabaseName()设置数据库名。 这些一定要一致。
如果没有问题,连接成功以后open会返回一个bool型的变量true,我们可以接收一下这个变量qDebug显示成功或输出错误信息。

bool ok=dataBase.open();
    if(ok)
    {
      qDebug()<<"open database success";
    }
    else
    {
      qDebug()<<"error open database because"<<this->dataBase.lastError().text();
    }

这里需要注意,使用lastError()函数需要在在.h中引入

#include <QSqlError>

如果遇到
在这里插入图片描述
Driver not loaded的问题,其中一个解决办法是:
在H:\Qt\Qt5.5.1\5.5\mingw492_32\bin下加入SQL的动态链接库:libmysql.dll。

qDebug在项目编译初期可以这样做,但是如果不打开编译器是无法看到显示的信息的,即是说用户是无法用这种方法来判断是否连接成功的,所以可以改成用QMessageBox弹出小对话框来判断是否能够连接成功,后面会说到。

连接成功用户需要完成功能对数据库的增删改查,先看设计的界面如图:
这里写图片描述
上面的lineEdit填入数据,两个pushButton,savedataBase将数据写入数据库,resetdataBase将数据库中的数据清除,并清空界面,也就是说这个工程的数据库中始终只有一条数据。同时注意,界面打开时,lineEdit会显示数据库中存在的表信息到界面上。

插入数据

我们运行工程打开界面,在lineEdit中写入数据,点击保存,数据插入到数据库中,插入语句
注意插入语句的语法:
INSERT INTO table_name (列1, 列2,…) VALUES (值1, 值2,…);
如下的这种方式是我认为最简单的数据库操作函数,相当于直接在Qt中书写SQL语句。

       QSqlQuery query(dataBase);
       QString datestr = ui->dateEdit->dateTime().toString("dd-MM-yyyy");
       QString timestr = ui->dateEdit->time().toString("hh:mm:ss");
    QString sql=QString("select *from information");
    query.exec(sql);
    if(query.numRowsAffected() == 0)
    {
    QString savesql = QString("INSERT INTO information(userName,IP,storagePath,productName,date)");
    savesql += QString(" VALUES('%1','%2','%3','%4','%5')").arg(ui->userNameEdit->text())
            .arg(ui->ipAddressEdit->text())
            .arg(ui->storagePathEdit->text())
            .arg(ui->productNameEdit->text())
            .arg(datestr+' '+timestr);
    bool ok=query.exec(savesql);
    if(ok){
          QMessageBox::about(NULL, "Save", "save new database success");
          }
      else{
           QMessageBox::about(NULL, "Save", "error save new database");
          }
    }

在QString中写插入语句insert,当然第一行代码也可以写成这样子

QString("INSERT INTO information(userName,IP,storagePath,productName,date)
VALUES('%1','%2','%3','%4','%5')");

但是由于代码过长不便于查看最好进行拆分。在需要调用lineEdit中的输入语句时,把值写成参数”%1”””%2”……等,在后面加入.arg().arg()……;括号内可以写从控件获取文字信息的函数,或直接写入已经赋值的变量名,或者值本身。

Qt提供的一种格式化字符串输出的函数arg():

  1. str=QString("%1 %2 (%3s-%4s)")
  2. arg(“permissive”).arg(“society”).arg(1950).arg(1970);
    这段代码中,%1, %2, %3, %4作为占位符,将被后面的arg()函数中的内容依次替换,比如%1将被替换成permissive,%2将被替换成society,%3将被替换成1950,%4将被替换曾1970,最后,这句代码输出为:permissive society (1950s-1970s). arg()函数比起sprintf()来是类型安全的,同时它也接受多种的数据类型作为参数,都会被转化为QString类型然后进行替换。

使用bool ok=query.exec(savesql)执行该sql语句,返回一个bool型的结果。如上面说到的,可用一个变量来接收这个结果,由结果的不同true或fulse返回不同的QMessageBox小对话来让用户得到是否执行成功。
前面的一些代码在最后一部分会有说到。

修改数据

在数据库中已经有数据的情况下,可以实现修改界面文字,点击保存,实现数据库中的值的修改,修改语句

QString updatesql = QString("UPDATE information SET userName='%1',IP='%2',storagePath='%3',productName='%4',date='%5' WHERE IP=%6")
                      .arg(ui->userNameEdit->text())
                      .arg(ui->ipAddressEdit->text())
                      .arg(ui->storagePathEdit->text())
                      .arg(ui->productNameEdit->text())
                      .arg(datestr+' '+timestr)
                      .arg(oldIP);
    bool ok=query.exec(updatesql);
    if(ok){
        QMessageBox::about(NULL, "Save", "save database success");}
      else{
        QMessageBox::about(NULL, "Save", "error save database");}

注意updata语句的语法是:
UPDATE 表名称 SET 列名称 = 新值 WHERE 列名称 = 某值
where之后需要给出修改的条件,如题要获取未修改的数据库中的ip的值。
贫僧之前将修改的条件设置为界面上获取的IP:

QString updatesql = QString("UPDATE information SET userName='%1',IP='%2',storagePath='%3',productName='%4',date='%5' WHERE IP=%6")
           .arg(ui->userNameEdit->text())
           .arg(ui->ipAddressEdit->text())
           .arg(ui->storagePathEdit->text())
           .arg(ui->productNameEdit->text())
           .arg(datestr+' '+timestr).arg(ui->ipAddressEdit->text());

此时%6所接收到的IP是你准备要修改成的,而此时数据库中并没有的值,导致sql语句执行之后数据库中毫无变化,修改失败。可以在执行修改之前,定义一个变量oldIP去保存数据库中原来的IP值,写到主函数中。作为update语句的条件传入。

QString oldIP;
oldIP=ui->ipAddressEdit->text();

删除数据

接着实现点击刷新按钮,删除数据库中的用户信息,删除语句
注意delete的语法是DELETE FROM 表名称 WHERE 列名称 = 值;
IP条件引用与上例相同。

    QSqlQuery deletequery(dataBase);
    QString deletesql = QString("DELETE FROM information WHERE IP='%1'").arg(oldIP);
    bool ok=deletequery.exec(deletesql);
    if(ok)
    {
      QMessageBox::about(NULL, "Reset", "Reset database success");
      ui->userNameEdit->clear();
      ui->ipAddressEdit->clear();
      ui->storagePathEdit->clear();
      ui->productNameEdit->clear();
      ui->dateEdit->clear();
    }
    else
    {
       QMessageBox::about(NULL, "Reset", "error reset database");
    }

删除数据后,需要清空lineEdit()上的数据,调用.clear();

其他的几个重点问题

判断数据库是否为空

我们再回头看插入语句的代码会发现一个问题,这里有一个问题,只有一个保存save按钮,当数据库是否为空,两种情况点击button是执行update或insert这两种哪一种sql语句呢?这里就需要加入一个判断数据库是否为空。使用select语句查询语句查找表,query.exec()运行语句。

QString sql=QString("select *from information");
query.exec(sql);

然后调用query.numRowsAffected()

int QSqlQuery::numRowsAffected () const
返回有多少行记录被结果集的 SQL语句影响了,如果不能确定将返回 -1 。注意,对于 SELECT语句,此值等同于size()如果查询处于非活动状态(isActive()返回FALSE),将反回 -1。

如果数据库为空,将有0行语句被影响,那么就执行插入语句,否则执行修改语句。

QdateTimeEdit的处理

注意界面中获取时间和日期的控件,使用的是QdateTimeEdit,从这个控件获得的数据插入到数据库中时总是出现问题,此处的是从中.dateTime()和.time()单独获取日期和时间,以dd-MM-yyyy和hh:mm:ss的形式toString();单独保存,同时传入。

QString datestr = ui->dateEdit->dateTime().toString("dd-MM-yyyy");
QString timestr = ui->dateEdit->time().toString("hh:mm:ss");

写入数据库时进行组合arg(datestr+’ '+timestr)

数据库显示到界面

如果数据库中有已插入的数据,项目执行起来时,数据会从数据库加载到lineEdit上显示到界面中,这里自然又要用到select查询语句,涉及到对执行SQL语句后返回的结果集的操作,结果集其实就是查询到的所有记录的集合,需要注意这个集合中的记录是从0开始编号的,这里使用value(int n)来获取属性的值,其中n表示你查询的第n个属性。比如value(0),返回userName的值,转化为String类型.settext()显示到lineEdit中。
关注:MySql执行之后返回的结果集指针都指向数组第一条语句之前,因此需要调用一个next(),更便于使用while循环显示,而且每执行一次该函数,便指向相邻的下一条记录。Sqllite数据库也是如此,要先调用next()。

QSqlQuery showquery(dataBase);
    QString showsql=QString("select *from information");
    showquery.exec(showsql);
    if(showquery.numRowsAffected() != 0)
    {
        showquery.next();  
        ui->userNameEdit->setText(showquery.value(0).toString());
        ui->ipAddressEdit->setText(showquery.value(1).toString());
        ui->storagePathEdit->setText(showquery.value(2).toString());
        ui->productNameEdit->setText(showquery.value(3).toString());
        ui->dateEdit->setDateTime(QDateTime::fromString(showquery.value(4).toString(),"dd-MM-yyyy hh:mm:ss"));
    }

我们注意到,数据库中始终保持了一行代码需要显示,但是如果数据库中是3×5的表,select*以后返回的结果集是个二维数组,若需要用上述的方式的显示到3×5的lineEdit中的话,可以使用while循环调用query.value();

while(query.next()){
            ui->button1->setText(query.value(0).toString());
            ui->button2->setText(query.value(1).toString());
            ui->button3->setText(query.value(2).toString());
            ui->button4->setText(query.value(3).toString());
            ui->button5->setText(query.value(4).toString());
        }

While语句开始执行,第一次执行query.next()后指向第一行数据,然后五次调用.value(),遍历五列数据(value只管列),逐次显示到界面上。

结束,如有错误,还望指正。

<think>嗯,用户再次询问Qt连接MySQL的问题,看来之前的解决方案可能没完全解决他的问题。用户提供了三篇站内引用,但需要仔细甄别有效信息。用户的核心诉求很明确:需要个可靠的Qt+MySQL连接教程。从引用内容看,用户可能已经尝试过常规方法但未成功,说明遇到的是环境配置这类深层次问题。值得注意的细节是用户提到"参考站内引用但非真正需求",暗示可能需要更系统化的指导而非碎片化方案。梳理三篇引用的关键信息:引用[1]展示编译时参数设置,引用[2]描述驱动编译的细节,引用[3]则是DLL依赖的解决方案。结合历史对话,用户上次提问就涉及驱动加载失败,这次引用的第三篇也提到QMYSQLdrivernotloaded错误,说明这个问题具有普遍性。需要构建个分层解决方案:从最基本的驱动编译开始,到环境变量配置,最后是健壮性处理。特别注意引用[3]提到的三个DLL文件可能被忽略。用户环境可能是Window+Qt5+MySQL8,所以方案要侧重新版本兼容性。考虑到用户多次提问,这次要强调排错步骤的完备性。比如在驱动编译环节明确区分源码编译和预编译的区别,在环境配置部分补充Qt版本与MySQL架构匹配性检查。引用[2]说的去掉-llibmysql操作Qt6可能不适用,这点要特别说明。最后准备的问题要覆盖用户可能的后续痛点:连接池管理对应高性能需求,加密传输针对安全场景,而SQL执行监控则是调试刚需。这样形成从连接到维护的完整知识链。</think> 在Qt连接MySQL数据库需要解决驱动加载和环境配置问题,以下是详细步骤和常见问题解决方案: --- ### **、核心步骤** #### 1. **编译MySQL驱动** ```cmake # CMake配置示例(Qt 5.15+) set(MySQL_INCLUDE_DIR "C:/MySQL/include") # MySQL头文件路径 set(MySQL_LIBRARY "C:/MySQL/lib/libmysql.lib") # MySQL库文件路径 find_package(Qt5 COMPONENTS Sql REQUIRED) qt_add_plugin(qsqlmysql TYPE sqlplugin) target_link_libraries(qsqlmysql PRIVATE Qt5::Sql ${MySQL_LIBRARY}) target_include_directories(qsqlmysql PRIVATE ${MySQL_INCLUDE_DIR}) ``` > **注意**:若使用MinGW,需将`libmysql.lib`替换为`libmysql.a` #### 2. **部署运行时库** - 将以下DLL复制到Qt编译目录(`debug/release`)或系统`PATH`: - `libmysql.dll` - `libcrypto-1_1-x64.dll`(OpenSSL依赖) - `libssl-1_1-x64.dll` > 引用[3]提到的`libeay32.dll`已废弃,请使用OpenSSL 1.1+文件[^3]。 #### 3. **代码连接数据库** ```cpp #include <QSqlDatabase> #include <QSqlError> QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL"); db.setHostName("localhost"); // 主机IP db.setPort(3306); // 端口 db.setDatabaseName("test_db"); // 数据库名 db.setUserName("root"); // 用户名 db.setPassword("123456"); // 密码 if (!db.open()) { qDebug() << "连接失败:" << db.lastError().text(); } else { qDebug() << "MySQL连接成功!"; } ``` --- ### **二、常见错误解决方案** #### ❌ **错误1:`QMYSQL driver not loaded`** - **原因**:驱动未正确编译或缺失依赖库 - **解决**: 1. 检查`plugins/sqldrivers`目录是否有`qsqlmysql.dll` 2. 将MySQL的`libmysql.dll`复制到: - Qt的编译器目录(如`mingw73_64/bin`) - 或程序输出目录 3. 使用`depends.exe`工具检查DLL依赖完整性 #### ❌ **错误2:`Authentication plugin 'caching_sha2_password' cannot be loaded`** - **原因**:MySQL 8.0默认认证方式不兼容 - **解决**: ```sql ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '新密码'; FLUSH PRIVILEGES; ``` --- ### **三、完整项目配置示例(.pro文件)** ```qmake QT += sql INCLUDEPATH += "C:/MySQL/include" LIBS += -L"C:/MySQL/lib" -lmysql ``` --- ### **环境验证方法** ```cpp qDebug() << "可用驱动:" << QSqlDatabase::drivers(); // 输出应包含 "QMYSQL" ``` > **重要提醒**: > - Qt版本需与MySQL架构致(同32位或64位) > - MySQL Connector/C版本建议为8.0+ > - 开发环境路径避免中文或空格[^1][^2] ---
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值