当前位置:首页 > 问答 > 正文

Qt里自带的数据库查询和查找表,简单案例分享给你看看

使用SQLite进行最简单的查询(来源:Qt助手示例代码思路简化)

这个案例展示如何连接一个SQLite内存数据库,建一张表,插入点数据,然后查出来。

得在项目文件(.pro)里加上这么一句,告诉编译器要用到SQL模块: QT += sql

然后看代码:

#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QDebug>
void simpleQueryDemo() {
    // 1. 添加一个SQLite数据库连接,数据库放在内存里,叫":memory:",重启程序就没了,适合测试
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName(":memory:");
    // 2. 尝试打开数据库,如果失败就打印错误信息并退出
    if (!db.open()) {
        qDebug() << "打开数据库失败:" << db.lastError().text();
        return;
    }
    // 3. 创建一个QSqlQuery对象,用它来执行SQL命令
    QSqlQuery query;
    // 4. 执行一条SQL语句,创建一张叫`person`的表
    QString createTableSql = "CREATE TABLE person ("
                             "id INTEGER PRIMARY KEY AUTOINCREMENT, "
                             "name VARCHAR(255) NOT NULL, "
                             "age INTEGER)";
    if (!query.exec(createTableSql)) {
        qDebug() << "创建表失败:" << query.lastError().text();
        return;
    }
    // 5. 往表里插两条数据
    QString insertSql = "INSERT INTO person (name, age) VALUES "
                        "('张三', 25), "
                        "('李四', 30)";
    if (!query.exec(insertSql)) {
        qDebug() << "插入数据失败:" << query.lastError().text();
        return;
    }
    // 6. 现在来查询,把刚才插进去的数据找出来
    QString selectSql = "SELECT id, name, age FROM person";
    if (!query.exec(selectSql)) {
        qDebug() << "查询失败:" << query.lastError().text();
        return;
    }
    // 7. 遍历查询结果,query.next()会移动到下一条记录,如果没了就返回false
    qDebug() << "查询结果:";
    while (query.next()) {
        // 通过字段的索引(从0开始)或者字段名来获取值
        int id = query.value(0).toInt();        // id是第一个字段,索引0
        QString name = query.value("name").toString(); // 用字段名"name"来取
        int age = query.value(2).toInt();       // age是第三个字段,索引2
        qDebug() << "ID:" << id << ",姓名:" << name << ",年龄:" << age;
    }
    // 8. 关闭数据库连接(对于内存数据库,程序结束也会自动关闭)
    db.close();
}

运行这个函数,你会在调试输出里看到插进去的张三和李四的信息,这就是一个完整的“连接-建表-插入-查询”流程。

Qt里自带的数据库查询和查找表,简单案例分享给你看看

使用预编译查询防止SQL注入(来源:Qt官方文档关于QSqlQuery::prepare()的强调)

直接拼接SQL字符串很危险,比如用户输入个名字叫 ' OR '1'='1,可能就会查出所有数据,所以要用预编译查询。

接上例,我们换种方式插入数据:

Qt里自带的数据库查询和查找表,简单案例分享给你看看

void preparedQueryDemo() {
    // ... 前面连接数据库、创建表的代码和上面一样,这里省略 ...
    QSqlQuery query;
    // 准备SQL语句,用:name和:age这样的占位符代替实际值
    query.prepare("INSERT INTO person (name, age) VALUES (:name, :age)");
    // 绑定值到占位符
    query.bindValue(":name", "王五");
    query.bindValue(":age", 28);
    // 执行插入
    if (!query.exec()) {
        qDebug() << "预编译插入失败:" << query.lastError().text();
    }
    // 也可以批量绑定值,比如用一个字符串列表和年龄列表
    QStringList names = {"赵六", "孙七"};
    QList<int> ages = {22, 35};
    query.prepare("INSERT INTO person (name, age) VALUES (?, ?)"); // 也可以用问号占位
    for (int i = 0; i < names.size(); ++i) {
        // 按位置绑定值,注意索引从0开始
        query.addBindValue(names.at(i));
        query.addBindValue(ages.at(i));
        if (!query.exec()) {
            qDebug() << "批量插入" << names.at(i) << "失败:" << query.lastError().text();
        }
    }
    // 查询验证
    query.exec("SELECT * FROM person");
    while (query.next()) {
        qDebug() << "ID:" << query.value("id").toInt()
                 << ",姓名:" << query.value("name").toString()
                 << ",年龄:" << query.value("age").toInt();
    }
}

这种方式更安全,数据库会先理解SQL指令的结构,再把绑定的值当作纯数据处理,有效防止恶意拼接。

用QSqlTableModel实现一个简单的查找表(来源:Qt的Model/View框架常见用法)

如果觉得写SQL麻烦,Qt提供了一个叫QSqlTableModel的类,它能直接把一张数据库表映射到一个模型上,这个模型可以很方便地用在Qt的视图控件(比如QTableView)上,实现显示、编辑、排序、过滤(查找)等功能。

#include <QApplication>
#include <QTableView>
#include <QSqlTableModel>
#include <QHeaderView>
#include <QVBoxLayout>
#include <QLineEdit>
#include <QWidget>
void tableViewDemo() {
    // ... 假设已经按照案例一的方法,创建了数据库连接,并在person表里有一些数据 ...
    QWidget window;
    QVBoxLayout *layout = new QVBoxLayout(&window);
    // 1. 创建一个QSqlTableModel模型,并设置它要操作的表
    QSqlTableModel *model = new QSqlTableModel(nullptr, db); // db是之前打开的数据库连接
    model->setTable("person");
    // 设置编辑策略,比如允许手动提交修改
    model->setEditStrategy(QSqlTableModel::OnManualSubmit);
    // 从数据库拉取数据到模型
    model->select();
    // 2. 创建一个表格视图,并设置模型
    QTableView *tableView = new QTableView;
    tableView->setModel(model);
    // 可以设置一些视图属性,比如拉伸最后一列填充剩余空间
    tableView->horizontalHeader()->setStretchLastSection(true);
    layout->addWidget(tableView);
    // 3. 添加一个搜索框来实现按姓名查找
    QLineEdit *searchBox = new QLineEdit;
    searchBox->setPlaceholderText("输入姓名进行过滤...");
    layout->addWidget(searchBox);
    // 4. 连接搜索框的文字变化信号到槽函数,实现实时过滤
    QObject::connect(searchBox, &QLineEdit::textChanged, [model](const QString &text) {
        // 设置过滤条件:name字段包含输入的文字(不区分大小写)
        // 语法类似SQL的WHERE子句,但用的是数据库方言,SQLite用LIKE
        model->setFilter(QString("name LIKE '%%1%'").arg(text));
        // 重新执行查询,应用过滤条件
        model->select();
    });
    window.resize(400, 300);
    window.show();
    // 如果是控制台程序,需要启动事件循环,这里假设在GUI应用中调用
    // QApplication::exec();
}

这个例子创建了一个带搜索框的窗口,你在搜索框里打字,下面的表格就会只显示姓名中包含你输入文字的记录,QSqlTableModel背后自动生成了相应的SQL查询(比如SELECT * FROM person WHERE name LIKE '%张%'),你不用自己写这些SQL了,非常方便。

这几个案例从底层SQL执行到高级的模型视图应用,展示了Qt处理数据库的基本路子。