Qt 与 SQLite 的结合是开发轻量级、跨平台嵌入式数据库应用的理想选择。SQLite 作为一种零配置、文件型数据库,无需独立的服务器进程,非常适合集成到 Qt 应用中。本文将深入探讨 Qt 与 SQLite 的嵌入式数据库开发,包括基础操作、高级特性、性能优化和实际应用案例。

一、SQLite 基础配置与连接

1. 驱动检查与数据库连接
#include <QSqlDatabase>
#include <QSqlError>
#include <QDebug>void connectToSQLite() {// 检查 SQLite 驱动是否可用if (!QSqlDatabase::isDriverAvailable("QSQLITE")) {qDebug() << "SQLite driver not available!";return;}// 创建数据库连接QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");db.setDatabaseName("mydatabase.db");  // 数据库文件名if (!db.open()) {qDebug() << "Cannot open database:" << db.lastError().text();return;}qDebug() << "SQLite database connected successfully!";
}
2. 创建表结构
void createTables(QSqlDatabase &db) {QSqlQuery query(db);// 创建用户表query.exec(R"(CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT NOT NULL,age INTEGER,email TEXT UNIQUE))");if (query.lastError().isValid()) {qDebug() << "Error creating table:" << query.lastError().text();}// 创建订单表query.exec(R"(CREATE TABLE IF NOT EXISTS orders (id INTEGER PRIMARY KEY AUTOINCREMENT,user_id INTEGER NOT NULL,product TEXT,price REAL,order_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,FOREIGN KEY (user_id) REFERENCES users(id)))");
}

二、数据操作与查询

1. 插入数据
void insertData(QSqlDatabase &db) {QSqlQuery query(db);// 插入用户数据query.prepare("INSERT INTO users (name, age, email) VALUES (:name, :age, :email)");query.bindValue(":name", "Alice");query.bindValue(":age", 30);query.bindValue(":email", "alice@example.com");if (query.exec()) {qDebug() << "User inserted successfully!";} else {qDebug() << "Error inserting user:" << query.lastError().text();}// 批量插入订单数据db.transaction();  // 使用事务提高性能QList<QVariantList> orders = {{1, "Product A", 99.99},{1, "Product B", 49.99},{1, "Product C", 199.99}};query.prepare("INSERT INTO orders (user_id, product, price) VALUES (:user_id, :product, :price)");for (const auto &order : orders) {query.bindValue(":user_id", order[0]);query.bindValue(":product", order[1]);query.bindValue(":price", order[2]);query.exec();}db.commit();
}
2. 查询数据
void queryData(QSqlDatabase &db) {// 简单查询QSqlQuery query("SELECT * FROM users", db);while (query.next()) {int id = query.value("id").toInt();QString name = query.value("name").toString();int age = query.value("age").toInt();QString email = query.value("email").toString();qDebug() << "User:" << id << name << age << email;}// 带参数的查询query.prepare("SELECT * FROM orders WHERE user_id = :user_id AND price > :min_price");query.bindValue(":user_id", 1);query.bindValue(":min_price", 50.0);if (query.exec()) {while (query.next()) {QString product = query.value("product").toString();double price = query.value("price").toDouble();QDateTime date = query.value("order_date").toDateTime();qDebug() << "Order:" << product << price << date.toString("yyyy-MM-dd");}}
}

三、高级特性与优化

1. 事务处理
bool transferMoney(QSqlDatabase &db, int fromAccount, int toAccount, double amount) {db.transaction();try {QSqlQuery query(db);// 减少源账户余额query.prepare("UPDATE accounts SET balance = balance - :amount WHERE id = :id");query.bindValue(":amount", amount);query.bindValue(":id", fromAccount);if (!query.exec() || query.numRowsAffected() == 0) {throw std::runtime_error("Failed to debit from source account");}// 增加目标账户余额query.prepare("UPDATE accounts SET balance = balance + :amount WHERE id = :id");query.bindValue(":amount", amount);query.bindValue(":id", toAccount);if (!query.exec() || query.numRowsAffected() == 0) {throw std::runtime_error("Failed to credit to target account");}db.commit();return true;} catch (const std::exception &e) {db.rollback();qDebug() << "Transaction failed:" << e.what();return false;}
}
2. 索引优化
void createIndex(QSqlDatabase &db) {QSqlQuery query(db);// 创建索引提高查询性能query.exec("CREATE INDEX IF NOT EXISTS idx_orders_user_id ON orders (user_id)");query.exec("CREATE INDEX IF NOT EXISTS idx_orders_price ON orders (price)");// 创建复合索引query.exec("CREATE INDEX IF NOT EXISTS idx_users_name_age ON users (name, age)");
}
3. 外键约束
void enableForeignKeys(QSqlDatabase &db) {QSqlQuery query(db);// 启用外键约束(SQLite 默认禁用)query.exec("PRAGMA foreign_keys = ON");if (query.lastError().isValid()) {qDebug() << "Failed to enable foreign keys:" << query.lastError().text();}
}

四、SQLite 特定功能

1. 数据库加密(使用 SQLCipher)
void openEncryptedDatabase(const QString &dbPath, const QString &password) {QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");db.setDatabaseName(dbPath);// 设置加密密钥db.setConnectOptions("QSQLITE_ENABLE_REGEXP=1;QSQLITE_PWD=" + password);if (!db.open()) {qDebug() << "Cannot open encrypted database:" << db.lastError().text();return;}qDebug() << "Encrypted database opened successfully!";
}
2. 全文搜索
void createFtsTable(QSqlDatabase &db) {QSqlQuery query(db);// 创建 FTS5 全文搜索表query.exec(R"(CREATE VIRTUAL TABLE IF NOT EXISTS notes USING fts5(title,content,tags))");// 插入测试数据query.prepare("INSERT INTO notes (title, content, tags) VALUES (:title, :content, :tags)");query.bindValue(":title", "Qt Development");query.bindValue(":content", "Learn Qt with SQLite for embedded applications");query.bindValue(":tags", "Qt,SQLite,Embedded");query.exec();
}void searchFtsTable(QSqlDatabase &db, const QString &keyword) {QSqlQuery query(db);query.prepare("SELECT * FROM notes WHERE content MATCH :keyword");query.bindValue(":keyword", keyword);if (query.exec()) {while (query.next()) {QString title = query.value("title").toString();QString content = query.value("content").toString();qDebug() << "Search result:" << title << content.left(50) + "...";}}
}

五、性能优化策略

1. 批量操作优化
void batchInsertOptimized(QSqlDatabase &db, const QList<QVariantList> &data) {db.transaction();QSqlQuery query(db);query.prepare("INSERT INTO large_table (col1, col2, col3) VALUES (:val1, :val2, :val3)");// 使用预处理语句和事务进行批量插入for (const auto &row : data) {query.bindValue(":val1", row[0]);query.bindValue(":val2", row[1]);query.bindValue(":val3", row[2]);query.exec();}db.commit();
}
2. 内存管理优化
void optimizeMemoryUsage(QSqlDatabase &db) {QSqlQuery query(db);// 设置页面大小query.exec("PRAGMA page_size = 4096");// 设置缓存大小(以页面为单位)query.exec("PRAGMA cache_size = -2000");  // 负值表示 KiB,此处为 2000 KiB// 优化写入性能query.exec("PRAGMA synchronous = NORMAL");// 启用 WAL 模式query.exec("PRAGMA journal_mode = WAL");
}

六、错误处理与恢复

1. 错误处理机制
bool executeSafely(QSqlQuery &query, const QString &sql, const QVariantMap &bindValues = {}) {query.prepare(sql);// 绑定参数for (auto it = bindValues.begin(); it != bindValues.end(); ++it) {query.bindValue(it.key(), it.value());}if (!query.exec()) {qDebug() << "SQL execution error:" << query.lastError().text();qDebug() << "Failed query:" << sql;return false;}return true;
}
2. 数据库恢复
bool backupDatabase(const QString &sourceDb, const QString &targetDb) {QSqlDatabase srcDb = QSqlDatabase::addDatabase("QSQLITE", "sourceConnection");srcDb.setDatabaseName(sourceDb);if (!srcDb.open()) {qDebug() << "Cannot open source database:" << srcDb.lastError().text();return false;}QSqlDatabase destDb = QSqlDatabase::addDatabase("QSQLITE", "targetConnection");destDb.setDatabaseName(targetDb);if (!destDb.open()) {qDebug() << "Cannot open target database:" << destDb.lastError().text();srcDb.close();return false;}// 使用 SQLite 的备份 APIQSqlQuery query(srcDb);query.exec("BACKUP TO '" + targetDb + "'");srcDb.close();destDb.close();return true;
}

七、ORM 框架集成

1. 简单 ORM 实现
class Note {
public:int id;QString title;QString content;QDateTime created;// 从记录创建对象static Note fromRecord(const QSqlRecord &record) {Note note;note.id = record.value("id").toInt();note.title = record.value("title").toString();note.content = record.value("content").toString();note.created = record.value("created").toDateTime();return note;}// 保存到数据库bool save(QSqlDatabase &db) {QSqlQuery query(db);if (id <= 0) {// 插入新记录query.prepare("INSERT INTO notes (title, content, created) VALUES (:title, :content, :created)");query.bindValue(":title", title);query.bindValue(":content", content);query.bindValue(":created", created.isValid() ? created : QDateTime::currentDateTime());if (query.exec()) {id = query.lastInsertId().toInt();return true;}} else {// 更新现有记录query.prepare("UPDATE notes SET title = :title, content = :content WHERE id = :id");query.bindValue(":title", title);query.bindValue(":content", content);query.bindValue(":id", id);return query.exec();}return false;}
};

八、实际应用案例

1. 嵌入式设备数据记录
class DataLogger {
public:DataLogger(const QString &dbPath) {db = QSqlDatabase::addDatabase("QSQLITE");db.setDatabaseName(dbPath);if (!db.open()) {qDebug() << "Failed to open database:" << db.lastError().text();} else {createTables();}}void logSensorData(const QString &sensorId, double value) {if (!db.isOpen()) return;QSqlQuery query(db);query.prepare("INSERT INTO sensor_data (sensor_id, value, timestamp) VALUES (:sensor_id, :value, :timestamp)");query.bindValue(":sensor_id", sensorId);query.bindValue(":value", value);query.bindValue(":timestamp", QDateTime::currentDateTime());query.exec();}private:QSqlDatabase db;void createTables() {QSqlQuery query(db);query.exec(R"(CREATE TABLE IF NOT EXISTS sensor_data (id INTEGER PRIMARY KEY AUTOINCREMENT,sensor_id TEXT NOT NULL,value REAL,timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP))");}
};

九、总结

Qt 与 SQLite 的结合为嵌入式数据库应用开发提供了强大而灵活的解决方案。SQLite 的轻量级特性与 Qt 的跨平台能力相得益彰,使开发者能够轻松构建高效、可靠的数据驱动应用。通过合理使用事务、索引、全文搜索等高级特性,并采用适当的性能优化策略,可以充分发挥 SQLite 在嵌入式环境中的优势。

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

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

相关文章

Oracle OMF 非OMF 文件 转化 不需要重建 file#.incarnation#

不需要重建就要重启&#xff0c; alter database datafile move 就可以在线 file#.incarnation# 是 incarnation 不是dbid Goal How to convert non OMF files to OMF files with ASM storage Datafiles are not deleted at dropping tablespace if files are non-OMF and …

大型微服务项目:听书——11 Redisson分布式布隆过滤器+Redisson分布式锁改造专辑详情接口

11 Redisson分布式布隆过滤器Redisson分布式锁改造专辑详情接口 11.1 缓存穿透解决方案&布隆过滤器 缓存穿透解决方案&#xff1a; 布隆过滤器&#xff1a; 布隆过滤器的使用&#xff1a; 11.2 远程调用查询所有的专辑id集合 修改&#xff1a; /*** 查询所有的专辑…

STM32与ADS1220实现多通道数据采集的完整分析和源程序

以下是基于STM32与ADS1220实现多通道数据采集的完整分析和源程序,结合硬件设计、通信协议及软件优化,提供高精度采集解决方案: 一、系统设计关键要点 ADS1220特性 24位高精度ΔΣ ADC,支持4路单端或2路差分输入 集成PGA(增益1~128)、基准电压和可编程电流源 多通道限制:…

百特搭AI低代码平台助力企业国际化业务敏捷拓展

在全球化浪潮下&#xff0c;企业扬帆出海或服务全球客户已成为重要战略。然而&#xff0c;开拓国际市场面临多重挑战&#xff1a;语言文化差异显著、本地化需求复杂多变、智能化应用需求激增、各国IT基础设施与合规要求各异。企业亟需一个能够快速响应、灵活适应&#xff0c;并…

epoll_event数据结构及使用案例详解

epoll_event 数据结构详解 在 Linux 的 I/O 多路复用机制 epoll 中&#xff0c;epoll_event 是关键的数据结构&#xff0c;用于描述文件描述符&#xff08;fd&#xff09;上的事件和关联数据。其定义在头文件 <sys/epoll.h> 中&#xff1a; struct epoll_event {uint32_t…

C++11STL容器map和set简单介绍

一、引言map和set底层结构比较复杂&#xff0c;我认为我们先谈基本介绍再谈C11&#xff0c;最后再谈map和set底层以及map和set封装。二、简单介绍一下map和setmap和set底层都是红黑树&#xff0c;是二叉搜索树的一种&#xff0c;查找非常快。不像数组、链表一样一个一个对比&am…

Java线程基础面试复习笔记

1. 线程与进程的区别进程是正在运行程序的实例&#xff0c;线程是进程中的执行单元。主要区别&#xff1a; 内存空间&#xff1a;不同进程使用不同的内存空间&#xff0c;同一进程下的线程共享内存空间资源开销&#xff1a;线程更轻量&#xff0c;线程上下文切换成本比进程上下…

面试题(技术面+hr面)

面试技术面HR面后端HR面常见问题*稳定性&#xff0c;上进心&#xff0c;目标感&#xff0c;抗压能力&#xff0c;学习能力*回答问题时注意体现上面五点&#xff0c;即使瞎扯也尽量往上靠。面经项目相关介绍一下你收获最大的一个项目你们团队有多少人&#xff0c;怎么分工的开发…

本地部署Dify教程

克隆 Dify 代码仓库克隆 Dify 源代码至本地。git clone hts://github.com/langgenius/dify.git启动 Dify进入 Dify 源代码的 docker 目录&#xff0c;执行一键启动命令:cd dify/docker #切换到指定目录 cp .env.example .env #修改文件名 docker compose up -d #启动

Android Kotlin 协程全面指南

协程是 Kotlin 提供的一套简化异步编程的轻量级线程操作框架&#xff0c;特别适合 Android 开发中的异步任务处理。以下是 Android 开发中需要掌握的协程核心知识点&#xff1a;1. 协程基础概念1.1 协程是什么轻量级线程&#xff1a;比线程更高效&#xff0c;可以在单个线程中运…

【Linux】进程切换与优先级

前言&#xff1a; 上文我们讲到了操作系统与Linux中进程的状态【Linux】进程状态-CSDN博客 本文我们来讲进程的优先级、以及进程的切换 进程优先级 什么是优先级&#xff1f; CPU中资源是有限的&#xff0c;而进程的数量一定是远大于CPU资源的&#xff0c;所以优先级是进程得…

首发即开源!DAWorkBench数据可视化分析软件正式发布!(附源码下载网址)

1 系统介绍DAWorkBench是一款面向科研实验和工程测试场景的数据可视化分析开源软件&#xff0c;支持实现数据清洗、信号处理和交互式可视化等功能。系统集成文件IO、数据处理以及可视化交互三大模块&#xff0c;支持多维数据分析与高质量图表生成&#xff0c;助力用户高效完成从…

Android Studio历史版本快速下载(二次修改记录)

原版&#xff1a;Android Studio历史版本快速下载_android studio 历史版本下载-CSDN博客 一. 最新版本 https://developer.android.com/studio?hlzh-cn 二. 历史版本 中国官网的历史版本为何不能下载&#xff1f;&#xff08;https://developer.android.com/studio/archi…

The Missing Semester of Your CS Education 学习笔记以及一些拓展知识(六)

文章目录The Missing Semester of Your CS Education 学习笔记以及一些拓展知识版本控制Git笔记部分Git的基本工作原理Git 的核心工作原理&#xff1a;快照而非差异Git 的三大工作区域Git的核心对象Git的四个对象对象之间的关系与工作流程&#xff1a;对象的引用Git的安装和基础…

嵌入式与 Linux 系统中的核心图形库全解析

嵌入式与 Linux 系统中的核心图形库全解析 图形库在嵌入式系统与 Linux 桌面系统中扮演着重要角色。从最底层的 GPU 驱动接口&#xff0c;到上层的图形渲染与 GUI 工具包&#xff0c;共同构成了完整的图形显示栈。本文将系统整理图形相关的核心组件&#xff0c;按功能分层分类&…

深度学习模块实践手册(第十二期)

56、Ghost 模块论文《GhostNet: More Features from Cheap Operations》1、作用&#xff1a; Ghost 模块是一种轻量级的特征提取模块&#xff0c;旨在通过廉价操作生成更多特征图&#xff0c;减少计算量的同时保持模型性能。传统卷积神经网络在生成特征图时存在大量冗余计算&am…

自己动手造轮子:如何创建JAR并通过Maven在Spring Boot中引用

让代码复用变得简单优雅——3分钟学会封装专属工具库作为Java开发者&#xff0c;你是否遇到过这些痛点&#xff1f;多个项目重复编写相同工具类工具代码分散难以统一维护团队协作缺乏标准化工具库本文将手把手教你创建自己的JAR包&#xff0c;并优雅地集成到Spring Boot项目中&…

使用dea工具 给vue 里面的ts打断点

在 Vue 项目中使用 TypeScript 时&#xff0c;我们通常会在 IDE&#xff08;如 JetBrains 的 IntelliJ IDEA 或 WebStorm&#xff09;中设置断点进行调试。以下是详细步骤&#xff1a; 准备工作 确保项目已配置 source maps&#xff08;Vue CLI 创建的项目默认已配置&#xff0…

Zabbix 企业级分布式监控

目录 简介 一、监控系统基础 1.1 监控的价值 1.2 监控的 5 大类型与 5 大层次 1.3 监控系统的实现原理 二、Zabbix&#xff1a;企业级监控方案 2.1 Zabbix 简介 2.2 Zabbix 核心功能特性 2.3 Zabbix 角色与架构 三、Zabbix 部署案例 3.1 资源清单 3.2 基础环境配置…

SQL JOIN 全解析:用 `users` 与 `orders` 表彻底掌握内连接、左连接、右连接

SQL JOIN 全解析&#xff1a;用 users 与 orders 表彻底掌握内连接、左连接、右连接 在日常开发中&#xff0c;SQL 的连接&#xff08;JOIN&#xff09;语句是数据库查询的核心技能。尤其在多表联合查询时&#xff0c;不掌握好 INNER JOIN、LEFT JOIN、RIGHT JOIN&#xff0c;…