Qt个人项目总结 —— MySQL数据库查询与断言
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数据库查询与断言的更多相关文章
- mysql数据库查询pdo的用法
最早的php对mysql数据库查询是mysql和mysqli方法,后来php的新版本进一步封住了该方法,于是又pdo,抛开php框架,使用pdo查询数据,使用也是相当简便 <?php ini_s ...
- 提高MySQL数据库查询效率的几个技巧(转载)
[size=5][color=Red]提高MySQL数据库查询效率的几个技巧(转)[/color][/size] MySQL由于它本身的小巧和操作的高效, 在数据库应用中越来越多的被采用.我 ...
- 将从mysql数据库查询的信息,遍历到List<>以及一些随机数的生成
将从mysql数据库查询的信息,遍历到List<>以及一些随机数的生成. 代码比较乱,但是方法还是对的,大家又需要的选择看,希望对博友 有帮助,欢迎留言分享! public class s ...
- MySQL 数据库查询数据,过滤重复数据保留一条数据---(MySQL中的row_number变相实现方法)
转自: http://www.maomao365.com/?p=10564 摘要: 下文讲述MySQL数据库查询重复数据时,只保留一条数据的方法 实现思路: 在MySQL数据库中没有row_numbe ...
- 一个项目中mysql数据库经常死锁的问题解决记录
1.问题描述 此项目为一个物流系统,需要使用PDA对货物进行入库.备货.出货等操作,在系统开发测试过程中,经常发现死锁问题. 有这样一种业务场景:仓库对备货单上货进行扫码备货后,点击"完成& ...
- 项目--解决MySQL数据库插入中文乱码
转载自:http://blog.csdn.net/zzh920625/article/details/51226312 情景再现] 如图,在项目中使用MySQL数据库,在做插入操作时,写入英文字符没有 ...
- 路飞项目使用mysql数据库详细讲解
目录 一.首先需要彻底删除原有的数据库步骤 二.去官网下载mysql步骤 三.安装mysql数据库步骤 四.一管理员身份进去cmd进行一系列命令启动 五.接下来为路飞项目创建数据库 六.luffy项目 ...
- 项目管理系统 SQL2005数据库查询CPU100%问题研究
[一篮饭特稀原创,转载请注明出自http://www.cnblogs.com/wanghafan/p/4595084.html] 在项目管理系统中出现查询工程明细出现CPU100%卡死症状: 1.打 ...
- 【入门】Spring-Boot项目配置Mysql数据库
前言 前面参照SpringBoot官网,自动生成了简单项目点击打开链接 配置数据库和代码遇到的问题 问题1:cannot load driver class :com.mysql.jdbc.Drive ...
- Mysql数据库查询数据文件大小
参考网站:https://zhidao.baidu.com/question/201227796936321525.html 用SQL命令查看Mysql数据库大小 要想知道每个数据库的大小的话,步骤如 ...
随机推荐
- java多层级zip解压
java多层级zip解压 前言 项目中偶然需要,希望能处理嵌套的压缩包,但是又不希望把文件解压处理.原本不希望重复造轮子,但没有发现很好用的现成案例,就简单处理了一下. 正文 java做zip解压一般 ...
- rocketMq4.2.0启动broker报错找不到或无法加载主类 Files\Java\jdk1.8.0_101\lib\dt.jar;C:\Program]
假如弹出提示框提示'错误: 找不到或无法加载主类 xxxxxx'.打开runbroker.cmd,然后将'%CLASSPATH%'加上英文双引号.保存并重新执行start语句.做如下图处理 但是输出还 ...
- VC++2008、2010、2012、2015、2017等IDE中如何设置命令行参数进行程序调试
有时我们在写程序时会从命令行中直接读入参数,形如: int main(int argc,char**argv){ //your code here return 0; } 其实在vc2010 IDE中 ...
- 阿里IM技术分享(十):深度揭密钉钉后端架构的单元化演进之路
本文由钉钉技术专家啸台.万泓分享,为了获得更好的阅读效果,本文已对内容进行少修订和重新排版. 1.引言 钉钉后端架构的单元化工作从2018年开始到今年,已经是第五个年头了.五年的时间,钉钉单元化迭代了 ...
- G1原理—1.G1回收器的分区机制
大纲 1.G1垃圾回收器的分区(Region大小+G1分区+Region过大过小和计算) 2.Region大小的计算原理(先转字节然后确定2的n次幂再通过1左移n位) 3.新生代分区及自动扩展(新生代 ...
- linux安装软件配置
CentOS7更换yum为阿里源 1 备份本地源mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backu ...
- Quartz调度框架详解、运用场景、与集群部署实践
以下将分别从Quartz架构简介.集群部署实践.Quartz监控.集群原理分析详解Quartz任务调度框架. Quartz简介 Quartz是Java领域最著名的开源任务调度工具,是一个任务调度框架, ...
- linux基础知识(基本认知、操作命令、常用技巧)
文章目录 Linux基本认知 容量大小 自动补全命令或文件(夹) 复用之前的命令 Linux文件系统 Linux中命令和执行程序长什么样子 执行过的历史命令的记录文件的位置 linux的隐藏文件 Li ...
- nginx配置好访问返回502错误
CentOS服务器配置好Nginx重新加载了配置文件,浏览器访问提示错误: 502 Bad Gatewaynginx/1.16.1 如图: 页面上直接显示了nginx名称,一般是说nginx服务器返回 ...
- 一个DataGridView辅助类
DataGridView是在用C#做windows界面程序时常用到的控件,DataGridView的功能非常多,用起来也非常复杂 例如1. 我想在每行前面显示行编号,则需要先设置RowHeadersV ...