00. 目录


文章目录


00. 目录01. 概述02. 开发环境03. QSqlQueryModel类04. QSqlTableModel类05. QSqlRelationalTableModel类06. QSqlRelationalDelegate类07. 附录


01. 概述

用户接口层主要包括Qt SQL模块中的QSqlQueryModel、QSqlTableModel、QSqlRelationalTableModel。用户接口层的类实现了将数据库中的数据链接到窗口部件上,是使用模型/视图框架实现的,是更高层次的抽象,即便不熟悉SQL也可以操作数据库。需要注意的是,在使用用户接口层的类之前必须先实例化QCoreApplication对象。

QT中使用了自己的机制来避免使用SQL语句,提供了更简单的数据库操作及数据显示模型,分别是只读的QSqlQueryModel、操作单表的QSqlTableModel和支持外键的QSqlRelationalTableModel。

02. 开发环境

Windows系统​:Windows10

Qt版本​:Qt5.15或者Qt6

03. QSqlQueryModel类

3.1 QSqlQueryModel类简介

QSqlQueryModel类为SQL结果集提供了只读的数据模型,是执行SQL语句和遍历结果集的高级接口。QSqlQueryModel基于下层的QSqlQuery构建,用于提供数据给QTableView等视图类。

QSqlQueryModel模型默认是只读的,通过QSqlQueryModel派生自定义类重写setData()和flags()函数可以实现读写,或是使用QSqlTableModel。

3.2 QSqlQueryModel类常用成员函数

QSqlQueryModel(QObject *parent = nullptr)
使用给定的parent创建一个空的QSqlQueryModel 。
virtual ~QSqlQueryModel()
销毁对象并释放所有分配的资源。
virtual void clear()
清除模型并释放所有获取的资源。
QSqlError lastError() const
返回有关数据库上发生的最后一个错误的信息。
QSqlQuery query() const
返回与此模型关联的QSqlQuery。
QSqlRecord record(int row) const
返回包含有关当前查询的字段信息的记录。如果row是有效行的索引,则将使用该行中的值填充记录。
如果未初始化模型,则将返回空记录。
QSqlRecord record() const
返回一个空记录,其中包含有关当前查询的字段的信息。
如果未初始化模型,则将返回空记录。
void setQuery(const QSqlQuery &query)
重置模型并将数据提供者设置为给定查询。请注意,查询必须处于活动状态,并且不能为isForwardOnly()。
如果设置查询时发生错误,lastError()可用于检索详细信息。
void setQuery(const QString &query, const QSqlDatabase &db = QSqlDatabase())
对给定的数据库连接db执行查询查询。如果未指定数据库(或无效的数据库),则使用默认连接。
如果设置查询时发生错误,lastError()可用于检索详细信息。

virtual QModelIndex indexInQuery(const QModelIndex &item) const
返回模型中给定项目的数据库结果集中的值的索引。
如果未插入,删除或移动任何列或行,则返回值与item相同。
如果item超出范围或item没有指向结果集中的值,则返回无效的模型索引。
virtual void queryChange()
每当查询更改时,都会调用此虚拟函数。默认实现不执行任何操作。
void setLastError(const QSqlError &error)
该函数允许派生类将数据库上发生的最后一个错误的值设置为error。

程序示例一:

QSqlQueryModel *model = new QSqlQueryModel;
model->setQuery("SELECT name, salary FROM employee");
model->setHeaderData(0, Qt::Horizontal, tr("Name"));
model->setHeaderData(1, Qt::Horizontal, tr("Salary"));
QTableView *view = new QTableView;
view->setModel(model);
view->show();

3.3 自定义QSqlQueryModel

QSqlQueryModel默认是只读的,在窗口上并不能对表格中的内容进行修改。如果要按照自己的需要显示数据和修改数据,可以创建自己的模型。要想使其可读

写,需要自己的类继承自QSqlQueryModel,并且重写setData()和flags()两个函数。如果要改变数据的显示,就要重写data() 函数。

Qt::ItemFlags flags(const QModelIndex &index) const;
bool setData(const QModelIndex &index, const QVariant &value, int role);
QVariant data(const QModelIndex &item, int role=Qt::DisplayRole) const;

04. QSqlTableModel类

4.1 QSqlTableModel类简介

QSqlTableModel提供了一个一次只能操作单个SQL表的读写模型,它是QSqlQuery的更高层次的替代品,可以浏览和修改独立的SQL表,并且只需编写很少的代码,而且不需要了解SQL语法。

QSqlTableModel类为单个数据库表提供了可编辑的数据模型,是从单个表中读写数据库记录的高级接口。QSqlTableModel基于下层的QSqlQuery构建,用于提供数据给QTableView等视图类。

4.2 QSqlTableModel类常用成员方法

QSqlTableModel::QSqlTableModel(QObject *parent = Q_NULLPTR, QSqlDatabase db = QSqlDatabase())
构建一个QSqlTableModel空对象,设置父对象为parent,数据库连接为db,如果db非法,使用默认数据库连接。

[signal] void QSqlTableModel::beforeDelete(int row)
[signal] void QSqlTableModel::beforeInsert(QSqlRecord &record)
[signal] void QSqlTableModel::beforeUpdate(int row, QSqlRecord &record)

QSqlDatabase QSqlTableModel::database() const
返回模型的数据库连接

[virtual protected] bool QSqlTableModel::deleteRowFromTable(int row)
从当前活跃的数据库表中删除给定的行

EditStrategy QSqlTableModel::editStrategy() const
返回当前的编辑策略

int QSqlTableModel::fieldIndex(const QString &fieldName) const
返回字段名为fieldName的字段的索引,如果没有相应字段返回-1

QString QSqlTableModel::filter() const
返回当前设置的过滤器

bool QSqlTableModel::insertRecord(int row, const QSqlRecord &record)
在row行插入一条记录record,如果row为负数,追加到尾部

bool QSqlTableModel::isDirty(const QModelIndex &index) const
如果index位置的值是脏值,返回true。脏值是被模型修改单尚未写入数据库的值

bool QSqlTableModel::isDirty() const
如果模型包含被修改的值并且没有提交到数据库,返回true

QSqlIndex QSqlTableModel::primaryKey() const
返回当前表的主键

程序示例一:结合模型视图显示

QSqlTableModel *model = new QSqlTableModel;
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 ID
view->show();

程序示例二:通过模型直接访问数据

QSqlTableModel model;
model.setTable("employee");
model.select();
int salary = model.record(4).value("salary").toInt();

程序示例三:增删改查

//查询操作
QString name = lineedit->text();
//根据姓名进行筛选
model->setFilter(QString("name = '%1'").arg(name));
//显示结果
model->select();
model->setTable("student"); //重新关联表
model->select();//选择整个表格


//排序操作
//升序:
model->setSort(0, Qt::AscendingOrder); //id属性即第0列,升序排列
model->select();

//降序:
model->setSort(0, Qt::DescendingOrder);
model->select();


//删除操作
//获取选中的行
int curRow = view->currentIndex().row();
//删除该行
model->removeRow(curRow);
int ok = QMessageBox::warning(this,tr("删除当前行!"),tr("你确定删除当前行吗?"),
QMessageBox::Yes,QMessageBox::No);
if(ok == QMessageBox::No)
{
model->revertAll(); //如果不删除,则撤销
}
else
model->submitAll(); //否则提交,在数据库中删除该行


//插入操作
int rowNum = model->rowCount(); //获得表的行数
int id = 10;
model->insertRow(rowNum); //添加一行
model->setData(model->index(rowNum,0),id);

05. QSqlRelationalTableModel类

5.1 QSqlRelationalTableModel简介

QSqlRelationalTableModel为了单个数据库表格提供了可编辑的数据模型。

QSqlRelationalTableModel继承自QSqlTableModel,并对其进行了扩展,提供了对外键的支持。外键就是一个表中的一个属性和其他表中的主键属性之间的一对一的映射。

5.2 QSqlRelationalTableModel常用成员方法

[virtual] void QSqlRelationalTableModel::setRelation(int column, const QSqlRelation &relation)
当前表中第column列为QSqlRelation(tableName,indexColumn,displayColumn)的外键

QVariant QSqlRelationalTableModel::data(const QModelIndex &index, int role = Qt::DisplayRole) const
返回index的数据

[virtual protected] bool QSqlRelationalTableModel::insertRowIntoTable(const QSqlRecord &values)
向表中插入一条记录values

QSqlRelation QSqlRelationalTableModel::relation(int column) const
返回表格中第column列的关系

[virtual] QSqlTableModel *QSqlRelationalTableModel::relationModel(int column) const
返回外键column要访问的表的QSqlTableModel对象

[virtual] bool QSqlRelationalTableModel::setData(const QModelIndex &index, const QVariant &value,
int role = Qt::EditRole)
设置index数据项的值为value,数据项角色为role

[virtual] void QSqlRelationalTableModel::setTable(const QString &table)
设置模型的表格为table

程序示例:

model->setTable("employee");

model->setRelation(2, QSqlRelation("city", "id", "name"));
model->setRelation(3, QSqlRelation("country", "id", "name"));

06. QSqlRelationalDelegate类

6.1 QSqlRelationalDelegate类简介

为了控制表中某些数据项的数据的可选类型或是数据内容,可以使用委托。QT提供了QSqlRelationalDelegate委托类,可以为QSqlRelationalTableModel显示和编辑数据。不同于默认的委托,QSqlRelationalDelegate为外键提供了字段的下拉框。

程序示例:

std::unique_ptr<QTableView> view{new QTableView};
view->setModel(model);
view->setItemDelegate(new QSqlRelationalDelegate(view.get()));

07. 附录