【Qt之QSqlTableModel】介绍及使用

【Qt之QSqlTableModel】介绍及使用

描述

QSqlTableModel类为单个数据库表提供可编辑的数据模型。

QSqlTableModel是一个高级接口,用于从单个表中读写数据库记录。

它建立在较低级别的QSqlQuery之上,可用于向QTableView等视图类提供数据。

例如:

cpp 复制代码
   QSqlTableModel *model = new QSqlTableModel(parentObject, database);
   // 设置表
   model->setTable("employee");
   // 设置编辑策略
   model->setEditStrategy(QSqlTableModel::OnManualSubmit);
   // 更新
   model->select();
   // 设置表头
   model->setHeaderData(0, Qt::Horizontal, tr("Name"));
   model->setHeaderData(1, Qt::Horizontal, tr("Salary"));
   
   QTableView *view = new QTableView;
   view->setModel(model);
   view->hideColumn(0); // don't show the name
   view->show();

以上代码:

  • 设置SQL表的名称和编辑策略
  • 然后设置视图头中显示的标签
  • 编辑策略指示用户在视图中所做的更改何时实际应用于数据库,取值为OnFieldChange、OnRowChange、OnManualSubmit。

QSqlTableModel也可以用编程方式访问数据库,而不需要绑定到视图:

cpp 复制代码
   QSqlTableModel model;
   model.setTable("employee");
   model.select();
   int salary = model.record(4).value("salary").toInt();

以上代码:

  • 代码片段从employee查询SELECT *的结果集中的记录4中提取工资字段
  • 可以使用setFilter()设置过滤器,或者使用setSort()修改排序顺序
  • 最后,必须调用select()来用数据填充模型。

表模型示例说明了如何使用QSqlTableModel作为QTableView的数据源。

QSqlTableModel不直接支持外键。

如果要解析外键,请使用QSqlRelationalTableModelQSqlRelationalDelegate

常用方法

  1. 枚举:QSqlTableModel::EditStrategy
    此枚举类型描述在编辑数据库中的值时选择的策略。
常量 描述 解释
QSqlTableModel::OnFieldChange 0 All changes to the model will be applied immediately to the database. 对模型的所有更改将立即应用于数据库。
QSqlTableModel::OnRowChange 1 Changes to a row will be applied when the user selects a different row. 当用户选择另一行时,将应用对一行的更改。
QSqlTableModel::OnManualSubmit 2 All changes will be cached in the model until either submitAll() or revertAll() is called. 在调用submitAll()或revertAll()之前,所有更改都将缓存在模型中。

注意:为了防止只将部分初始化的行插入数据库,OnFieldChange的行为将像OnRowChange一样用于新插入的行。

因此,一般设置为手动刷新:

cpp 复制代码
   pTableModel->setEditStrategy(QSqlTableModel::OnManualSubmit);
  1. QSqlDatabase database() const

    获取模型连接的数据库对象。

  2. EditStrategy editStrategy() const

    返回当前的编辑策略。

  3. int fieldIndex(const QString &fieldName) const

    返回字段的索引,返回-1表示此模型内没有该字段。

cpp 复制代码
    qDebug().noquote() << "当前字段索引 :" << pTableModel->fieldIndex("name");
  1. QString filter() const

    获取当前设置的过滤。

  2. bool insertRecord(int row, const QSqlRecord &record)

    在位置行插入记录。如果row为负数,则将该记录追加到末尾。内部调用insertRows()setRecord()

    如果记录可以插入,则返回true,否则返回false

    更改立即提交OnFieldChangeOnRowChange。失败不会在模型中留下新行。

cpp 复制代码
    QSqlRecord record = pTableModel->record();
    qDebug().noquote() << "获取字段 :" << record.fieldName(0) << record.fieldName(1) << record.fieldName(2) << record.fieldName(3);
    record.setValue("field0", "666");
    record.setValue("field1", "666");
    record.setValue("field2", 666);
    record.setValue("field3", "666");
    
    // 插入记录
     // -1 表示在表的末尾插入新记录
    qDebug().noquote() << "插入 :" << pTableModel->insertRecord(pTableModel->rowCount(), record);
  1. bool isDirty(const QModelIndex &index) const

    如果索引index处的值是被改的,则返回true,否则返回false。脏值是在模型中被修改但尚未写入数据库的值。

    如果index无效或指向不存在的行,则返回false。

    此函数还有重载:bool isDirty() const

    意思就是:

    这是一个重载函数。

    如果模型包含未提交给数据库的修改值,则返回true,否则返回false。

  2. QSqlIndex primaryKey() const

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

  3. QSqlRecord record(int row) const

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

    如果row是有效行的索引,则将使用该行的值填充记录。

    如果模型没有初始化,将返回一个空记录。

    此函数还有重载:QSqlRecord record() const

    意思就是:

    这是一个重载函数。

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

  4. void revertRow(int row)

    恢复指定行的所有改变。

  5. void setFilter(const QString &filter)

    将当前过滤器设置为filter

    过滤器是一个不带关键字WHERESQL WHERE子句(例如,name='Josephine')。

    如果已经用数据库中的数据填充了模型,则模型将使用新的过滤器重新选择它。否则,过滤器将在下次调用select()时应用。

cpp 复制代码
    QSqlTableModel* pTableModel = new QSqlTableModel(ui->tableView, db);
    pTableModel->setEditStrategy(QSqlTableModel::OnManualSubmit);
    pTableModel->setTable("\"tableTest\"");
    // 未选择
    pTableModel->setFilter("name = '666'");
    // 执行setFilter操作
    pTableModel->select();
    if (pTableModel->lastError().isValid()) {
        qDebug() << "Error:" << pTableModel->lastError();
    }
    ui->tableView->setModel(pTableModel);


    // 当前字段索引
    qDebug().noquote() << "当前字段索引 :" << pTableModel->fieldIndex("name");
    // 重新选择
    pTableModel->setFilter("name = '22'"); 
  1. bool setRecord(int row, const QSqlRecord &values)

    将值应用于模型中的行。源字段和目标字段按字段名映射,而不是按记录中的位置映射。

    请注意,将保留值中生成的标志,并确定在将更改提交给数据库时是否使用相应的字段。调用者应该记得将数据库提供值的字段(比如自动增加的ID)的生成标志设置为FALSE。

    对于编辑策略OnFieldChangeOnRowChange,只有当其他行没有缓存更改时,一行才可能接收到更改。更改会立即提交。提交的更改在失败时不会恢复。

    如果所有值都可以设置,则返回true;否则返回false

  2. void setSort(int column, Qt::SortOrder order)

    将列的排序顺序设置为order。这不会影响当前数据,要使用新的排序顺序刷新数据,请调用select()。

  3. void setTable(const QString &tableName)

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

    要用表的数据填充模型,请调用select()

    可以使用lastError()检索错误信息。

cpp 复制代码
    pTableModel->setTable("\"tableTest\"");
  1. QString tableName() const
    获取当前选择的表名

槽函数

  1. bool submit()

    QAbstractItemModel::submit()重新实现。

    当用户停止编辑当前行时,项委托调用这个重新实现的槽。

    如果模型的策略设置为OnRowChangeOnFieldChange,则提交当前编辑的行。对OnManualSubmit策略不做任何操作。

    使用submitAll()OnManualSubmit策略提交所有挂起的更改。

    成功时返回true;否则返回false。使用lastError()查询详细的错误信息。

    不会自动重新填充模型。提交的行在成功时从数据库中刷新。

  2. bool submitAll()

    提交所有挂起的更改,并在成功时返回true。错误时返回false,详细的错误信息可以通过lastError()获得。

    OnManualSubmit中,一旦成功,模型将被重新填充。任何呈现它的视图都将失去其选择。

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

  3. void revert()

    QAbstractItemModel::revert()重新实现。

    当用户取消编辑当前行时,项目委托调用这个重新实现的槽。

    如果模型的策略设置为OnRowChangeOnFieldChange,则恢复更改。对OnManualSubmit策略不做任何操作。 使用revertAll()来恢复OnManualSubmit策略的所有挂起的更改,或者使用revertRow()`来恢复特定的行。

  4. void revertAll()

    重置所有缓存操作。

  5. bool select()

    使用通过setTable()设置的表中的数据填充模型,使用指定的筛选和排序条件,如果成功则返回true;否则返回false。

    注意:调用select()将恢复所有未提交的更改并删除所有插入的列。

  6. bool selectRow(int row)

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

    如果成功返回true;否则返回false。

信号

  1. void beforeDelete(int row)
    该信号由deleteRowFromTable()在从当前活动的数据库表中删除行之前发出。
  2. void beforeInsert(QSqlRecord &record)
    该信号由insertRowIntoTable()在将新行插入当前活动的数据库表之前发出。要插入的值存储在记录中,可以在插入之前进行修改。
  3. void beforeUpdate(int row, QSqlRecord &record)
    在使用record中的值更新当前活动数据库表中的行之前,updateRowInTable()会发出这个信号。
    注意,只有标记为生成的值才会被更新。生成标志可以用QSqlRecord::setGenerated()设置,用QSqlRecord::isGenerated()检查。
  4. void primeInsert(int row, QSqlRecord &record)
    当在当前活动的数据库表的给定行中发起插入时,该信号由insertRows()发出。record参数可以写入(因为它是一个引用),例如用默认值填充一些字段,并设置字段的生成标志。在处理此信号时,不要尝试通过setData()或setRecord()等其他方法编辑记录。

示例

在.pro中添加QT += sql

包含头文件

cpp 复制代码
        #include <QDebug>
        #include <QSqlTableModel>
        #include <QSqlDatabase>
        #include <QSqlRecord>
        #include <QSqlError>

初始化

cpp 复制代码
            QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
            db.setDatabaseName("xxx/xxx/xxx.db");
            bool ok = db.open();
        
            QSqlTableModel* pTableModel = new QSqlTableModel(ui->tableView, db);
            pTableModel->setEditStrategy(QSqlTableModel::OnManualSubmit);
            pTableModel->setTable("\"tableTest\"");
            pTableModel->setFilter("name = '666'");
        
            pTableModel->select();
            if (pTableModel->lastError().isValid()) {
                qDebug() << "Error:" << pTableModel->lastError();
            }
            ui->tableView->setModel(pTableModel);
        
        
            // 当前字段索引
            qDebug().noquote() << "当前字段索引 :" << pTableModel->fieldIndex("name");
            pTableModel->setFilter("name = '666'");         

插入

cpp 复制代码
            QSqlTableModel* pTableModel = (QSqlTableModel*)ui->tableView->model();
            // 实现以下代码,插入空行后进行数据插入,会插入失败。
            //pTableModel->insertRow(pTableModel->rowCount());
          
            QSqlRecord record = pTableModel->record();
            qDebug().noquote() << "获取字段 :" << record.fieldName(0) << record.fieldName(1) << record.fieldName(2) << record.fieldName(3);
            record.setValue("field0", "66");
            record.setValue("field1", "66");
            record.setValue("field2", 66);
            record.setValue("field3", "66");
          
            // 插入记录
            qDebug().noquote() << "插入 :" << pTableModel->insertRecord(pTableModel->rowCount(), record); // -1 表示在表的末尾插入新记录
                        

提交

cpp 复制代码
            QSqlTableModel* pTableModel = (QSqlTableModel*)ui->tableView->model();
            pTableModel->submitAll();                   
相关推荐
SPC的存折8 小时前
openEuler 24.03 MariaDB Galera 集群部署指南(cz)
linux·运维·服务器·数据库·mysql
仲芒8 小时前
[24年单独笔记] MySQL 常用的 DML 命令
数据库·笔记·mysql
SPC的存折8 小时前
MySQL 8.0 分库分表
linux·运维·服务器·数据库·mysql
AlanW8 小时前
QT 信号槽内部实现原理深度解析
qt
蓦然乍醒9 小时前
使用 DBeaver 还原 PostgreSQL 备份文件 (.bak) 技术文档
数据库·postgresql
XDHCOM9 小时前
Redis节点故障自动恢复机制详解,如何快速抢救故障节点,确保数据不丢失?
java·数据库·redis
A.A呐9 小时前
【QT第五章】系统相关
开发语言·qt
QCzblack9 小时前
BugKu BUUCTF ——Reverse
java·前端·数据库
cyber_两只龙宝9 小时前
【Oracle】Oracle之DQL中WHERE限制条件查询
linux·运维·数据库·云原生·oracle
luis的妙妙屋9 小时前
主流数据库数据类型对比分析
数据库