Qt SQL:QSqlQueryModel、QSqlTableModel

本文详细介绍了Qt框架中的QSqlQueryModel和QSqlTableModel,它们是用于数据库操作的模型类。QSqlQueryModel主要用于执行SQL查询并展示结果,而QSqlTableModel则提供了对单个数据库表的读写支持。文章通过实例展示了如何创建、设置查询、插入和编辑数据,以及如何处理错误。此外,还提到了这两个模型的成员函数,包括数据访问、修改、排序和过滤等功能。
摘要由CSDN通过智能技术生成

QSqlQueryModel

一、描述

QSqlQueryModel 类继承自 QAbstractTableModel,为 SQL 结果集提供只读数据模型,是用于执行 SQL 语句和遍历结果集的高级接口。它建立在较低级别的 QSqlQuery 之上,可用于为 QTableView 等视图类提供数据。


static bool createConnection()
{
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName(":memory:");
    if (!db.open())
    {
        return false;
    }

    QSqlQuery query;
    query.exec("create table person (id int primary key, "
                                    "姓名 varchar(20), "
                                    "职业 varchar(20))");
    query.exec("insert into person values(101, '张三', '电工')");
    query.exec("insert into person values(102, '李四', '学生')");
    query.exec("insert into person values(103, '王五', '程序员')");
    query.exec("insert into person values(104, '赵六', '外卖员')");

    return true;
}

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    if (!createConnection())
        return EXIT_FAILURE;

    QSqlQueryModel model;
    model.setQuery("SELECT 姓名, 职业 FROM person");
    model.setHeaderData(0, Qt::Horizontal, QObject::tr("姓名_"));
    model.setHeaderData(1, Qt::Horizontal, QObject::tr("职业_"));
    QTableView view;
    view.setModel(&model);
    view.show();

    return app.exec();
}

QSqlQueryModel 也可用于以编程方式访问数据库,而无需将其绑定到视图:

    qDebug()<<model.record(1).value("职业").toString();//"学生"

这等同于:

    model.data(model.index(1, 1)).toString();

该模型默认为只读。要使其可读写,必须对其进行子类化并重新实现 setData() 和 flags()。另一种选择是使用 QSqlTableModel,它提供了基于单个数据库表的读写模型。

二、成员函数

1、bool canFetchMore(const QModelIndex &parent = QModelIndex())

是否可以从数据库中读取更多行。parent 应该始终是无效的 QModelIndex。

2、void clear()

清除模型并释放所有获取的资源。

3、QVariant data(const QModelIndex &item, int role = Qt::DisplayRole)

返回指定项和角色的值。

4、void fetchMore(const QModelIndex &parent = QModelIndex())

从数据库中获取更多行。parent 应该始终是无效的 QModelIndex。

要获取整个结果集,可以使用:

while (myModel->canFetchMore())
    myModel->fetchMore();

5、QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole)

返回具有指定方向的标题部分中角色 role 的标题数据。

6、QModelIndex indexInQuery(const QModelIndex &item)

返回模型中给定项目的数据库结果集中值的索引。

如果没有插入、删除或移动任何列或行,则返回值与 item 相同。

7、bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex())

将 count 列插入模型的第 column 列处 。parent 参数必须始终是无效的 QModelIndex。

默认情况下,插入的列是空的。要用数据填充它们,需要重新实现 data() 处理。

static bool createConnection()
{
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName(":memory:");
    if (!db.open())
    {
        return false;
    }

    QSqlQuery query;
    query.exec("create table person (id int primary key, "
                                    "姓名 varchar(20), "
                                    "职业 varchar(20))");
    query.exec("insert into person values(101, '张三', '电工')");
    query.exec("insert into person values(102, '李四', '学生')");
    query.exec("insert into person values(103, '王五', '程序员')");
    query.exec("insert into person values(104, '赵六', '外卖员')");

    return true;
}

class cumstomModel : public QSqlQueryModel
{
public:
    cumstomModel(QObject *parent = nullptr)
        :QSqlQueryModel(parent)
    {
    }

    QVariant data(const QModelIndex &item, int role) const override
    {
        if (item.column() > 1 && role == Qt::DisplayRole)
        {
            return QString("插入的数据");
        }
        return QSqlQueryModel::data(item, role);
    }
};

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    if (!createConnection())
        return EXIT_FAILURE;

    cumstomModel model;
    model.setQuery("SELECT 姓名, 职业 FROM person");
    model.setHeaderData(0, Qt::Horizontal, QObject::tr("姓名_"));
    model.setHeaderData(1, Qt::Horizontal, QObject::tr("职业_"));

    QWidget w;
    QVBoxLayout vb(&w);

    QTableView view;
    view.setModel(&model);
    vb.addWidget(&view);
    QPushButton btn("添加");
    QObject::connect(&btn,&QPushButton::clicked,[&]
    {
        model.insertColumns(2,1);
    });
    QHBoxLayout hb;
    hb.addStretch();
    hb.addWidget(&btn);
    vb.addLayout(&hb);
    w.show();

    return app.exec();
}

8、QSqlError lastError()

返回有关数据库上发生的最后一个错误的信息。

9、QSqlQuery query()

返回与此模型关联的 QSqlQuery。

10、void queryChange()

每当查询更改时,都会调用此虚函数。

11、QSqlRecord record(int row)

返回包含有关当前查询的字段信息的记录。如果 row 是有效行的索引,则将使用该行中的值填充记录。

      QSqlRecord record()

返回一个空记录,其中包含有关当前查询的字段的信息。

12、bool removeColumns(int column, int count, const QModelIndex &parent = QModelIndex())

从位置 column 开始从模型中删除 count 列。parent 参数必须始终是无效的 QModelIndex。

删除列可以有效地隐藏它们。它不会影响底层的 QSqlQuery

返回是否删除成功。

13、QHash<int, QByteArray> roleNames()

返回模型的角色名称。

Qt 只为 QSqlQueryModel 定义了一个角色:

14、int rowCount(const QModelIndex &parent = QModelIndex())

如果数据库支持返回查询的大小,则返回当前查询的行数。否则返回当前缓存的行数。

parent 应该始终是无效的 QModelIndex。

15、bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole)

将角色 role 的水平标题设置为 value。orientation 必须是 Qt::Horizo​​ntal

此函数不能用于修改数据库中的值,因为模型是只读的。

16、void setLastError(const QSqlError &error)

用于派生类设置数据库上发生的最后一个错误的值。

17、void setQuery(QSqlQuery && query)

重置模型并设置数据提供者。query 必须是活动的,并且不能是 isForwardOnly()。

      void setQuery(const QString &query, const QSqlDatabase &db = QSqlDatabase())

对数据库连接 db 执行查询查询。如果未指定数据库(或无效数据库),则使用默认连接。

QSqlQueryModel model;
model.setQuery("select * from MyTable");
if (model.lastError().isValid())
    qDebug() << model.lastError();

QSqlTableModel

一、描述

QSqlTableModel 类为单个数据库表提供可编辑的数据模型,继承自 QSqlQueryModel,它是用于从单个表中读取和写入数据库记录的高级接口。它建立在较低级别的 QSqlQuery 之上,可用于为 QTableView 等视图类提供数据。

#include <QApplication>
#include <QSqlTableModel>
#include <QTableView>
#include <QSqlQuery>
#include <QHeaderView>
#include <stdlib.h>

static bool createConnection()
{
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName(":memory:");
    if (!db.open())
    {
        return false;
    }

    QSqlQuery query;
    query.exec("create table person (id int primary key, "
                                    "姓名 varchar(20), "
                                    "职业 varchar(20))");
    query.exec("insert into person values(101, '张三', '电工')");
    query.exec("insert into person values(102, '李四', '学生')");
    query.exec("insert into person values(103, '王五', '程序员')");
    query.exec("insert into person values(104, '赵六', '外卖员')");

    return true;
}

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    if (!createConnection())
        return EXIT_FAILURE;

    QSqlTableModel model;
    model.setTable("person");
    model.setEditStrategy(QSqlTableModel::OnManualSubmit);
    model.select();

    model.setHeaderData(0, Qt::Horizontal, QObject::tr("编号"));
    model.setHeaderData(1, Qt::Horizontal, QObject::tr("人员姓名"));
    model.setHeaderData(2, Qt::Horizontal, QObject::tr("职业信息"));

    QTableView view;
    view.horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    view.setModel(&model);
    view.show();

    return app.exec();
}

QSqlTableModel 也可用于以编程方式访问数据库,而无需将其绑定到视图:

    qDebug()<<model.record(1).value("职业").toString();//"学生"

上面的代码片段从查询 SELECT * from person 的结果集中的记录 1 中提取“职业”字段。

可以使用 setFilter() 设置过滤器,或使用 setSort() 修改排序顺序。最后必须调用 select() 以使用数据填充模型。

QSqlTableModel 不直接支持外键。如果要解析外键,应使用 QSqlRelationalTableModel QSqlRelationalDelegate

二、类型成员

1、enum QSqlTableModel::EditStrategy:此枚举描述了在编辑数据库中的值时选择的策略。

  • OnFieldChange:对模型的所有更改将立即应用于数据库。
  • OnRowChange:当用户选择不同的行时,将应用对行的更改。
  • OnManualSubmit:在调用 submitAll() 或 revertAll() 之前,所有更改都将缓存在模型中。

三、成员函数

1、【信号】void beforeDelete(int row)

此信号由 deleteRowFromTable() 在从当前活动的数据库表中删除行之前发出。

2、【信号】void beforeInsert(QSqlRecord &record)

在将新行插入当前活动的数据库表之前,insertRowIntoTable() 会发出此信号。即将插入的值存储在 record 中,可以在插入之前进行修改。

3、【信号】void beforeUpdate(int row, QSqlRecord &record)

此信号由 updateRowInTable() 在当前活动数据库表中使用记录中的值更新行之前发出。

只有标记为已生成的值才会被更新。生成的标志可以用 QSqlRecord::setGenerated() 设置并用 QSqlRecord::isGenerated() 检查。

4、【信号】void primeInsert(int row, QSqlRecord &record)

当在当前活动数据库表的给定行中启动插入时,insertRows() 发出此信号。

处理此信号时,请勿尝试通过其他方式(例如 setData() 或 setRecord())编辑记录。

5、void revert()

当用户取消编辑当前行时,项目委托将调用此函数。

如果模型的策略设置为 OnRowChange OnFieldChange,则还原更改。

6、void revertAll()

还原所有还未应用的更改。

7、bool select()

使用指定的过滤器和排序条件,使用通过 setTable() 设置的表中的数据填充模型。

调用 select() 将还原所有未提交的更改并删除所有插入的列。

8、bool selectRow(int row)

使用与主键值匹配数据库表行中的值刷新模型中的行。如果没有主键,所有列值都必须匹配。如果没有找到匹配的行,模型将显示一个空行。

9、bool submit()

当用户停止编辑当前行时,项目委托会调用函数。

如果模型的策略设置为 OnRowChange OnFieldChange,则提交当前编辑的行。

10、bool submitAll()

提交所有更改。

OnManualSubmit 模式下,当 submitAll() 失败时,已经提交的更改不会从缓存中清除。这允许在不丢失数据的情况下回滚和重新提交事务。

11、QSqlDatabase database()

返回模型的数据库连接。

12、bool deleteRowFromTable(int row)

从当前活动的数据库表中删除给定的行。返回该行是否被删除

这是一种直接对数据库进行操作的低级方法,不建议使用。建议使用 removeRow() 或 removeRows() 删除值。模型将根据其编辑策略决定何时修改数据库。

13、int fieldIndex(const QString &fieldName)

返回字段 fieldName 的索引,如果模型中不存在对应的字段,则返回 -1。

14、bool insertRecord(int row, const QSqlRecord &record)

插入记录。如果 row 为负数,则记录将附加到末尾。返回是否插入成功。

15、bool insertRowIntoTable(const QSqlRecord &values)

将记录插入到当前活动的数据库表中。返回是否插入成功

这是一种直接对数据库进行操作的低级方法,不建议使用。建议使用 insertRow() 和 setData() 插入值。模型将根据其编辑策略决定何时修改数据库。

16、bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex())

在位置 row 插入 count 个空行。parent 必须是无效的,因为当前模型不支持父子关系。

对于编辑策略 OnFieldChange OnRowChange,一次只能插入一行。

将为每个新行发出 primeInsert() 信号。如果要使用默认值初始化新行,可连接到此信号。

无论编辑策略如何,都不提交行。

如果参数超出范围或无法插入行,则返回 false。

17、bool isDirty(const QModelIndex &index)

如果索引 index 处的值是否脏值。脏值是在模型中修改但尚未写入数据库的值。

       bool isDirty()

模型是否包含尚未提交到数据库的修改值。

18、QSqlIndex primaryKey()

返回当前表的主键,如果表没有设置或没有主键,则返回一个空的 QSqlIndex。

19、QSqlRecord record()

 返回一个记录,只有字段名称。此函数可用于检索记录的字段名称。

       QSqlRecord record(int row)

返回模型中第 row 行的记录。

20、bool removeColumns(int column, int count, const QModelIndex &parent = QModelIndex())

从父模型中删除 count 列,从索引 column 开始。

21、bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex())

从 row 开始删除计数行。由于此模型不支持分层结构,因此 parent 必须是无效的模型索引。

在从数据库中删除一行之前,会发出 beforeDelete() 信号。

如果可以删除所有行,则返回 true。可以使用 lastError() 检索详细的数据库错误信息。

22、void revertRow(int row)

还原指定行的所有更改。

23、bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole)

将角色 role 的项目 index 的数据设置为 value。

如果角色不是 Qt::EditRole,则返回 false。要为 Qt::EditRole 以外的角色设置数据,请使用自定义代理模型或子类 QSqlTableModel。

24、void setFilter(const QString &filter)

设置过滤器。过滤器是一个没有关键字 WHERE 的 SQL WHERE 子句(例如,name='Josephine')。

25、void setPrimaryKey(const QSqlIndex &key)

设置主键。通常,每当调用 setTable() 时,都会自动设置主索引。

26、bool setRecord(int row, const QSqlRecord &values)

将 values 应用于模型中的行 row 。

必须对 values 中的所有值设置 setGenerated(false) 将标志设置为 false(默认 QSqlRecord 中的所有字段为 true),才能将更改保存回数据库。

27、void setSort(int column, Qt::SortOrder order)

设置要排序的列的排序顺序。

这不会影响当前数据,要使用新的排序顺序刷新数据,需要调用 select()。

enum Qt::SortOrder:此枚举描述了小部件中的项目是如何排序的。

  • Qt::AscendingOrder:升序排序。
  • Qt::DescendingOrder:降序排序。

28、void setTable(const QString &tableName)

设置模型操作的数据库表。不会从表中选择数据,但获取其字段信息。

29、void sort(int column, Qt::SortOrder order)

对数据进行排序。

30、bool updateRowInTable(int row, const QSqlRecord &values)

使用指定值更新当前活动数据库表中的给定行。

这是一种直接对数据库进行操作的低级方法,不建议使用用。建议使用 setData() 更新值。模型将根据其编辑策略决定何时修改数据库。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值