Qt 数据库操作详解:从连接到增删改查

示例代码:

cpp 复制代码
QSqlDatabase db = QSqlDatabase::addDatabase("QSSLITE");
db.setDatabaseName("test.db");
db.open();

Qt 提供了一个强大的 SQL 模块,可以方便地连接和操作多种数据库。本文将介绍 Qt 中数据库操作的基本流程,并以 SQLite 为例演示增删改查(CRUD)操作,同时展示如何结合模型视图快速展示数据。

1. Qt SQL 模块概述

Qt SQL 模块支持多种主流数据库,包括:

  • SQLite(默认支持,无需额外配置)

  • MySQL / MariaDB

  • PostgreSQL

  • Oracle(通过 OCI)

  • ODBC(可用于连接 SQL Server 等)

  • 以及其他通过插件支持的数据库

使用该模块时,需要在项目文件(.pro)中添加:

cpp 复制代码
QT += sql

并在源代码中包含必要的头文件:

cpp 复制代码
#include <QtSql>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QSqlTableModel>
#include <QTableView>

2. 建立数据库连接

数据库连接通过 QSqlDatabase 类管理。以下代码创建一个 SQLite 内存数据库,并打开连接:

cpp 复制代码
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); // 使用 SQLite 驱动
db.setDatabaseName(":memory:"); // 内存数据库,也可以指定文件路径如 "test.db"

if (!db.open()) {
    qDebug() << "数据库打开失败:" << db.lastError().text();
    return;
}
qDebug() << "数据库连接成功!";

对于 MySQL 等数据库,还需要设置用户名、密码、主机名等:

cpp 复制代码
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
db.setHostName("localhost");
db.setDatabaseName("mydb");
db.setUserName("root");
db.setPassword("password");
  • 使用QSqlDatabase::contains()检查连接是否已存在,避免重复创建。

3. 执行 SQL 语句:QSqlQuery

QSqlQuery 用于执行任意 SQL 语句,并处理结果集。下面演示创建表、插入、查询、更新和删除操作。

3.1 创建表

cpp 复制代码
QSqlQuery query;
bool success = query.exec(
    "CREATE TABLE person ("
    "id INTEGER PRIMARY KEY AUTOINCREMENT, "
    "name TEXT NOT NULL, "
    "age INTEGER)"
);

if (!success) {
    qDebug() << "创建表失败:" << query.lastError().text();
} else {
    qDebug() << "创建表成功";
}

3.2 插入数据

插入数据可以使用 exec() 直接执行 SQL,也可以使用预处理语句(prepare + bind)防止 SQL 注入。

cpp 复制代码
// 方式1:直接拼接字符串(不推荐,存在注入风险)
query.exec("INSERT INTO person (name, age) VALUES ('张三', 25)");

// 方式2:预处理语句(推荐)
query.prepare("INSERT INTO person (name, age) VALUES (:name, :age)");
query.bindValue(":name", "李四");
query.bindValue(":age", 30);
if (!query.exec()) {
    qDebug() << "插入失败:" << query.lastError().text();
} else {
    qDebug() << "插入成功";
}

3.3 查询数据

执行 SELECT 语句后,使用 next() 遍历结果集。

cpp 复制代码
query.exec("SELECT id, name, age FROM person");

while (query.next()) {
    int id = query.value(0).toInt();
    QString name = query.value("name").toString(); // 可用列名或索引
    int age = query.value(2).toInt();
    qDebug() << id << name << age;
}

3.4 更新数据

cpp 复制代码
query.prepare("UPDATE person SET age = :age WHERE name = :name");
query.bindValue(":age", 26);
query.bindValue(":name", "张三");
if (!query.exec()) {
    qDebug() << "更新失败:" << query.lastError().text();
}

3.5 删除数据

cpp 复制代码
query.prepare("DELETE FROM person WHERE name = :name");
query.bindValue(":name", "李四");
if (!query.exec()) {
    qDebug() << "删除失败:" << query.lastError().text();
}

4. 使用模型视图简化开发

对于需要展示或编辑数据的场景,可以使用 QSqlTableModel 结合 QTableView,几行代码即可实现数据表格的显示和编辑。

cpp 复制代码
// 创建模型并绑定到数据库表
QSqlTableModel *model = new QSqlTableModel;
model->setTable("person");
model->setEditStrategy(QSqlTableModel::OnManualSubmit); // 手动提交修改
model->select(); // 加载数据

// 设置表头
model->setHeaderData(0, Qt::Horizontal, "ID");
model->setHeaderData(1, Qt::Horizontal, "姓名");
model->setHeaderData(2, Qt::Horizontal, "年龄");

// 创建视图
QTableView *view = new QTableView;
view->setModel(model);
view->resizeColumnsToContents();
view->show();

通过模型视图,用户可以直接在表格中修改数据,然后调用 model->submitAll() 提交修改,或 model->revertAll() 撤销。


5. 事务处理

对于需要保证原子性的操作,可以使用事务:

cpp 复制代码
if (db.transaction()) {
    QSqlQuery query;
    if (query.exec("INSERT ...") && query.exec("UPDATE ...")) {
        db.commit();
        qDebug() << "事务提交成功";
    } else {
        db.rollback();
        qDebug() << "事务回滚:" << query.lastError().text();
    }
} else {
    qDebug() << "启动事务失败";
}

6. 完整示例代码

以下是一个完整的控制台程序,演示了 SQLite 内存数据库的增删改查操作:

cpp 复制代码
#include <QCoreApplication>
#include <QtSql>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 1. 连接数据库
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName(":memory:");
    if (!db.open()) {
        qDebug() << "数据库打开失败:" << db.lastError().text();
        return -1;
    }

    // 2. 创建表
    QSqlQuery query;
    if (!query.exec("CREATE TABLE person (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER)")) {
        qDebug() << "建表失败:" << query.lastError().text();
        return -1;
    }

    // 3. 插入数据
    query.prepare("INSERT INTO person (name, age) VALUES (?, ?)");
    query.addBindValue("张三");
    query.addBindValue(25);
    if (!query.exec()) qDebug() << "插入失败:" << query.lastError().text();

    query.bindValue(0, "李四");
    query.bindValue(1, 30);
    if (!query.exec()) qDebug() << "插入失败:" << query.lastError().text();

    // 4. 查询数据
    qDebug() << "查询所有记录:";
    query.exec("SELECT * FROM person");
    while (query.next()) {
        qDebug() << query.value(0).toInt() << query.value(1).toString() << query.value(2).toInt();
    }

    // 5. 更新数据
    query.prepare("UPDATE person SET age = :age WHERE name = :name");
    query.bindValue(":age", 26);
    query.bindValue(":name", "张三");
    if (!query.exec()) qDebug() << "更新失败:" << query.lastError().text();

    // 6. 删除数据
    query.prepare("DELETE FROM person WHERE name = :name");
    query.bindValue(":name", "李四");
    if (!query.exec()) qDebug() << "删除失败:" << query.lastError().text();

    // 7. 再次查询验证
    qDebug() << "操作后剩余记录:";
    query.exec("SELECT * FROM person");
    while (query.next()) {
        qDebug() << query.value(0).toInt() << query.value(1).toString() << query.value(2).toInt();
    }

    db.close();
    return 0;
}

7. 常见问题与注意事项

  • 驱动加载:部分数据库(如 MySQL)需要编译相应的驱动插件,确保 Qt 安装时包含该驱动。

  • 错误处理 :每次执行 SQL 后都应检查 lastError(),尤其在生产代码中。

  • 线程安全QSqlDatabase 实例不可跨线程使用,每个线程需建立自己的连接。

  • 模型视图QSqlTableModel 默认使用 OnManualSubmit 策略,如需自动提交可改为 OnRowChangeOnFieldChange

  • 性能 :批量操作时使用 QSqlQuery::prepare()addBindValue() 可以有效提升性能并避免 SQL 注入。


8. 总结

Qt SQL 模块提供了一套完整的数据库操作接口,从底层 QSqlQuery 到高层模型视图,开发者可以根据需求灵活选择。对于小型应用,SQLite 搭配 QSqlTableModel 可以快速实现数据管理功能;对于大型项目,Qt 也能无缝对接 MySQL、PostgreSQL 等企业级数据库。掌握这些基础操作,即可在 Qt 项目中游刃有余地处理数据持久化问题。

相关推荐
天天学IT5 小时前
第三章 Qt 编译及安装
开发语言·qt·qt教程·qt6教程
weixin_464307635 小时前
QT插件系统
qt
Summer_Uncle6 小时前
【QT学习】Qt界面布局的生命周期和加载时机
c++·qt
weixin_4643076310 小时前
QT宏、属性系统
开发语言·qt
qq_2837200510 小时前
VSCode 编译 Qt 5.12 QML 完整教程(Windows + MinGW)
windows·vscode·qt
肖恭伟11 小时前
Curso调试Qt:GDB + Qt 官方 qt5printers.py + .gdbinit
开发语言·qt
天天学IT11 小时前
第二章 Qt 模块
开发语言·qt·qt教程·qt6教程
仲舟11 小时前
【Qt游戏】骰子街Machi_Koro_AI
c++·人工智能·qt·游戏
火山上的企鹅12 小时前
QGC二次开发本地媒体浏览实战(二)FFmpeg最小系统实战
qt·ffmpeg·媒体·qgc