当前位置: 首页 > news >正文

QT开发--QT SQL模块

第十五章 QT SQL模块

15.1 QT SQL模块概览

        Qt SQL模块是Qt框架中操作数据库的组件,提供易用API,支持SQLite、MySQL等多种数据库。它包含数据库驱动与连接功能。

15.1.1 QSqlDatabase 类

        在Qt SQL模块中,数据库驱动基于QSqlDriver类,可通过继承创建自定义驱动。

        使用QSqlDatabasestatic 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提供相应数据库驱动插件。以下是部分支持的数据库类型及驱动名称。

序号驱动名称数据库系统驱动说明
1QSQLITESQLite支持 SQLite3 数据库系统
2QMYSQLMySQL支持 MySQL 数据库系统
3QPSQLPostgreSQL支持 PostgreSQL 数据库系统
4QODBCODBC支持 ODBC 驱动,包括微软的 SQL Server
5QOCIOracle支持 Oracle 调用接口驱动
6QIBASEInterBase支持 Borland InterBase 驱动,适用于嵌入式和跨平台数据库应用
7QDB2IBM DB2支持 IBM DB2 数据库系统

        这些驱动名可以在创建 QSqlDatabase 实例时指定,例如:

QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");

        在此例中,我们添加了QMYSQL驱动以连接MySQL数据库。

        随后,可利用Qt SQL模块中的类(例如QSqlQuery、QSqlTableModel)执行数据库操作,无需关注数据库特异性。

15.1.4 Qt SQL模块中的主要类与概念

        Qt SQL模块包含多个类,用于数据库操作:

        QSqlQuery执行SQL查询

        QSqlTableModelQSqlRelationalTableModel表示和操作数据库表数据

        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++;  
}

使用QSqlRecordQSqlField处理查询结果

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(主键)nameage
orders表id(主键)user_id(外键)productprice

        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框架中操作数据库的组件&#xff0c;提供易用API&#xff0c;支持SQLite、MySQL等多种数据库。它包含数据库驱动与连接功能。 15.1.1 QSqlDatabase 类 在Qt SQL模块中&#xff0c;数据库驱动基于QSqlDriver类&#xf…...

如何保证接口幂等性?

一、什么是接口幂等性&#xff1f; 幂等性是指&#xff1a;同一请求&#xff0c;执行很多次&#xff0c;最终结果都一样。 二、为什么会产生接口幂等性问题&#xff1f; 那么&#xff0c;什么情况下&#xff0c;会产生接口幂等性的问题呢&#xff1f; 网络波动, 可能会引起重…...

【9718】基于springboot+vue的生鲜交易系统

作者主页&#xff1a;Java码库 主营内容&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 项目描述 生鲜交易管理方面的任务繁琐,以至于交易市场每年都在生…...

Spring循环依赖解决方案

解决方案 使用提前暴露机制三级缓存进行解决 singletonObjects一级缓存&#xff0c;存放完整的 Bean。earlySingletonObjects二级缓存&#xff0c;存放提前暴露的Bean&#xff0c;Bean 是不完整的&#xff0c;未完成属性注入和执行 init 方法。singletonFactories三级缓存(用…...

解决 IntelliJ IDEA 运行时 “Command line is too long“ 问题

文章目录 文章标题&#xff1a;解决 IntelliJ IDEA 运行时 "Command line is too long" 问题简介问题描述解决方案代码示例代码示例1&#xff1a;使用JAR Manifest代码示例2&#xff1a;使用Classpath File代码示例3&#xff1a;优化项目依赖 结论进一步的资源 文章标…...

鸿蒙网络编程系列5-TCP连接超时分析

1. TCP连接超时简介 TCP是面向连接的协议&#xff0c;通过三次握手建立连接&#xff0c;但是&#xff0c;在建立连接的过程中对方有可能没有响应&#xff0c;这时候发起连接的一方会重试&#xff0c;如果重试多次仍然没有响应&#xff0c;就会触发超时&#xff0c;从而导致连接…...

金蝶云星空移动字段后关闭页面后重新打开无效

有同事反馈&#xff0c;单据的明细字段里面移动了字段&#xff0c;然后退出&#xff0c;其他字段都能按最后排版的位置显示&#xff0c;有个别字段始终无法按照排版的位置显示。 只需要打开BOS平台&#xff0c;找到对应字段&#xff0c;然后更改可见性。...

幂律分布笔记

一、幂律分布的数据拟合 数据分箱&#xff1a; 所谓分箱就是对原始数据进行分组&#xff0c;然后对每一组内的数据进行平滑处理。常见的分箱方式主要有等深分箱、等宽分箱、用户自定义等 对数分箱&#xff1a; 对原数据进行分箱&#xff0c;第i个箱的宽度为bi&#xff0c;b…...

一些NLP代表性模型

&#xff08;一&#xff09;BERT 由Bidirectional Encoder Representations from Transformers的首字母组成&#xff0c;是encoder-only结构类型的代表。 模型分预训练和微调两步&#xff0c;预训练任务有两类&#xff1a;masked language model(MLM)、next sentence predict…...

低代码移动端开发:未来的趋势与挑战

什么是低代码移动端开发&#xff1f; 低代码移动端开发平台允许开发者通过可视化界面和少量编码来构建应用程序。相较于传统的代码开发&#xff0c;低代码平台大大降低了技术和学习门槛&#xff0c;使非专业开发人员也能参与到移动应用的开发过程中。 低代码移动端开发的优势 …...

【Linux】嵌入式Linux系统的组成、u-boot编译

Linux—嵌入式Linux系统的组成、u-boot编译 前言一、嵌入式Linux系统的组成1.1 嵌入式Linux系统和PC完整的操作系统的对比如下&#xff1a;1.2 PC机—Windows系统启动流程&#xff08;PC机—Linux系统、嵌入式ARM—linux系统的启动流程类似&#xff09; 二、编译u-boot2.1 u-bo…...

Qt打开excel文件,并读取指定单元格数据

1. 下载并安装QXlsx库&#xff0c;详见之前的博文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+

大家好&#xff0c;今天要给大家分享的项目是定制儿歌&#xff0c;精准定位宝妈群体&#xff0c;每天轻松赚500&#xff01; ***01* 项目原理 父母都非常疼爱自己的孩子&#xff0c;愿意为孩子提供独特的东西。而我们正是利用这一点&#xff0c;通过免费AI工具生成专属的儿童…...

git的基本操作 + 分支管理

一、基本操作 1. 修改文件 Git比其他的版本管理器设计得更加优秀&#xff0c;因为Git追踪并管理的是修改&#xff0c;而非文件。 修改一个文件&#xff0c;不管你是添加一行&#xff0c;或者删除一行&#xff0c;还是添加了又删除了&#xff0c;甚至你创建了一个新文件&…...

VRRP

1、VRRP简介 虚拟路由冗余协议 VRRP&#xff08;Virtual Router Redundancy Protocol&#xff09;通过把几台路由设备联合组成一台虚拟的路由设备&#xff0c;将虚拟路由设备的IP地址作为用户的默认网关实现与外部网络通信。当网关设备发生故障时&#xff08;单点故障&#xf…...

个人健康系统|个人健康数据管理系统|基于小程序+java的个人健康数据管理系统设计与实现(源码+数据库+文档)

个人健康数据管理系统 目录 基于小程序java的个人健康数据管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️大厂码农|毕设布道师…...

R语言统计分析——折线图

参考资料&#xff1a;R语言实战【第2版】 如果将散点图上的点从左到右连接起来&#xff0c;就会得到一个折线图。以基础安装中的Orange数据集为例&#xff0c;展示如下&#xff1a; # 设置绘图参数 opar<-par(no.readonly TRUE) # 画布拆分为1行2列 par(mfrowc(1,2)) # 选…...

前端怎么实现电子签名

电子签名&#xff08;e-signature&#xff09;作为一种数字化的签署方式&#xff0c;广泛应用于合同、协议等文件的确认中。随着科技的发展&#xff0c;前端技术也为电子签名的实现提供了便利。本文将探讨在前端如何实现电子签名&#xff0c;包括技术选型、实现步骤及注意事项。…...

数字后端零基础入门系列 | Innovus零基础LAB学习Day1

一 Floorplan 数字IC后端设计如何从零基础快速入门&#xff1f;(内附数字IC后端学习视频&#xff09; Lab5-1这个lab学习目标很明确——启动Innovus工具并完成设计的导入。 在进入lab之前&#xff0c;我们需要进入我们的FPR工作目录。 其中ic062为个人服务器账户。比如你端…...

鼠标移入盒子,盒子跟随鼠标移动

demo效果&#xff1a; 鼠标移入盒子&#xff0c;按下鼠标,开启移动跟随移动模式,再次按下关闭移动模式 涉及主要属性 在元素上单击鼠标按钮时输出鼠标指针的坐标&#xff1a; var x event.pageX; // 获取水平坐标 var y event.pageY; // 获取垂直坐标元素offsetL…...

css的简单问题

1.display:none;和visibility:hidden;的区别 相同点&#xff1a;都可以让元素不可见 区别&#xff1a; display:none;可以让元素完成在渲染树中消失&#xff0c;渲染时不占任何空间&#xff1b;visibility:hidden;不会让元素从渲染树消失&#xff0c;渲染元素继续占据空间&a…...

使⽤ Override 和 New 关键字进⾏版本控制(C#)

文章目录 1. 基础概念1.1 override1.2 new 2. 示例代码1. override 关键字2. new 关键字 3.完整示例测试3.1 基类和派生类的定义3.2 测试代码3.3 运行结果 结论 在 C# 中&#xff0c;override 和 new 关键字用于控制类之间的成员方法的隐藏和重写。理解它们之间的差异和使用场景…...

JavaScript 15章:模块化编程

在现代软件开发中&#xff0c;模块化编程是一种非常重要的实践&#xff0c;它可以帮助开发者组织代码&#xff0c;提高代码的复用性和可维护性。以下是关于模块化编程的一些关键知识点和实战案例&#xff1a; 第15章&#xff1a;模块化编程 模块的概念 模块是指将一组相关的…...

qt creator 开发环境的安装

1.找官网 官网地址&#xff1a;Installation | Qt Creator Documentation 点 Parent Directory 继续点 Parent Directory 点 archive/ 2.下载在线安装器 点 online_ainstallers 选择在线安装器版本 选择对应版本后进入下载列表&#xff0c;根据自己的系统选择下载。 下载后…...

Xilinx远程固件升级(二)——STARTUPE2原语的使用

通过&#xff08;一&#xff09;可以看出&#xff0c;对于远程固件升级实际上是通过调用flash不同区域的bit实现&#xff0c;通过golden image和update image共同保障了系统的稳定性。在项目中如果将flash的时钟直接绑定FPGA后进行约束&#xff0c;在综合编译时是无法通过的。这…...

DynamicExpresso

DynamicExpresso 动态Expression 安装包&#xff1a;DynamicExpresso.Core Student.cs public class Student { public int Age { get; set; } public string Name { get; set; } public void Hello() { Con…...

从Naive RAG到Agentic RAG:基于Milvus构建Agentic RAG

检索增强生成&#xff08;Retrieval-Augmented Generation, RAG&#xff09;作为应用大模型落地的方案之一&#xff0c;通过让 LLM 获取上下文最新数据来解决 LLM 的局限性。典型的应用案例是基于公司特定的文档和知识库开发的聊天机器人&#xff0c;为公司内部人员快速检索内部…...

Linux 环境chrony设置服务器间时间同步一致

服务器&#xff1a; master01: slave02: slave03: 安装chrony安装&#xff1a; yum -y install chrony 设置以master01为时间服务器&#xff0c;其他服务器同步master01时间 master01的chrony.conf配置: server ntp1.aliyun.com iburst allow all local stratum 10重启ch…...

MetaCTO确认将放弃QuestPro2及轻量化头显正在开发中

MetaCTO确认将放弃QuestPro2及轻量化头显正在开发中 随着虚拟现实(VR)和增强现实(AR)技术的不断发展&#xff0c;越来越多的公司开始关注这个领域。其中&#xff0c;QuestPro2是一款备受关注的头戴式显示器&#xff0c;由MetaCTO公司开发。然而&#xff0c;最近MetaCTO公司宣布…...

深度学习 .exp()

在 MXNet 中&#xff0c;.exp() 是 ndarray 对象的方法&#xff0c;用于计算数组中每个元素的指数&#xff08;e 的幂&#xff09;。此方法适用于所有类型的 ndarray&#xff0c;并返回一个新的数组&#xff0c;其中每个元素都是相应输入元素的指数。 语法 ndarray.exp() 参…...