3.Qt项目总结——数据库查询断言问题


  • 问题:

    • 当我使用MySQL数据库的查询操作时,
    • 如果查询的数据在数据库中不存在,那么Qt会直接被干崩溃
    • 但是?为什么呢?不应该是返回if语句中的结果吗,为什么会崩溃呢?
  • bug代码示例
    ===========================================================================================
    // 查询数据库获取哈希密码和盐
    QSqlQuery query(p->db);
    query.prepare("SELECT passwd, salt FROM musicplayer WHERE username = :username");
    query.bindValue(":username", username); if (!query.exec() || !query.next())
    {
    qDebug() << "查询失败或用户名不存在:" << p->db.lastError();
    QMessageBox::warning(this, "警告", "用户名或密码错误!");
    return;
    }
    ===========================================================================================

  • 为此,我特意写了一个函数用来测试这个问题

  • 但是,在此之前,先来回顾几个知识点

  • 1.query.exec()

    • query.exec() 用于执行 SQL 查询语句,返回值代表查询是否成功
    • 如果查询执行成功,返回true
    • 如果执行失败(例如表不存在、语法错误等),query.exec() 会返回 false
  • 2.query.next()

    • query.next() 用于获取查询结果的下一条数据,返回值代表下一行数据是否存在
    • 如果查询执行成功,返回true
    • 如果查询为空(没有任何匹配结果),query.next() 会返回 false
  • 3.与运算符||

    • 执行顺序是从左至右的

  • 现在再来看看测试函数

  • // 断言bug测试
    // 假设数据库已经连接
    void Widget::AssertTest()
    {
    QSqlQuery query(db); #if 1
    // 1.使用断言查询一个不存在的人(给Qt干崩溃了) —— 预处理语句
    // 查询结果为空时, query.next() 返回 false
    // 但是没有进一步操作无效数据,程序就跳转到错误处理部分
    // 然后,嘭!你的QT崩溃了,开始今天晚上的修bug之旅吧 QString username = "111";
    query.prepare("select passwd, salt from musicplayer where username = :username");
    query.bindValue(":username", username);
    #else
    // 2.不使用断言查询一个不存在的人(Qt没有崩溃) —— 拼接字符串
    // 查询结果为空时, query.next() 返回 false
    // 但是没有进一步操作无效数据,程序就跳转到错误处理部分
    // 会继续if条件分支,执行错误处理并退出
    // 没有进一步访问无效数据或发生未定义行为
    query.prepare("select passwd, salt from musicplayer where username = qwwq");
    #endif // 使用断言时,如果查询数据在数据库中不存在(exec执行),那么Qt就会崩溃
    // 但是如果将query.exec()和query.next()的执行顺序对调
    // 先执行query.next()再执行query.exec()呢
    // 如果这样做了,请尽量不要在你老师面前提及到这件事(会被揍的)........
    // 当然,如果有仇的话,出门的时候可以多报一下你老师的名字....... // || 的运算顺序是从左至右 // 1.if (!query.exec() || !query.next())
    // 先执行query.exec(),再执行query.next()
    // 即:先确保查询语句是否成功再查询有效数据 // 2.if (!query.next() || !query.exec())
    // 先执行query.next(),再执行query.exec()
    // 即:query.next()先执行,query.next()的行为就会是不可预测的(Qt说不定就又被干崩溃了),
    // 即使查询没有执行成功,通常也会返回false // 如果查询没有执行("exec()"),
    // query.next() 会试图访问无效的结果集,这可能会导致不可预料的行为,甚至崩溃
    // query.exec() 没有执行,那么query.next() 根本就不应该被执行,因为查询结果集并不存在
    // 调用 next() 就是访问不存在的数据 // 人话:exec()是执行,next()是访问下一行数据
    // 你都没有执行,怎么可以访问下一行数据
    // 再说直接一点,你进家门,门都还没有打开,你就想躺平怎么可能嘛 // 1.正确写法
    // if (!query.exec() || !query.next())
    // 2.错误写法
    if (!query.next() || !query.exec())
    {
    qDebug() << "查询失败或用户名不存在:" << db.lastError();
    QMessageBox::warning(this, "提示", "用户名不存在!");
    return;
    } qDebug() << "查询成功" ;
    }
  • 那么,问题来了,为什么使用断言Qt会崩溃,不使用断言就不会崩溃呢?

  • 这就得提到断言的工作原理了


  • 断言的工作原理

    • 断言是在开发过程中用来检查代码正确性的一种手段

    • 它会检查某个条件是否为真,如果条件为假,就会中断程序的执行,通常会抛出一个错误或崩溃

    • 断言的使用是根据编译模式的不同来决定的:

      • 在 调试模式 下,断言会被启用,而在 发布模式 下,它通常会被禁用

  • 为什么不使用断言就不会崩溃?

  • 因为query.next()query.exec()并不会使Qt崩溃,说白了就是断言的锅

  • Qt的设计并不要求开发者强制使用断言来检查查询结果的有效性

  • 当查询没有结果时,query.next() 返回 false,但不会抛出异常或触发断言

  • 它的行为是让开发者检查查询是否成功(通过 query.exec())以及是否有数据返回(通过 query.next()

  • 如果查询失败或没有结果,开发者通常会自己决定如何处理

  • 如果在没有结果的情况下继续访问数据,query.value() 会返回一个无效的默认值(例如空字符串),而不会触发崩溃


你以为就这样结束了吗,这个问题?作为bug的专业制造机,我怎么可能只生产一个bug?

还有一个强制性的DLC扩展包

提问:上面的代码还有一个bug,是什么呢?

    // 错误的断言方式(语法错误)
// QString sql = "SELECT passwd, salt FROM musicplayer WHERE username = " + username;
// 查询数据库获取哈希密码和盐
QString sql = "SELECT passwd, salt FROM musicplayer WHERE username = '" + username + "'";
QSqlQuery query(p->db);

不是,谁教你sql执行语句是这样写的啊,字符串格式怎么写的啊,用单引号括起来啊喂

是我自己写的啊,那没事了

  • 为什么不能这样写?
  • 假设我现在在查询用户名 zzz
  • 代码直接拼接 username,导致生成的 SQL 语句将 zzz 视为列名或标识符,而非字符串值
  • 如果数据库中不存在名为 zzz 的列,查询会返回空结果
  • 当用户名为 zzz 时,生成的 SQL 语法错误,导致查询失败或返回空结果
  • 若用户名包含空格或特殊字符(如 John Doe),问题会更明显,可能导致 SQL 语法错误

省流:语法错误 那你讲这么一大堆干什么啊喂


看了一下我以前写的项目总结,我只能说

不愧是我,bug制造者,调试的克星,代码的混乱之源,咖啡的吞噬者,深夜的守护者以及键盘毁灭者 —— 某苦逼大学生是也(借用美剧《权力的游戏》龙妈头衔梗)

Qt个人项目总结 —— MySQL数据库查询与断言的更多相关文章

  1. mysql数据库查询pdo的用法

    最早的php对mysql数据库查询是mysql和mysqli方法,后来php的新版本进一步封住了该方法,于是又pdo,抛开php框架,使用pdo查询数据,使用也是相当简便 <?php ini_s ...

  2. 提高MySQL数据库查询效率的几个技巧(转载)

    [size=5][color=Red]提高MySQL数据库查询效率的几个技巧(转)[/color][/size]      MySQL由于它本身的小巧和操作的高效, 在数据库应用中越来越多的被采用.我 ...

  3. 将从mysql数据库查询的信息,遍历到List<>以及一些随机数的生成

    将从mysql数据库查询的信息,遍历到List<>以及一些随机数的生成. 代码比较乱,但是方法还是对的,大家又需要的选择看,希望对博友 有帮助,欢迎留言分享! public class s ...

  4. MySQL 数据库查询数据,过滤重复数据保留一条数据---(MySQL中的row_number变相实现方法)

    转自: http://www.maomao365.com/?p=10564 摘要: 下文讲述MySQL数据库查询重复数据时,只保留一条数据的方法 实现思路: 在MySQL数据库中没有row_numbe ...

  5. 一个项目中mysql数据库经常死锁的问题解决记录

    1.问题描述 此项目为一个物流系统,需要使用PDA对货物进行入库.备货.出货等操作,在系统开发测试过程中,经常发现死锁问题. 有这样一种业务场景:仓库对备货单上货进行扫码备货后,点击"完成& ...

  6. 项目--解决MySQL数据库插入中文乱码

    转载自:http://blog.csdn.net/zzh920625/article/details/51226312 情景再现] 如图,在项目中使用MySQL数据库,在做插入操作时,写入英文字符没有 ...

  7. 路飞项目使用mysql数据库详细讲解

    目录 一.首先需要彻底删除原有的数据库步骤 二.去官网下载mysql步骤 三.安装mysql数据库步骤 四.一管理员身份进去cmd进行一系列命令启动 五.接下来为路飞项目创建数据库 六.luffy项目 ...

  8. 项目管理系统 SQL2005数据库查询CPU100%问题研究

    [一篮饭特稀原创,转载请注明出自http://www.cnblogs.com/wanghafan/p/4595084.html]  在项目管理系统中出现查询工程明细出现CPU100%卡死症状: 1.打 ...

  9. 【入门】Spring-Boot项目配置Mysql数据库

    前言 前面参照SpringBoot官网,自动生成了简单项目点击打开链接 配置数据库和代码遇到的问题 问题1:cannot load driver class :com.mysql.jdbc.Drive ...

  10. Mysql数据库查询数据文件大小

    参考网站:https://zhidao.baidu.com/question/201227796936321525.html 用SQL命令查看Mysql数据库大小 要想知道每个数据库的大小的话,步骤如 ...

随机推荐

  1. 【C#】【平时作业】习题-6-静态成员

    习题-6静态成员 一.概念题 1. 什么是静态成员 被static修饰的成员,叫做静态成员.静态成员是属于类的.通过类名直接访问. 当类第一次被访问的时候,就会将这个类下面的所有的静态成员创建在内存当 ...

  2. jenkins集群 - HTMLreport测试报告

    一.安装 HTML Publisher plugin 插件 插件下载地址 二.配置构建后步骤 三.编辑报告执行脚本 四.安装 Startup Trigger 和 Groovy 插件 1.安装原因: J ...

  3. Qt/C++音视频开发65-切换声卡/选择音频输出设备/播放到不同的声音设备/声卡下拉框

    一.前言 近期收到一个用户需求,要求音视频组件能够切换声卡,首先要在vlc上实现,于是马不停蹄的研究起来,马上查阅对应vlc有没有自带的api接口,查看接口前,先打开vlc播放器,看下能不能切换,因为 ...

  4. Qt/C++音视频开发61-多屏渲染/一个解码渲染到多个窗口/画面实时同步

    一.前言 多屏渲染就是一个解码线程对应多个渲染界面,通过addrender这种方式添加多个绘制窗体,我们经常可以在展会或者卖电视机的地方可以看到很多电视播放的同一个画面,原理应该类似,一个地方负责打开 ...

  5. Qt编写跨平台视频监控系统(64通道占用7%CPU/支持win_linux_mac等)

    一.前言 视频监控组件经历过数十年的迭代,从最初的只简单播放个rtsp视频流,到现在支持各种音频视频文件格式(mp3.wav.mp4.asf.rm.rmvb.mkv等).支持各种视频流格式(rtp.r ...

  6. Qt编写物联网管理平台45-采集数据转发

    一.前言 本系统严格意义上说是一个直连硬件的客户端软件,下面接的modbus协议的设备直接通过网络或者串口和软件通信,软件负责解析数据和存储记录.有时候客户想要领导办公室或者分管这一块的部门经理办公室 ...

  7. Qt项目升级到Qt6吐血经验总结

    Qt的版本发布越来越频繁,Qt6发布已经有一段时间了,越来越多的人咨询之前的代码是否可以增加对Qt6的支持,包括开源的项目QWidgetDemo(一年时间超过2.6K star),近期百忙之中,对所有 ...

  8. Qt编写安防视频监控系统35-onvif抓拍图片

    一.前言 以前不知道onvif也可以做抓拍功能,直到近期重新用Onvif Device Test Tool工具测试的时候,发现还有抓图的接口,于是抓跑分析出要收发的数据,然后加入到自己封装的onvif ...

  9. [转]swing中如何将jtable中的数据导入到excel中?

    这个版本的代码是可以支持中文,需要导入jxl.jar包,并添加到Build Path中(自行搜索下载). 最终代码: package test; import java.awt.event.*; im ...

  10. IM扫码登录技术专题(三):通俗易懂,IM扫码登录功能详细原理一篇就够

    本文引用了作者"大古同学"的"二维码扫码登录是什么原理"一文的主要内容,为了更好的理解和阅读,即时通讯网收录时有修订和改动,感谢原作者的分享. 1.引言 自从微 ...