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

Qt 中使用 SQLite 数据库的完整指南

SQLite 是一款轻量级、嵌入式的关系型数据库,无需独立的服务器进程,数据以文件形式存储,非常适合桌面和移动端应用的本地数据管理。Qt 通过 Qt SQL 模块提供了对 SQLite 的原生支持,开发者可以轻松实现数据库的增删改查、事务处理等操作。本文将详细介绍如何在 Qt 中集成并使用 SQLite 数据库。


1. 环境配置与准备工作

1.1 启用 Qt SQL 模块

在 Qt 项目文件(.pro)中添加 SQL 模块依赖:

QT += sql

1.2 包含头文件

在代码中引入必要的类:

#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QSqlTableModel>


2. 连接 SQLite 数据库

2.1 创建并打开数据库

QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("my_database.db"); // 数据库文件名(或完整路径)if (!db.open()) {qDebug() << "Error: Failed to open database:" << db.lastError().text();return;
}
  • 说明

    • QSQLITE 是 Qt 内置的 SQLite 驱动名称。

    • 如果文件不存在,SQLite 会自动创建新数据库。

2.2 关闭数据库

db.close(); // 显式关闭连接(通常不需要,程序退出时自动关闭)


3. 执行 SQL 操作

3.1 创建表

QSqlQuery query;
query.exec("CREATE TABLE IF NOT EXISTS users (""id INTEGER PRIMARY KEY AUTOINCREMENT,""name TEXT NOT NULL,""age INTEGER,""email TEXT UNIQUE)");

3.2 插入数据

直接执行 SQL
query.exec("INSERT INTO users (name, age, email) VALUES ('Alice', 30, 'alice@example.com')");
使用预处理语句(防 SQL 注入)
query.prepare("INSERT INTO users (name, age, email) VALUES (?, ?, ?)");
query.addBindValue("Bob");
query.addBindValue(25);
query.addBindValue("bob@example.com");
query.exec();

3.3 查询数据

if (query.exec("SELECT id, name, age FROM users WHERE age > 20")) {while (query.next()) {int id = query.value(0).toInt();QString name = query.value("name").toString();int age = query.value(2).toInt();qDebug() << "User:" << id << name << age;}
} else {qDebug() << "Query error:" << query.lastError().text();
}

3.4 更新与删除数据

// 更新
query.exec("UPDATE users SET age = 31 WHERE name = 'Alice'");// 删除
query.exec("DELETE FROM users WHERE email IS NULL");

4. 事务处理

通过事务确保多个操作的原子性:

db.transaction(); // 开始事务QSqlQuery query;
query.exec("UPDATE account SET balance = balance - 100 WHERE id = 1");
query.exec("UPDATE account SET balance = balance + 100 WHERE id = 2");if (/* 检查操作是否成功 */) {db.commit();   // 提交事务
} else {db.rollback(); // 回滚事务
}

5. 使用模型-视图(Model-View)编程

Qt 提供了 QSqlTableModel 和 QSqlQueryModel,方便将数据库与 UI 组件(如 QTableView)绑定。

5.1 显示表格数据

QSqlTableModel *model = new QSqlTableModel(this);
model->setTable("users");
model->setFilter("age > 20");
model->select();QTableView *view = new QTableView;
view->setModel(model);
view->show();

5.2 编辑并保存修改

model->setEditStrategy(QSqlTableModel::OnManualSubmit);
// 用户通过视图修改数据后调用:
model->submitAll(); // 提交所有更改到数据库

6. 错误处理与调试

6.1 捕获数据库错误

if (!query.exec("INVALID SQL")) {qDebug() << "SQL Error:" << query.lastError().text();qDebug() << "Executed SQL:" << query.lastQuery();
}

6.2 查看支持的数据库驱动

qDebug() << "Available drivers:" << QSqlDatabase::drivers();
// 输出示例:("QSQLITE", "QMYSQL", "QPSQL")

7. 高级技巧与注意事项

7.1 批量插入优化

使用事务加速大批量插入:

db.transaction();
QSqlQuery query;
query.prepare("INSERT INTO users (name) VALUES (?)");
for (const QString &name : namesList) {query.addBindValue(name);query.exec();
}
db.commit();

7.2 多线程访问

  • SQLite 默认不支持多线程同时写入,需通过 QSqlDatabase::cloneDatabase 为每个线程创建独立连接。

  • 在子线程中使用数据库时,确保在子线程内打开连接。

7.3 数据库迁移

  • 使用 user_version 字段管理数据库版本:

    query.exec("PRAGMA user_version = 1"); // 设置版本号
    query.exec("PRAGMA user_version");     // 读取版本号

8. 常见问题解答

Q1:数据库文件被锁定了怎么办?

  • 确保所有 QSqlQuery 和 QSqlDatabase 对象在使用后及时释放。

  • 避免多线程同时写入同一连接。

Q2:如何防止 SQL 注入?

  • 始终使用 prepare() 和 addBindValue() 替代字符串拼接。

Q3:查询性能慢如何优化?

  • 为常用查询字段添加索引。

  • 减少频繁的小事务,合并为批量操作。


9. 完整示例代码

#include <QCoreApplication>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QDebug>int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");db.setDatabaseName("test.db");if (!db.open()) {qDebug() << "Database error:" << db.lastError().text();return -1;}QSqlQuery query;query.exec("CREATE TABLE IF NOT EXISTS books (""id INTEGER PRIMARY KEY,""title TEXT,""author TEXT)");query.prepare("INSERT INTO books (title, author) VALUES (?, ?)");query.addBindValue("Qt Programming");query.addBindValue("John Doe");query.exec();query.exec("SELECT * FROM books");while (query.next()) {qDebug() << "Book:" << query.value("title").toString()<< "by" << query.value("author").toString();}db.close();return a.exec();
}

10. 总结

Qt 的 SQLite 支持使得本地数据管理变得简单高效。核心要点包括:

  • 使用 QSqlDatabase 管理数据库连接。

  • 通过 QSqlQuery 执行 SQL 语句并处理结果。

  • 利用事务保证数据一致性。

  • 结合模型-视图框架快速构建 UI 界面。

官方文档参考

  • Qt SQL Module

  • SQLite 官方文档

相关文章:

Qt 中使用 SQLite 数据库的完整指南

SQLite 是一款轻量级、嵌入式的关系型数据库&#xff0c;无需独立的服务器进程&#xff0c;数据以文件形式存储&#xff0c;非常适合桌面和移动端应用的本地数据管理。Qt 通过 Qt SQL 模块提供了对 SQLite 的原生支持&#xff0c;开发者可以轻松实现数据库的增删改查、事务处理…...

数智化时代的工单管理:从流程驱动到数据驱动-亿发

在数智化时代&#xff0c;工单管理系统已从简单的任务分发工具演变为企业运营的智能中枢。传统工单系统关注流程的线性推进&#xff0c;而现代工单管理系统则强调数据的全生命周期管理&#xff0c;通过智能算法实现工单的自动分配、优先级判定和效能优化。这种转变不仅提升了运…...

Large Language Model Distilling Medication Recommendation Model

摘要&#xff1a;药物推荐是智能医疗系统的一个重要方面&#xff0c;因为它涉及根据患者的特定健康需求开具最合适的药物。不幸的是&#xff0c;目前使用的许多复杂模型往往忽视医疗数据的细微语义&#xff0c;而仅仅严重依赖于标识信息。此外&#xff0c;这些模型在处理首次就…...

floodfill算法系列一>被围绕的区域

目录 整体思想&#xff1a;代码设计&#xff1a;代码呈现&#xff1a; 整体思想&#xff1a; 代码设计&#xff1a; 代码呈现&#xff1a; class Solution {int m,n;int[] dx {0,0,-1,1};int[] dy {-1,1,0,0};public void solve(char[][] board) {m board.length;n board[…...

Redis 01 02章——入门概述与安装配置

一、入门概述 &#xff08;1&#xff09;是什么 Redis&#xff1a;REmote Dictionary Server&#xff08;远程字典服务器&#xff09;官网解释&#xff1a;Remote Dictionary Server(远程字典服务)是完全开源的&#xff0c;使用ANSIC语言编写遵守BSD协议&#xff0c;是一个高…...

windows基于cpu安装pytorch运行faster-whisper-large-v3实现语音转文字

1.创建虚拟环境 conda create -n faster-whisper python3.10 conda activate faster-whisper 2.安装cpu版本的pytorch pip3 install torch torchvision torchaudio -i https://pypi.tuna.tsinghua.edu.cn/simple 3.验证pytorch安装结果 (faster-whisper) H:\big-model\faste…...

AI大模型(如GPT、BERT等)可以通过自然语言处理(NLP)和机器学习技术,显著提升测试效率

在软件测试中,AI大模型(如GPT、BERT等)可以通过自然语言处理(NLP)和机器学习技术,显著提升测试效率。以下是几个具体的应用场景及对应的代码实现示例: 1. 自动生成测试用例 AI大模型可以根据需求文档或用户故事自动生成测试用例。 代码示例(使用 OpenAI GPT API): …...

【Prometheus】prometheus黑盒监控balckbox全面解析与应用实战

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全…...

CSS实现单行、多行文本溢出显示省略号(…)

在网页设计中&#xff0c;我们常常遇到这样的情况&#xff1a;文本内容太长&#xff0c;无法完全显示在一个固定的区域内。为了让界面看起来更整洁&#xff0c;我们可以使用省略号&#xff08;…&#xff09;来表示内容溢出。这不仅能提升用户体验&#xff0c;还能避免内容溢出…...

服务器中部署大模型DeepSeek-R1 | 本地部署DeepSeek-R1大模型 | deepseek-r1部署详细教程

0. 部署前的准备 首先我们需要足够算力的机器&#xff0c;这里我在vultr中租了有一张A16显卡一共16GB显存的服务器作为演示。部署的模型参数为14b的。如果需要部署满血版本671b的&#xff0c;需要更大的算力支持&#xff0c;这里由于是个人资金有限&#xff0c;就演示14b的部署…...

元学习之孪生网络Siamese Network

简介&#xff1a;元学习是一种思想&#xff0c;一般以神经网络作为特征嵌入的工具&#xff0c;实现对数据特征的提取&#xff0c;然后通过构造某种指标以引导优化器对模型参数进行优化。而最小化距离是最常见的学习目标&#xff0c;这就是熟知的度量学习&#xff0c;度量学习里…...

深入HBase——引入

引入 前面我们通过深入HDFS到深入MapReduce &#xff0c;从设计和落地&#xff0c;去深入了解了大数据最底层的基石——存储与计算是如何实现的。 这个专栏则开始来看大数据的三驾马车中最后一个。 通过前面我们对于GFS和MapReduce论文实现的了解&#xff0c;我们知道GFS在数…...

Python创建FastApi项目模板

1. 项目结构规范 myproject/ ├── app/ │ ├── core/ # 核心配置 │ │ ├── config.py # 环境配置 │ │ └── security.py # 安全配置 │ ├── routers/ # 路由模块 │ │ └── users.py # 用户路由 │ ├…...

TCNE 网络安全

一.概况 CTF&#xff08;Capture The Flag&#xff09;在网络安全领域中指的是网络技术人员之间进行技术竞技的一种比赛形式&#xff0c;它起源于1996年的DEFCON全球黑客大会&#xff0c;以代替之前黑客们通过互相发起真实攻击进行技术比拼的方式&#xff0c;现已成为全球范围网…...

车规MCU处理器选择Cortex-M7还是Cortex-R52?

车规mcu处理器选择Cortex-M7还是Cortex-R52&#xff1f;跟随小编从具体应用场景、安全等级&#xff08;ASIL&#xff09;、性能、成本进行分析吧。 01安全等级需求 ASIL-D&#xff08;如刹车、转向&#xff09;→ 必选R52。R52原生支持ASIL-D&#xff0c;硬件级错误检测&#…...

什么是计算机中的 “终端”?

在我们初学编程的时候&#xff0c;会遇到一个很重要的概念 ——终端。那它到底是什么呢&#xff1f; 在计算机领域&#xff0c;终端就像是我们和计算机进行对话的 “窗口”。我们可以在这个窗口里&#xff0c;用一些特定的命令来告诉计算机该做什么。比如&#xff0c;让计算机…...

LeetCode刷题---字符串---819

最常见的单词 819. 最常见的单词 - 力扣&#xff08;LeetCode&#xff09; 题目&#xff1a; 给你一个字符串 paragraph 和一个表示禁用词的字符串数组 banned &#xff0c;返回出现频率最高的非禁用词。题目数据 保证 至少存在一个非禁用词&#xff0c;且答案 唯一 。 par…...

SSH IBM AIX服务器相关指标解读

&#xff08;一&#xff09;ZPU使用率 含义 在IBM AIX服务器中&#xff0c;ZPU使用率反映了特定处理单元&#xff08;ZPU&#xff0c;假设是某种自定义或特定环境下的处理单元&#xff09;的资源利用程度。它表示ZPU在一段时间内处于忙碌状态执行任务的时间比例。例如&#xff…...

Wireshark TS | 再谈虚假的 TCP Spurious Retransmission

前言 在之前的《虚假的 TCP Spurious Retransmission》文章中曾提到一个错误判断为 TCP Spurious Retransmission&#xff0c;实际为 TCP Out-Of-Order 的案例&#xff0c;本次继续探讨一个虚假的 TCP Spurious Retransmission 案例。 问题背景 TCP Spurious Retransmission…...

基于kafka、celery的日志收集报警项目

项目环境&#xff1a;centOS7.9 mariadb5.6 celery5.0 kafka3.6.1 项目时间&#xff1a;2025年1月 项目描述&#xff1a;这个项目搭建了一个基于 Nginx 和 Flask 的 Web 集群&#xff0c;使用 Filebeat 将 Nginx 的访问日志发送到 Kafka 集群。通过 Python 消费者程序解析日志…...

【Java学习笔记】Arrays类

Arrays 类 1. 导入包&#xff1a;import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序&#xff08;自然排序和定制排序&#xff09;Arrays.binarySearch()通过二分搜索法进行查找&#xff08;前提&#xff1a;数组是…...

UE5 学习系列(三)创建和移动物体

这篇博客是该系列的第三篇&#xff0c;是在之前两篇博客的基础上展开&#xff0c;主要介绍如何在操作界面中创建和拖动物体&#xff0c;这篇博客跟随的视频链接如下&#xff1a; B 站视频&#xff1a;s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

第25节 Node.js 断言测试

Node.js的assert模块主要用于编写程序的单元测试时使用&#xff0c;通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试&#xff0c;通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...

多种风格导航菜单 HTML 实现(附源码)

下面我将为您展示 6 种不同风格的导航菜单实现&#xff0c;每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...

GitFlow 工作模式(详解)

今天再学项目的过程中遇到使用gitflow模式管理代码&#xff0c;因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存&#xff0c;无论是github还是gittee&#xff0c;都是一种基于git去保存代码的形式&#xff0c;这样保存代码…...

【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制

使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下&#xff0c;限制某个 IP 的访问频率是非常重要的&#xff0c;可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案&#xff0c;使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...

MySQL JOIN 表过多的优化思路

当 MySQL 查询涉及大量表 JOIN 时&#xff0c;性能会显著下降。以下是优化思路和简易实现方法&#xff1a; 一、核心优化思路 减少 JOIN 数量 数据冗余&#xff1a;添加必要的冗余字段&#xff08;如订单表直接存储用户名&#xff09;合并表&#xff1a;将频繁关联的小表合并成…...

tomcat指定使用的jdk版本

说明 有时候需要对tomcat配置指定的jdk版本号&#xff0c;此时&#xff0c;我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...

6️⃣Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙

Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙 一、前言:离区块链还有多远? 区块链听起来可能遥不可及,似乎是只有密码学专家和资深工程师才能涉足的领域。但事实上,构建一个区块链的核心并不复杂,尤其当你已经掌握了一门系统编程语言,比如 Go。 要真正理解区…...

32单片机——基本定时器

STM32F103有众多的定时器&#xff0c;其中包括2个基本定时器&#xff08;TIM6和TIM7&#xff09;、4个通用定时器&#xff08;TIM2~TIM5&#xff09;、2个高级控制定时器&#xff08;TIM1和TIM8&#xff09;&#xff0c;这些定时器彼此完全独立&#xff0c;不共享任何资源 1、定…...