使用 SQL 模型类
除了 QSqlQuery,Qt 还提供了三个更高级的类用于访问数据库。这些类是 QSqlQueryModel、QSqlTableModel 和 QSqlRelationalTableModel。
QSqlQueryModel | 基于任意 SQL 查询的可读模型。 |
QSqlTableModel | 基于单个表的读写模型。 |
QSqlRelationalTableModel | 支持外键的 QSqlTableModel 子类。 |
这些类都从 QAbstractTableModel 继承(后者又继承自 QAbstractItemModel),使得在 QListView 和 QTableView 等项视图类中显示数据库数据变得容易。这将在 在表格视图中显示数据 部分详细解释。
使用这些类的另一个优点是可以使你的代码更容易适应其他数据源。例如,如果你使用 QSqlTableModel,后来决定用 XML 文件而不是数据库来存储数据,本质上只需用一个数据模型替换另一个。
SQL 查询模型
QSqlQueryModel 提供基于 SQL 查询的可读模型。
示例
QSqlQueryModel model; model.setQuery("SELECT * FROM employee"); for (int i = 0; i < model.rowCount(); ++i) { int id = model.record(i).value("id").toInt(); QString name = model.record(i).value("name").toString(); qDebug() << id << name; }
使用 QSqlQueryModel::setQuery() 设置查询后,您可以使用 QSqlQueryModel::record(int) 访问单个记录。您还可以使用 QSqlQueryModel::data() 和从 QAbstractItemModel 继承的其他任何函数。
还有一个重载函数 setQuery(),它接受一个 QSqlQuery 对象并对其结果集进行操作。这使得您可以使用 QSqlQuery 的任何功能来设置查询(例如,预编译查询)。
SQL 表模型
QSqlTableModel 提供了对单个 SQL 表进行操作的读写模型。
示例
QSqlTableModel model; model.setTable("employee"); model.setFilter("salary > 50000"); model.setSort(2, Qt::DescendingOrder); model.select(); for (int i = 0; i < model.rowCount(); ++i) { QString name = model.record(i).value("name").toString(); int salary = model.record(i).value("salary").toInt(); qDebug() << name << salary; }
QSqlTableModel 是 QSqlQuery 的一个高级替代品,用于导航和修改单个 SQL 表。通常这会导致代码量减少,且无需了解 SQL 语法。
使用 QSqlTableModel::record() 获取表中的一行,使用 QSqlTableModel::setRecord() 修改行。例如,以下代码会将每个员工的薪水增加 10%。
for (int i = 0; i < model.rowCount(); ++i) { QSqlRecord record = model.record(i); double salary = record.value("salary").toInt(); salary *= 1.1; record.setValue("salary", salary); model.setRecord(i, record); } model.submitAll();
您还可以使用从QAbstractItemModel继承的QSqlTableModel::data() 和 QSqlTableModel::setData(),以访问数据。例如,以下是使用setData()更新记录的方法
model.setData(model.index(row, column), 75000); model.submitAll();
以下是如何插入行并填充数据
model.insertRows(row, 1); model.setData(model.index(row, 0), 1013); model.setData(model.index(row, 1), "Peter Gordon"); model.setData(model.index(row, 2), 68500); model.submitAll();
以下是删除连续五行的方法
model.removeRows(row, 5); model.submitAll();
QSqlTableModel::removeRows()的第一个参数是要删除的第一行的索引。
完成一个记录的更改后,您应该始终调用QSqlTableModel::submitAll()以确保更改写入到数据库。
何时以及是否需要调用submitAll()取决于表的编辑策略。默认策略是QSqlTableModel::OnRowChange,它指定在用户选择不同的行时应用挂起的更改。其他策略包括QSqlTableModel::OnManualSubmit(将所有更改缓存到模型中,直到您调用submitAll())和QSqlTableModel::OnFieldChange(不缓存任何更改)。这些策略在QSqlTableModel与视图一起使用时非常有用。
QSqlTableModel::OnFieldChange似乎承诺您永远不需要显式地调用submitAll()。但是有两个陷阱:
- 在没有缓存的情况下,性能可能会显著下降。
- 如果您修改主键,记录可能在您尝试填充时通过您的手指滑走。
SQL关系表模型
QSqlRelationalTableModel扩展QSqlTableModel以提供对外键的支持。外键是一个表中的一个字段与其他表的主键字段之间的1对1映射。例如,如果有一个名为book
的表有一个名为authorid
的字段,它引用作者表的id
字段,那么我们说authorid
是一个外键。
左边的截图显示了一个普通QSqlTableModel在QTableView中的样子。外键(city
和country
)没有被解析为可读的文本值。右边的截图显示了一个QSqlRelationalTableModel,其外键被解析为人类可读的文本字符串。
以下代码片段显示了如何设置QSqlRelationalTableModel
model->setTable("employee"); model->setRelation(2, QSqlRelation("city", "id", "name")); model->setRelation(3, QSqlRelation("country", "id", "name"));
有关详细信息,请参阅QSqlRelationalTableModel文档。
© 2024 Qt公司有限公司的版权。本文件中包含的文档贡献是相关所有者的版权。本文件中所提供的文档是根据自由软件基金会发布的GNU自由文档许可证版本1.3的条款许可的。Qt及其相应的标志是芬兰和/或其他国家的Qt公司有限公司的商标。所有其他商标均为各自所有者的财产。