Qt个人项目总结 —— MySQL数据库查询与断言

news/2025/3/13 14:41:54/文章来源:https://www.cnblogs.com/leaf-7-scouts/p/18758243

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


  • 问题:

    • 当我使用MySQL数据库的查询操作时,
    • 如果查询的数据在数据库中不存在,那么Qt会直接被干崩溃
    • 但是?为什么呢?不应该是返回if语句中的结果吗,为什么会崩溃呢?
    • img
  • 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制造者,调试的克星,代码的混乱之源,咖啡的吞噬者,深夜的守护者以及键盘毁灭者 —— 某苦逼大学生是也(借用美剧《权力的游戏》龙妈头衔梗)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/895201.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Effective log parsing in log streams using fixed depth forest 论文笔记

挑战 主要讲的是 Drain 的一些问题: ① 对于变量开头的日志会存在解析错误 ② 常量在变量之前发生变化的日志也会导致解析错误 框架预处理 对于源日志,采用随机修改 token 的下标(即顺序)分成几个子日志,相当于数据增强 候选模版生成 这里采用的就是 Drain 的解析过程,为…

P2241 统计方形(数据加强版)

题目背景 1997年普及组第一题 题目描述 有一个 $n \times m$ 方格的棋盘,求其方格包含多少正方形、长方形(不包含正方形)。 输入格式 一行,两个正整数 $n,m$($n \leq 5000,m \leq 5000$)。 输出格式 一行,两个正整数,分别表示方格包含多少正方形、长方形(不包含正方形…

2025扩展可能性采购和供应链管理使用AI报告100+份汇总解读|附PDF下载

原文链接:https://tecdat.cn/?p=40348 在当今快速发展的商业环境中,采购和供应链管理领域正经历着深刻变革,人工智能(AI)技术的融入成为推动这一变革的关键力量。 本报告汇总解读聚焦于AI在采购和供应链管理中的应用,深入剖析其发展现状、面临挑战与潜在机遇。通过对大量…

通义灵码AI程序员深度测评:这些能力体验感拉满!满血版 DeepSeek 玩法大揭秘

随着科技的发展,AI编程,或者说是AI辅助编程,已经成为了每一位程序员的福利。今天我们要说的AI程序员,相对于传统的AI辅助编程工具, AI 程序员具备多文件代码修改(Multi-file Edit)和工具使用(Tool-use)的能力,可以与开发者协同完成编码任务,如需求实现、问题解决、单…

从星链到数字样机:直升机智能化升级的双引擎

​直升机作为一种多功能航空器,凭借其垂直起降、空中悬停的独特优势,在军事、民用、救援等多个领域发挥着重要作用。然而,受制于传统通信导航性能瓶颈与机械系统脆弱性叠加效应,直升机在复杂环境下仍面临通信中断、导航精度不足、数据传输受限等问题,其物理特性与技术架构…

manim边学边做--局部缩放的场景类

在动画制作中,尤其是数学和科学可视化领域,有时我们需要将观众的注意力集中在场景的某个特定部分。 Manim提供了一个强大的工具 ZoomedScene,它允许我们在场景中创建一个独立的缩放视图,从而实现对局部细节的深入展示。 本文将详细介绍ZoomedScene的作用、参数、方法,并通…

docker-compose文件目录

/usr/local/binEND作者:超级鲨鱼辣椒 转载请注明原文链接:https://www.cnblogs.com/jinzlblog/p/18758160

Linux重启nginx命令

cd /usr/sbin ./nginx -s reloadEND作者:超级鲨鱼辣椒 转载请注明原文链接:https://www.cnblogs.com/jinzlblog/p/18758164

使用Nginx实现域名解析到同一台服务器不同服务端口

作为个人网站的服务器,一般都是一台。上面部署了各种应用,都是不同的端口。但是域名只能解析到 80 端口,而且如果你使用 隐性URL、显性URL 转发的话,又会直接 301 跳转,体验非常不好。这可如何是好呢?这就需要用到 Nginx 做反向代理了。什么是反向代理?我们先来看一下解…

Inventor pro 2025下载与安装教

1、安装包 扫描下方二维码关注「软知社」,后台回复【054】三位数字即可免费获取分享链接,无广告拒绝套路;2、安装教程(建议关闭杀毒软件)双击Setup.exe安装,弹窗安装对话框勾选‘我同意,点击下一步选择软件安装路径,建议C盘之外进行安装,点击下一步默认所有组件,点击安…

基于Fluent和深度学习算法驱动的流体力学计算与应用

流体力学基础 一、流体力学基础理论与编程实战 1、流体力学的主要内容 2、不可压缩流体力学的基本方程 3、Navier–Stokes方程的数值求解介绍 4、有限体积法与有限差分法介绍 案例实践: 1、Matlab编程实现有限差分(案例) 2、使用深度学习框架(如TensorFlow或PyTorch)进行流…

YC 孵化项目 Pinch:实时语音翻译视频会议平台;Mistral OCR:能处理多语言多模态复杂文档丨日报

开发者朋友们大家好:这里是 「RTE 开发者日报」 ,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE(Real-Time Engagement) 领域内「有话题的 技术 」、「有亮点的 产品 」、「有思考的 文章 」、「有态度的 观点 」、「有看点的 活动 」,但内容仅代表编辑…