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.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
返回模型的角色名称。
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::Horizontal。
此函数不能用于修改数据库中的值,因为模型是只读的。
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 类为单个数据库表提供可编辑的数据模型,继承自 QSqlQueryModel,它是用于从单个表中读取和写入数据库记录的高级接口。它建立在较低级别的 QSqlQuery 之上,可用于为 QTableView 等视图类提供数据。
#include
#include
#include
#include
#include
#include
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()<
上面的代码片段从查询 SELECT * from person 的结果集中的记录 1 中提取“职业”字段。
可以使用 setFilter() 设置过滤器,或使用 setSort() 修改排序顺序。最后必须调用 select() 以使用数据填充模型。
QSqlTableModel 不直接支持外键。如果要解析外键,应使用 QSqlRelationalTableModel 和 QSqlRelationalDelegate。
1、enum QSqlTableModel::EditStrategy:此枚举描述了在编辑数据库中的值时选择的策略。
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:此枚举描述了小部件中的项目是如何排序的。
28、void setTable(const QString &tableName)
设置模型操作的数据库表。不会从表中选择数据,但获取其字段信息。
29、void sort(int column, Qt::SortOrder order)
对数据进行排序。
30、bool updateRowInTable(int row, const QSqlRecord &values)
使用指定值更新当前活动数据库表中的给定行。
这是一种直接对数据库进行操作的低级方法,不建议使用用。建议使用 setData() 更新值。模型将根据其编辑策略决定何时修改数据库。