QT开发--QT SQL模块
第十五章 QT SQL模块
15.1 QT SQL模块概览
Qt SQL模块是Qt框架中操作数据库的组件,提供易用API,支持SQLite、MySQL等多种数据库。它包含数据库驱动与连接功能。
15.1.1 QSqlDatabase 类
在Qt SQL模块中,数据库驱动基于QSqlDriver类,可通过继承创建自定义驱动。
使用QSqlDatabase的static addDatabase()方法能创建数据库连接,需指定驱动类型及连接名(非数据库名)。连接由连接名区分,支持同一数据库的多连接。默认连接是无名连接,创建时省略连接名即可。若使用静态成员函数且不指定连接名,则操作默认连接。
15.1.2. 数据库驱动与连接
Qt SQL通过数据库驱动与各种数据库交互,驱动是Qt与数据库系统间的接口。
Qt支持多种驱动,如QSQLITE、QMYSQL。
要使用数据库,需建立连接,连接由QSqlDatabase类表示。
#include <QSqlDatabase> // 引入Qt SQL数据库类
#include <QDebug> // 引入Qt调试输出类 int main(int argc, char *argv[]) { QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); // 添加SQLite数据库驱动 db.setDatabaseName("example.db"); // 设置数据库文件名为example.db if (!db.open()) { // 尝试打开数据库,若失败则输出错误信息并返回 qDebug() << "Error: Could not connect to database."; return 1; } // 在此处进行数据库操作,例如查询、插入、更新等 db.close(); // 关闭数据库连接 return 0; // 程序正常结束
}
15.1.3 支持的数据库类型
Qt SQL模块优点在于提供通用API,使代码大多独立于特定数据库。
但要与特定数据库连接,需为Qt提供相应数据库驱动插件。以下是部分支持的数据库类型及驱动名称。
| 序号 | 驱动名称 | 数据库系统 | 驱动说明 |
|---|---|---|---|
| 1 | QSQLITE | SQLite | 支持 SQLite3 数据库系统 |
| 2 | QMYSQL | MySQL | 支持 MySQL 数据库系统 |
| 3 | QPSQL | PostgreSQL | 支持 PostgreSQL 数据库系统 |
| 4 | QODBC | ODBC | 支持 ODBC 驱动,包括微软的 SQL Server |
| 5 | QOCI | Oracle | 支持 Oracle 调用接口驱动 |
| 6 | QIBASE | InterBase | 支持 Borland InterBase 驱动,适用于嵌入式和跨平台数据库应用 |
| 7 | QDB2 | IBM DB2 | 支持 IBM DB2 数据库系统 |
这些驱动名可以在创建 QSqlDatabase 实例时指定,例如:
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
在此例中,我们添加了QMYSQL驱动以连接MySQL数据库。
随后,可利用Qt SQL模块中的类(例如QSqlQuery、QSqlTableModel)执行数据库操作,无需关注数据库特异性。
15.1.4 Qt SQL模块中的主要类与概念
Qt SQL模块包含多个类,用于数据库操作:
QSqlQuery执行SQL查询,
QSqlTableModel和QSqlRelationalTableModel表示和操作数据库表数据,
QSqlQueryModel展示查询结果,
QSqlError处理错误,
QSqlRecord代表访问记录(行),
QSqlField访问字段(列)。
15.1.5 数据库操作基础
在Qt SQL模块中,QSqlQuery类是执行SQL语句的核心工具,它支持创建表、插入记录、查询数据、更新记录、删除记录等操作。
创建表:
QSqlQuery query;
query.exec("CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)");
插入记录:
query.prepare("INSERT INTO users (name, age) VALUES (?, ?)");
query.addBindValue("John Doe"); //按顺序绑定到sql语句占位符
query.addBindValue(30);
query.exec();
查询数据:
query.exec("SELECT * FROM users");
while (query.next()) { int id = query.value("id").toInt(); QString name = query.value("name").toString(); int age = query.value("age").toInt(); qDebug() << "User:" << id << name << age;
}
QSqlQuery query;query.prepare("SELECT * FROM users WHERE username = :username AND password = :password");query.bindValue(":username", username);query.bindValue(":password", password);
在SQL语句中,字符串值应该被单引号(')包围,而不是双引号(")。双引号在SQL中通常用于标识数据库对象(如表名、列名等),而字符串值则应该使用单引号。
SELECT * FROM users WHERE username = '123' AND password = '123';
更新记录:
query.prepare("UPDATE users SET age = ? WHERE id = ?");
query.addBindValue(35);
query.addBindValue(1);
query.exec();
删除记录:
query.prepare("DELETE FROM users WHERE id = ?");
query.addBindValue(1);
query.exec();
使用事务:
QSqlDatabase db = QSqlDatabase::database();
db.transaction(); //数据库启动事务
// 执行数据库操作...
if (/* 操作成功 */) { db.commit();
} else { db.rollback();
}
执行存储过程:
query.prepare("CALL my_stored_procedure(?, ?)");
query.addBindValue("param1");
query.addBindValue("param2");
query.exec();
检查查询是否成功:
if (!query.exec("SELECT * FROM users")) { QSqlError error = query.lastError(); if (error.type() != QSqlError::NoError) { qDebug() << "Error:" << error.text(); }
}
获取查询结果的记录数(如果驱动支持):
int numRows = query.size(); // 可能返回-1表示不支持
如果不支持,则通过遍历计算:
int numRows = 0;
while (query.next()) { numRows++;
}
使用QSqlRecord和QSqlField处理查询结果:
QSqlRecord record = query.record();
while (query.next()) { for (int i = 0; i < record.count(); ++i) { QSqlField field = record.field(i); qDebug() << "Field:" << field.name() << "Value:" << query.value(i); }
}
15.2 使用QSqlTableModel
使用QSqlTableModel实例与数据库表关联并检索数据:
QSqlTableModel model;
model.setTable("users");
model.select(); // 遍历并显示数据
//遍历行
for (int row = 0; row < model.rowCount(); ++row) { //遍历列for (int col = 0; col < model.columnCount(); ++col) { //获取行列位置的索引QModelIndex index = model.index(row, col); qDebug() << "Row:" << row << "Col:" << col << "Value:" << model.data(index); }
}
上例创建了一个QSqlTableModel实例,将其与users表关联,检索所有记录,并遍历显示每个单元格的值。
15.2 使用QSqlQueryModel
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), tableView(nullptr), model(nullptr) { // 初始化数据库连接 QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); db.setHostName("localhost"); // SQLite 通常不需要主机名,但这里保留以防其他数据库 db.setDatabaseName("testdb.db"); // 设置数据库文件名 // SQLite 默认不需要用户名和密码,以下两行通常不需要 // db.setUserName("hebbe"); // db.setPassword("123456"); if (!db.open()) { // 如果数据库连接失败,输出错误信息并返回 qWarning() << "Failed to connect to database:" << db.lastError().text(); return; } // 创建并设置QTableView tableView = new QTableView(this); setCentralWidget(tableView); // 创建QSqlQueryModel并执行查询 model = new QSqlQueryModel(this); model->setQuery("SELECT * FROM table1;"); // 执行查询,请确保表名正确 // 检查查询模型是否有错误 if (model->lastError().isValid()) { // 如果有错误,输出错误信息并返回 qWarning() << "Query model error:" << model->lastError().text(); return; } // 将模型与QTableView关联 tableView->setModel(model); /*可以验证,模型和View关联后,model改变,view自动改变*///model->setQuery("SELECT * FROM table1 limit1;"); // 执行查询,请确保表名正确 // 调整列宽以显示内容 tableView->resizeColumnsToContents(); // 输出模型行数,验证数据加载情况 qDebug() << "Model row count:" << model->rowCount(); // 输出连接成功信息 qDebug("ok");
} MainWindow::~MainWindow() { // 析构函数,用于清理资源(当前无特殊资源需清理)
}

15.3 使用QSqlRelationalTableModel
使用QSqlRelationalTableModel实例与数据库表关联并设置外键关系。
QSqlRelationalTableModel model;
model.setTable("orders"); //设置模型将操作的数据库表名为"orders"
// 将orders表的user_id列与users表的id列关联,显示name列
model.setRelation(1, //关联的列索引 QSqlRelation("users", //关联的表名"id", //关联表的主键"name")); //关联表的关联列名
model.select(); //执行查询// 遍历并显示数据
for (int row = 0; row < model.rowCount(); ++row) { for (int col = 0; col < model.columnCount(); ++col) { QModelIndex index = model.index(row, col); qDebug() << "Row:" << row << "Col:" << col << "Value:" << model.data(index); }
}
15.4 数据库表关系处理
关系数据库设计中,表之间的关系至关重要,涉及引用、约束和联接。
使用Qt SQL模块时,可以处理这些数据库表关系。
15.4.1 外键约束
外键是数据库约束,确保数据间存在对应记录,常表现为“一对多”关系。
在Qt SQL中,QSqlRelationalTableModel类用于处理此类外键关系。
以下是一个具有外键关系的表结构示例:
| users表 | id(主键) | name | age | |
|---|---|---|---|---|
| orders表 | id(主键) | user_id(外键) | product | price |
orders 表的 user_id 列是 users 表的 id 列的外键。
这意味着 orders 表中的每个记录必须与 users 表中的一个记录相关联。
15.4.2 使用 QSqlRelation
QSqlRelation 类表示两个表之间的外键关系。
QSqlRelation relation("user_id", //users表的属性"id", //外键表orders表的主键列名"name"); //外键表中要绑定的列名
15.4.3 在 QSqlRelationalTableModel 中设置表关系
在设置 QSqlRelationalTableModel 时,可以使用 QSqlRelation 实例设置表关系。
QSqlRelationalTableModel model;
model.setTable("orders"); //表示我要设置这个表
model.setRelation(1, QSqlRelation("users", "id", "name")); //设置外键关系
model.select(); //执行
15.4.4 使用QSqlQueryModel与Model/View框架
QSqlQueryModel是Qt SQL模块中的类,用于处理查询结果并继承自QAbstractTableModel。
它可将SQL查询结果与视图组件关联,实现数据灵活展示。
创建并设置 QSqlQueryModel
要使用QSqlQueryModel,先创建实例并执行SQL查询,可将此过程放在实例创建时或之后。
QSqlQueryModel model("SELECT * FROM users"); // 创建时查询
// 或
QSqlQueryModel model;
model.setQuery("SELECT * FROM users"); // 创建后查询
接着,将QSqlQueryModel与视图组件(如QTableView)关联:
QTableView view;
view.setModel(&model); //关联视图组件和QSqlQueryModel
view.show();
对于复杂查询,如联接,QSqlQueryModel同样适用:
QSqlQueryModel model;
//查询,关联查询
model.setQuery("SELECT users.name, orders.product, orders.price FROM users INNER JOIN orders ON users.id = orders.user_id");
QTableView view; //视图组件
view.setModel(&model); //关联视图组件和QSqlQueryModel
view.show();
相关文章:
QT开发--QT SQL模块
第十五章 QT SQL模块 15.1 QT SQL模块概览 Qt SQL模块是Qt框架中操作数据库的组件,提供易用API,支持SQLite、MySQL等多种数据库。它包含数据库驱动与连接功能。 15.1.1 QSqlDatabase 类 在Qt SQL模块中,数据库驱动基于QSqlDriver类…...
如何保证接口幂等性?
一、什么是接口幂等性? 幂等性是指:同一请求,执行很多次,最终结果都一样。 二、为什么会产生接口幂等性问题? 那么,什么情况下,会产生接口幂等性的问题呢? 网络波动, 可能会引起重…...
【9718】基于springboot+vue的生鲜交易系统
作者主页:Java码库 主营内容:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 项目描述 生鲜交易管理方面的任务繁琐,以至于交易市场每年都在生…...
Spring循环依赖解决方案
解决方案 使用提前暴露机制三级缓存进行解决 singletonObjects一级缓存,存放完整的 Bean。earlySingletonObjects二级缓存,存放提前暴露的Bean,Bean 是不完整的,未完成属性注入和执行 init 方法。singletonFactories三级缓存(用…...
解决 IntelliJ IDEA 运行时 “Command line is too long“ 问题
文章目录 文章标题:解决 IntelliJ IDEA 运行时 "Command line is too long" 问题简介问题描述解决方案代码示例代码示例1:使用JAR Manifest代码示例2:使用Classpath File代码示例3:优化项目依赖 结论进一步的资源 文章标…...
鸿蒙网络编程系列5-TCP连接超时分析
1. TCP连接超时简介 TCP是面向连接的协议,通过三次握手建立连接,但是,在建立连接的过程中对方有可能没有响应,这时候发起连接的一方会重试,如果重试多次仍然没有响应,就会触发超时,从而导致连接…...
金蝶云星空移动字段后关闭页面后重新打开无效
有同事反馈,单据的明细字段里面移动了字段,然后退出,其他字段都能按最后排版的位置显示,有个别字段始终无法按照排版的位置显示。 只需要打开BOS平台,找到对应字段,然后更改可见性。...
幂律分布笔记
一、幂律分布的数据拟合 数据分箱: 所谓分箱就是对原始数据进行分组,然后对每一组内的数据进行平滑处理。常见的分箱方式主要有等深分箱、等宽分箱、用户自定义等 对数分箱: 对原数据进行分箱,第i个箱的宽度为bi,b…...
一些NLP代表性模型
(一)BERT 由Bidirectional Encoder Representations from Transformers的首字母组成,是encoder-only结构类型的代表。 模型分预训练和微调两步,预训练任务有两类:masked language model(MLM)、next sentence predict…...
低代码移动端开发:未来的趋势与挑战
什么是低代码移动端开发? 低代码移动端开发平台允许开发者通过可视化界面和少量编码来构建应用程序。相较于传统的代码开发,低代码平台大大降低了技术和学习门槛,使非专业开发人员也能参与到移动应用的开发过程中。 低代码移动端开发的优势 …...
【Linux】嵌入式Linux系统的组成、u-boot编译
Linux—嵌入式Linux系统的组成、u-boot编译 前言一、嵌入式Linux系统的组成1.1 嵌入式Linux系统和PC完整的操作系统的对比如下:1.2 PC机—Windows系统启动流程(PC机—Linux系统、嵌入式ARM—linux系统的启动流程类似) 二、编译u-boot2.1 u-bo…...
Qt打开excel文件,并读取指定单元格数据
1. 下载并安装QXlsx库,详见之前的博文Qt子线程创建excel文件报错QObject: Cannot create children for a parent that is in a different thread.-CSDN博客 2. // 创建一个XlsxDocument对象QString filename "D:\\mydocuments\\data_acquisition\\data\\tes…...
适合下班回家做的小副业,用AI做视频,几天时间3000+
大家好,今天要给大家分享的项目是定制儿歌,精准定位宝妈群体,每天轻松赚500! ***01* 项目原理 父母都非常疼爱自己的孩子,愿意为孩子提供独特的东西。而我们正是利用这一点,通过免费AI工具生成专属的儿童…...
git的基本操作 + 分支管理
一、基本操作 1. 修改文件 Git比其他的版本管理器设计得更加优秀,因为Git追踪并管理的是修改,而非文件。 修改一个文件,不管你是添加一行,或者删除一行,还是添加了又删除了,甚至你创建了一个新文件&…...
VRRP
1、VRRP简介 虚拟路由冗余协议 VRRP(Virtual Router Redundancy Protocol)通过把几台路由设备联合组成一台虚拟的路由设备,将虚拟路由设备的IP地址作为用户的默认网关实现与外部网络通信。当网关设备发生故障时(单点故障…...
个人健康系统|个人健康数据管理系统|基于小程序+java的个人健康数据管理系统设计与实现(源码+数据库+文档)
个人健康数据管理系统 目录 基于小程序java的个人健康数据管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取: 博主介绍:✌️大厂码农|毕设布道师…...
R语言统计分析——折线图
参考资料:R语言实战【第2版】 如果将散点图上的点从左到右连接起来,就会得到一个折线图。以基础安装中的Orange数据集为例,展示如下: # 设置绘图参数 opar<-par(no.readonly TRUE) # 画布拆分为1行2列 par(mfrowc(1,2)) # 选…...
前端怎么实现电子签名
电子签名(e-signature)作为一种数字化的签署方式,广泛应用于合同、协议等文件的确认中。随着科技的发展,前端技术也为电子签名的实现提供了便利。本文将探讨在前端如何实现电子签名,包括技术选型、实现步骤及注意事项。…...
数字后端零基础入门系列 | Innovus零基础LAB学习Day1
一 Floorplan 数字IC后端设计如何从零基础快速入门?(内附数字IC后端学习视频) Lab5-1这个lab学习目标很明确——启动Innovus工具并完成设计的导入。 在进入lab之前,我们需要进入我们的FPR工作目录。 其中ic062为个人服务器账户。比如你端…...
鼠标移入盒子,盒子跟随鼠标移动
demo效果: 鼠标移入盒子,按下鼠标,开启移动跟随移动模式,再次按下关闭移动模式 涉及主要属性 在元素上单击鼠标按钮时输出鼠标指针的坐标: var x event.pageX; // 获取水平坐标 var y event.pageY; // 获取垂直坐标元素offsetL…...
为什么92%的Sora 2初学者卡在第4步?——帧一致性崩塌诊断工具包+时间轴锚点校准法
更多请点击: https://kaifayun.com 第一章:Sora 2视频生成的核心原理与环境准备 Sora 2并非OpenAI官方发布的模型,而是社区基于Sora技术理念构建的开源复现与增强框架,其核心依托于时空联合建模的扩散变换器(Spacetim…...
3分钟快速上手:用BetterNCM安装器彻底改造你的网易云音乐
3分钟快速上手:用BetterNCM安装器彻底改造你的网易云音乐 【免费下载链接】BetterNCM-Installer 一键安装 Better 系软件 项目地址: https://gitcode.com/gh_mirrors/be/BetterNCM-Installer 还在使用功能单一的网易云音乐吗?想不想让你的播放器拥…...
AX-MES生产制造管理系统-总览
前言说起 MES 就不得不说 ERP,但是 ERP 大家基本上都知道,MES 就不一定了,常见的 ERP 系统包括 SAP、金蝶、用友等,ERP的流程相对来说也比较统一;MES就不同了,基本上熟悉业务流程的软件公司都可以开发并实施…...
Stitches API完全指南:从基础配置到自定义扩展
Stitches API完全指南:从基础配置到自定义扩展 【免费下载链接】stitches HTML5 Sprite Sheet Generator 项目地址: https://gitcode.com/gh_mirrors/sti/stitches Stitches是一款强大的HTML5 Sprite Sheet Generator,它提供了直观的API接口&…...
Unity安卓构建72小时实战指南:从零到真机运行
1. 这不是“又一本Unity教程”,而是我带三个新人从零上线第一款安卓游戏的真实路径你点开这个标题,大概率正站在两个路口之间:一边是满屏“30天速成Unity”“零基础做爆款”的短视频封面,一边是你刚下载完Unity Hub、卡在Android …...
一次搞懂内存取证:用Volatility3和Cobalt Strike分析工具复现VNCTF‘来一把紧张刺激的CS’
实战内存取证:从Volatility3到Cobalt Strike信标分析全解析 在网络安全事件响应中,内存取证往往是发现高级威胁的最后一道防线。当攻击者使用文件无落地的技术时,传统的磁盘取证可能一无所获,而内存中却保留着攻击行为的完整痕迹。…...
智慧树自动刷课助手:3步告别手动操作的学习效率工具
智慧树自动刷课助手:3步告别手动操作的学习效率工具 【免费下载链接】zhihuishu 智慧树刷课插件,自动播放下一集、1.5倍速度、无声 项目地址: https://gitcode.com/gh_mirrors/zh/zhihuishu 还在为智慧树平台的重复刷课操作而烦恼吗?智…...
开启Python GUI开发新纪元:Tkinter Designer可视化界面自动化生成终极指南
开启Python GUI开发新纪元:Tkinter Designer可视化界面自动化生成终极指南 【免费下载链接】Tkinter-Designer An easy and fast way to create a Python GUI 🐍 项目地址: https://gitcode.com/gh_mirrors/tk/Tkinter-Designer 在Python GUI开发…...
《我看见的世界:李飞飞自传》第1-6章阅读笔记:从移民少女到AI教母的“看见“之旅
前言 当我们谈论人工智能时,我们谈论的是算法、数据、算力,是那些冰冷的代码和复杂的模型。但在《我看见的世界:李飞飞自传》中,李飞飞用她独特的视角告诉我们:AI的本质,是人类对"看见"世界的渴望…...
基于双T振荡器的正弦波LED调光电路设计与实践
1. 项目概述:用双T振荡器实现正弦波LED调光最近在捣鼓一些氛围灯项目,总感觉用单片机PWM做的呼吸灯效果有点“硬”,那种线性的明暗变化看久了难免审美疲劳。于是翻出以前模拟电路的老本行,琢磨着能不能用纯硬件的方式,…...
