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

使用Qt操作SQLite数据库

目录

      • 一、开发成果
      • 二、环境配置与基础概念
        • 1. 引入SQL模块
        • 2. SQLite数据库特性
      • 三、数据库连接与操作流程
        • 1. 创建并连接数据库
        • 2. 执行SQL语句
        • 3. 查询与遍历数据
      • 四、进阶操作与最佳实践
        • 1. 事务处理
        • 2. 错误处理
        • 3. 使用模型/视图架构
      • 五、完整代码示例(学生人员管理)
        • 1.mainwindow.h
        • 2.mainwindow.cpp
        • 3.main.cpp
      • 六、常见问题与优化建议
        • 1. 连接管理:
        • 2. 性能优化:

一、开发成果

在这里插入图片描述

二、环境配置与基础概念

1. 引入SQL模块

在Qt项目文件(.pro)中添加SQL模块支持,这是操作数据库的前提:

QT += sql

该语句启用了Qt的数据库驱动功能,支持SQLite、MySQL等数据库。

2. SQLite数据库特性

SQLite无需独立服务器进程,数据以单个文件形式存储(扩展名通常为.db),支持事务、零配置,适合嵌入式和小型应用。其轻量级特性使其成为Qt开发中的首选数据库之一。

三、数据库连接与操作流程

1. 创建并连接数据库
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");  // 指定驱动类型
db.setDatabaseName("mydatabase.db");                     // 设置数据库文件路径
if (!db.open()) {qDebug() << "连接失败:" << db.lastError().text();return;
}
  • 关键点:
    • 使用QSQLITE驱动标识符。
    • setDatabaseName()可指定绝对路径或内存数据库(如:memory:)。
    • 若文件不存在,SQLite会自动创建新数据库。
2. 执行SQL语句

通过QSqlQuery类执行SQL命令:

QSqlQuery query;
// 创建表
query.exec("CREATE TABLE IF NOT EXISTS users (""id INTEGER PRIMARY KEY AUTOINCREMENT, ""name TEXT NOT NULL, age INT)");// 插入数据(预编译防SQL注入)
query.prepare("INSERT INTO users (name, age) VALUES (:name, :age)");
query.bindValue(":name", "Alice");
query.bindValue(":age", 30);
if (!query.exec()) {qDebug() << "插入失败:" << query.lastError().text();
}
  • 方法对比:
    • 直接执行exec(“SQL语句”)适合简单操作。
    • prepare() + bindValue()更安全,支持参数绑定,防止SQL注入。
3. 查询与遍历数据
query.exec("SELECT * FROM users");
while (query.next()) {int id = query.value("id").toInt();QString name = query.value(1).toString();  // 通过字段名或索引获取int age = query.value(2).toInt();qDebug() << id << name << age;
}
  • 注意:
    • query.value()返回QVariant类型,需转换为具体数据类型。
    • 使用query.record()可获取字段元数据(如字段名、类型)。

四、进阶操作与最佳实践

1. 事务处理

确保数据一致性:

db.transaction();  // 开启事务
// 执行多条SQL操作
if (所有操作成功) {db.commit();    // 提交事务
} else {db.rollback();  // 回滚事务
}

事务适用于批量插入、更新等场景,避免部分操作失败导致数据不一致。

2. 错误处理

每次操作后检查错误:

if (!query.exec()) {qDebug() << "错误信息:" << query.lastError().text();qDebug() << "执行的SQL:" << query.lastQuery();
}

通过lastError()获取详细错误描述,便于调试。

3. 使用模型/视图架构

Qt提供QSqlTableModel和QSqlQueryModel,实现数据库与UI组件的绑定:

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

通过模型类可自动同步数据到表格视图,简化开发。

五、完整代码示例(学生人员管理)

1.mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QWidget>
#include <QVBoxLayout>
#include <QPushButton>
#include <QTableView>
#include <QLineEdit>
#include <QComboBox>
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
#include <QSqlTableModel>
#include <QMessageBox>class DatabaseManager {
public:static DatabaseManager* getInstance() {if (!instance) {instance = new DatabaseManager();}return instance;}QSqlDatabase getDatabase() const {return db;}private:DatabaseManager() {db = QSqlDatabase::addDatabase("QSQLITE");db.setDatabaseName("students.db");if (!db.open()) {QMessageBox::critical(nullptr, "Cannot open database","Unable to establish a database connection.\n""This example needs SQLite support. Please read ""the Qt SQL driver documentation for information how ""to build it.\n\n""Click Cancel to exit.", QMessageBox::Cancel);} else {createTable();}}~DatabaseManager() {db.close();}void createTable() {QSqlQuery query;query.exec("CREATE TABLE IF NOT EXISTS students (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER, gender TEXT)");}static DatabaseManager* instance;QSqlDatabase db;
};class MainWindow : public QWidget{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();
private:void setHeadersForQueryModel(QSqlQueryModel *queryModel);QSqlTableModel *m_model;QSqlQueryModel *m_queryModel;QTableView *m_tableView;QLineEdit *m_nameEdit;QLineEdit *m_ageEdit;QComboBox *m_genderCombo;
};#endif // MAINWINDOW_H
2.mainwindow.cpp

#include "mainwindow.h"DatabaseManager* DatabaseManager::instance = nullptr;
MainWindow::MainWindow(QWidget *parent): QWidget(parent),m_model(new QSqlTableModel(this))
{QVBoxLayout *layout = new QVBoxLayout(this);m_tableView = new QTableView(this);layout->addWidget(m_tableView);QPushButton *insertButton = new QPushButton("新增", this);QPushButton *deleteButton = new QPushButton("删除", this);QPushButton *updateButton = new QPushButton("修改", this);QPushButton *queryButton = new QPushButton("查询", this);QHBoxLayout *buttonLayout = new QHBoxLayout();buttonLayout->addWidget(insertButton);buttonLayout->addWidget(deleteButton);buttonLayout->addWidget(updateButton);buttonLayout->addWidget(queryButton);layout->addLayout(buttonLayout);m_nameEdit = new QLineEdit(this);m_ageEdit = new QLineEdit(this);m_genderCombo = new QComboBox(this);m_genderCombo->addItem("男");m_genderCombo->addItem("女");QHBoxLayout *inputLayout = new QHBoxLayout();inputLayout->addWidget(m_nameEdit);inputLayout->addWidget(m_ageEdit);inputLayout->addWidget(m_genderCombo);layout->addLayout(inputLayout);connect(insertButton, &QPushButton::clicked, [this]() {QString name = m_nameEdit->text();int age = m_ageEdit->text().toInt();QString gender = m_genderCombo->currentText();QSqlQuery query;query.prepare("INSERT INTO students (name, age, gender) VALUES (:name, :age, :gender)");query.bindValue(":name", name);query.bindValue(":age", age);query.bindValue(":gender", gender);if (!query.exec()) {QMessageBox::warning(this, "Error", "Failed to insert record.");} else {m_model->select();}});connect(deleteButton, &QPushButton::clicked, [this]() {QModelIndex index = m_tableView->currentIndex();if (index.isValid()) {m_model->removeRow(index.row());m_model->submitAll();}});connect(updateButton, &QPushButton::clicked, [this]() {QModelIndex index = m_tableView->currentIndex();if (index.isValid()) {QString name = m_nameEdit->text();int age = m_ageEdit->text().toInt();QString gender = m_genderCombo->currentText();m_model->setData(m_model->index(index.row(), 1), name);m_model->setData(m_model->index(index.row(), 2), age);m_model->setData(m_model->index(index.row(), 3), gender);m_model->submitAll();}});connect(queryButton, &QPushButton::clicked, [this]() {QString name = m_nameEdit->text();if (!name.isEmpty()) {m_queryModel->setQuery(QString("SELECT * FROM students WHERE name='%1'").arg(name));setHeadersForQueryModel(m_queryModel);m_tableView->setModel(m_queryModel);} else {m_model->select();m_tableView->setModel(m_model);}});// Set headers for the table modelm_model->setHeaderData(0, Qt::Horizontal, QObject::tr("ID"));m_model->setHeaderData(1, Qt::Horizontal, QObject::tr("姓名"));m_model->setHeaderData(2, Qt::Horizontal, QObject::tr("年龄"));m_model->setHeaderData(3, Qt::Horizontal, QObject::tr("性别"));m_queryModel = new QSqlQueryModel(this);m_model->setTable("students");m_model->select();m_tableView->setModel(m_model);}MainWindow::~MainWindow()
{delete m_model;delete m_queryModel;delete m_tableView;delete m_nameEdit;delete m_ageEdit;delete m_genderCombo;
}void MainWindow::setHeadersForQueryModel(QSqlQueryModel *queryModel)
{queryModel->setHeaderData(0, Qt::Horizontal, QObject::tr("ID"));queryModel->setHeaderData(1, Qt::Horizontal, QObject::tr("姓名"));queryModel->setHeaderData(2, Qt::Horizontal, QObject::tr("年龄"));queryModel->setHeaderData(3, Qt::Horizontal, QObject::tr("性别"));
}
3.main.cpp
#include "mainwindow.h"
#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);DatabaseManager::getInstance()->getDatabase();MainWindow w;w.show();return a.exec();
}

六、常见问题与优化建议

1. 连接管理:
  • 使用QSqlDatabase::contains()检查连接是否已存在,避免重复创建。
  • 多线程环境下需为每个线程创建独立连接。
2. 性能优化:
  • 批量操作时启用事务,减少磁盘I/O次数。
  • 使用索引加速查询,避免全表扫描。
    更多Qt开发实战持续更新中。

相关文章:

  • 《Effective Python》第2章 字符串和切片操作——Python 字符串格式化的现代选择f-strings
  • 使用Thrust库实现异步操作与回调函数
  • 一篇解决Redis:持久化机制
  • 从入门到精通:阿里云/腾讯云服务器深度优化实践
  • UUG杭州站 | 团结引擎1.5.0 OpenHarmony新Feature介绍
  • Web安全核心内容与常见漏洞总结
  • SQLServer如何为数据库创建只读账号,并测试是否只读成功。直接代入替换就行,全流程,新手替换复制即可。
  • (1-4)Java Object类、Final、注解、设计模式、抽象类、接口、内部类
  • WebGL图形编程实战【7】:变换流水线 × 坐标系与矩阵精讲
  • 深度解析 JWT:从原理到实战的全场景解决方案(附永久 Token 设计与集成系统实践)
  • 用模型预测控制算法实现对电机位置控制仿真
  • Linux服务器硬盘挂载小记录
  • 商城小程序源码介绍
  • 使用ECS搭建云上博客wordpress(ALMP)
  • 汇川Easy系列PLC数据值改变功能块(随动增益改变判断)
  • 2025 AI如何重构网络安全产品
  • IP SSL怎么签发使用
  • 初识C++:类和对象(上)
  • 【SpringBoot实战指南】集成Easy ES
  • 蚓链数字化营销系统深度解析,以“三位一体“模式驱动企业数字化营销转型
  • 透视社会组织创新实践中的花开岭现象:与乡村发展的融合共进
  • 习近平复信中国丹麦商会负责人
  • 王征、解宁元、牛恺任西安市副市长
  • 4台肺癌手术,2名“90后”患者,这届年轻人的肺怎么了?
  • “典孝急乐批麻蚌赢”:互联网“八字真言”与当代赛博赢学
  • 《蛮好的人生》:为啥人人都爱这个不完美的“大女主”