摘要:
这一篇Qt博文主要介绍在Qt开发中针对数据库相关开发时可以用到或参考的一些数据库类,例如显示数据库的数据通常涉及到几个关键组件,包括数据库连接、查询执行以及用户界面元素的更新等等,这些类的作用是什么,大致应该怎么用,类的常用类方法及相关需要注意的事项等等,更多更加细致的需根据类名查找翻阅官方帮助文档。
QT提供的与数据库操作相关的类有以下几个:
- QSqlDatabase:这个类用于处理与数据库的连接。
- QSqlError:这个类提供了在数据库连接或查询过程中发生错误时的关键信息。
- QSqlIndex:这个类用于表示数据库中的索引。
- QSqlQuery:这个类用于执行SQL语句并获取结果。
- QSqlQueryModel:这个类是一个基于SQL查询的模型,用于与视图(如
QTableView
)结合使用。 - QSqlRecord:这个类表示从数据库查询结果中检索到的一条记录。
- QSqlField:这个类表示数据库表或视图中单个列的特征。
- QSqlTableModel:这个类是一个基于数据库表的模型,为单个数据库表提供可编辑的数据模型。
- QSqlDriverPlugin:通过子类化这个基类,可以创建自己的SQL驱动插件。
- QSqlRelationalTableModel:这个类为单个数据库表提供了一个可编辑的数据模型,它支持外键和关系数据的展示和编辑。
开发环境:Qt5.14.1,Qt Creator 4.11.1
关键词
: Qt,数据库操作,sql,总结,QSqlDatabase,QSqlError,QSqlIndex,QSqlQuery,QSqlQueryModel,QSqlRecord,QSqlField,QSqlTableModel,QSqlDriverPlugin,QSqlRelationalTableModel
声明:
本文作者原创,转载请附上文章出处与本文链接。
文章目录
正文:
QSqlDatabase
这个类用于处理与数据库的连接。它提供了一个接口来访问数据库,并通过调用静态函数addDatabase()
来创建连接。一个QSqlDatabase
的实例代表一个数据库连接,该连接通过受支持的数据库驱动程序提供对数据库的访问。
常用成员函数:
addDatabase(const QString &type, const QString &connectionName = QString())
:用于添加一个新的数据库连接。type
参数指定数据库类型(如 “QMYSQL”, “QPSQL”, “QSQLITE” 等),connectionName
是连接的名称。database(const QString &connectionName = QString())
:返回指定名称的数据库连接。如果没有指定名称,则返回默认的数据库连接。removeDatabase(const QString &connectionName)
:移除指定的数据库连接。isOpen() const
:检查数据库连接是否打开。open()
:打开数据库连接。close()
:关闭数据库连接。lastError()
:返回最后一次数据库操作的错误信息。exec(const QString &query)
:执行 SQL 查询,并返回一个QSqlQuery
对象,用于处理查询结果。transaction()
:开始一个新的事务。commit()
:提交当前事务。rollback()
:回滚当前事务。
使用例子:
首先,确保你的 Qt 项目包含了 SQL 模块,可以通过项目文件(.pro
)来添加模块:
// .pro文件
QT += sql
然后在main.cpp即可:
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
// 添加数据库连接
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("path/to/your/database.db"); // 替换为你的数据库文件路径
// 打开数据库连接
if (!db.open()) {
qDebug() << "Error: Could not open database";
return -1;
}
// 执行 SQL 语句,创建表
QSqlQuery query;
if (!query.exec("CREATE TABLE person (id INT PRIMARY KEY, name VARCHAR(20))")) {
qDebug() << "Error: Could not create table";
return -1;
}
// 执行 SQL 语句,为刚刚创建的表插入数据
if (!query.exec("INSERT INTO person (id, name) VALUES (1, 'Alice')")) {
qDebug() << "Error: Could not insert data";
return -1;
}
// 执行查询并打印输出结果
query.exec("SELECT * FROM person");
while (query.next()) {
int id = query.value(0).toInt();
QString name = query.value(1).toString();
qDebug() << "ID:" << id << "Name:" << name;
}
// 关闭数据库连接
db.close();
return a.exec();
}
QSqlError
这个类提供了在数据库连接或查询过程中发生错误时的关键信息。它包含如错误消息、原生错误代码等属性,帮助开发者识别和处理数据库操作中的错误。
常用成员函数:
text() const
:返回描述错误的文本信息。这通常是一个人类可读的字符串,描述了错误的原因。nativeErrorCode() const
:返回数据库特定的错误代码。这个代码通常对于特定的数据库系统是有意义的,它可以帮助你更准确地诊断问题。type() const
:返回错误的类型。这通常是一个枚举值,表示错误的性质(例如,连接错误、查询错误等)。isValid() const
:返回一个布尔值,指示是否存在有效的错误信息。如果QSqlError
对象不包含错误(即没有错误发生),这个函数将返回false
。
使用例子:
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
// 添加数据库连接(这里以 SQLite 为例)
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("path/to/your/database.db");
if (!db.open()) {
// 处理数据库连接错误
QSqlError error = db.lastError();
qDebug() << "Database connection error:" << error.text();
return -1;
}
// 执行 SQL 查询
QSqlQuery query;
query.exec("SELECT * FROM non_existent_table"); // 假设这个表不存在
if (query.lastError().isValid()) {
// 处理查询错误
QSqlError error = query.lastError();
qDebug() << "Query error:" << error.text();
qDebug() << "Native error code:" << error.nativeErrorCode();
qDebug() << "Error type:" << error.type();
} else {
// 处理查询结果(在这个例子中,由于表不存在,不会执行到这里)
while (query.next()) {
// ... 处理每一行数据 ...
}
}
// 关闭数据库连接
db.close();
return a.exec();
}
QSqlIndex
这个类用于表示数据库中的索引。它通常用于优化查询性能,通过指定一个或多个字段来创建索引。
常用成员函数:
name() const
:返回索引的名称。setName(const QString &name)
:将索引的名称设置为name。append(const QSqlField &field, bool desc = false)
:向索引中添加一个字段,并指定是否按降序排序。setDescending(int i, bool desc)
:设置索引中指定位置的字段是否按降序排序。clear()
:清除索引中的所有字段。
使用例子:
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlIndex>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
// 添加数据库连接(这里以 SQLite 为例)
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("path/to/your/database.db");
if (!db.open()) {
// 处理数据库连接错误
qDebug() << "Error connecting to database";
return -1;
}
// 假设我们有一个名为 "employees" 的表,并且我们想按 "lastName" 字段降序排序
QSqlQuery query;
QSqlIndex index("lastName", true); // 创建一个降序索引
// 执行查询,使用 QSqlIndex 来指定排序条件,用prepare缓冲
query.prepare("SELECT * FROM employees ORDER BY :sortColumn");
query.bindValue(":sortColumn", index);
if (!query.exec()) {
// 处理查询错误
qDebug() << "Query error:" << query.lastError().text();
return -1;
}
// 处理查询结果
while (query.next()) {
QString lastName = query.value(index.fieldName(0)).toString();
qDebug() << "Last Name:" << lastName;
// ... 处理其他字段 ...
}
// 关闭数据库连接
db.close();
return a.exec();
}
QSqlQuery
这个类用于执行SQL语句并获取结果。它提供了执行查询、插入、更新和删除等操作的方法,并可以处理查询结果。
常用成员函数:
exec()
:执行 SQL 语句。对于非查询语句(如 INSERT、UPDATE、DELETE),此函数返回是否成功执行。prepare(const QString &query)
:准备 SQL 语句以供执行。这允许你使用占位符(如:placeholder
),并使用bindValue()
函数来绑定具体的值。bindValue(const QString &placeholder, const QVariant &val, QSql::ParamType type = QSql::In)
:绑定一个值到 SQL 语句中的占位符。这增加了安全性,并避免了 SQL 注入攻击。next()
:将查询结果的位置前进到下一行。在查询结果集上迭代时常用。seek(int row)
:将查询结果的位置移动到指定行。value(int index)
:返回当前行中指定列的值。列索引从 0 开始。record()
:返回当前行的QSqlRecord
对象,它包含行中所有字段的信息。lastError()
:返回最近一次数据库操作的错误信息。如果操作成功,则返回的QSqlError
对象将不包含有效的错误信息。isSelect()
:检查查询是否是 SELECT 语句。
使用例子:
#include <QCoreApplication>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
// 添加数据库连接
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("path/to/your/database.db");
if (!db.open()) {
// 无法打开数据库,处理错误
qDebug() << "无法连接到数据库: " << db.lastError().text();
return -1;
}
// 创建表
QSqlQuery query;
query.exec("CREATE TABLE employee ("
"id INTEGER PRIMARY KEY,"
"name TEXT NOT NULL,"
"age INTEGER)");
// 插入数据
query.exec("INSERT INTO employee (name, age) VALUES ('Alice', 30)");
query.exec("INSERT INTO employee (name, age) VALUES ('Bob', 25)");
query.exec("INSERT INTO employee (name, age) VALUES ('Charlie', 35)");
// 查询数据
query.exec("SELECT * FROM employee");
while (query.next()) {
int id = query.value(0).toInt();
QString name = query.value(1).toString();
int age = query.value(2).toInt();
qDebug() << "ID:" << id << "Name:" << name << "Age:" << age;
}
// 关闭数据库连接
db.close();
return a.exec();
}
QSqlQueryModel
这个类是一个基于SQL查询的模型,QSqlQueryModel
是执行SQL语句和遍历结果集的高级接口,它建立在较低级别的QSqlQuery
之上,用于与视图(如QTableView
)结合使用。它将SQL查询的结果封装成模型,方便在视图中展示和操作数据。
常用成员函数:
setQuery(const QString &query)
:设置要执行的 SQL 查询。rowCount(const QModelIndex &parent = QModelIndex()) const
:返回模型中的行数。columnCount(const QModelIndex &parent = QModelIndex()) const
:返回模型中的列数。data(const QModelIndex &index, int role = Qt::DisplayRole) const
:返回给定索引和角色的数据。index(int row, int column, const QModelIndex &parent = QModelIndex()) const
:返回对应于给定行和列的模型索引。record(int row) const
:返回包含有关当前查询字段信息的记录,即给定行的QSqlRecord
。lastError() const
:返回最后一次查询的错误信息。
使用例子:
当你创建 QSqlQueryModel
的实例时,它会在内部使用当前默认的数据库连接(通过 QSqlDatabase::database()
获取)来执行查询,如果你的程序有多个数据库连接,并且你想要 QSqlQueryModel
使用特定的连接,例如db2
,那么阔以通过 QSqlDatabase::setDatabaseDefault(db2)
将 db2
设置为默认数据库连接,或者可以使用 QSqlQuery
的构造函数来指定连接名称。
#include <QApplication>
#include <QSqlDatabase>
#include <QSqlQueryModel>
#include <QTableView>
#include <QDebug>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// 添加数据库连接(这里以SQLite为例)
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("path/to/your/database.db");
if (!db.open()) {
qDebug() << "无法连接到数据库: " << db.lastError().text();
return -1;
}
// 创建 QSqlQueryModel 实例
QSqlQueryModel *model = new QSqlQueryModel();
// 设置查询语句
model->setQuery("SELECT * FROM employee");
// 检查查询是否成功
if (model->lastError().isValid()) {
qDebug() << "查询错误: " << model->lastError().text();
return -1;
}
// 创建 QTableView 实例并设置模型
QTableView *view = new QTableView();
view->setModel(model);
view->show();
// 可选:设置表头标签
model->setHeaderData(0, Qt::Horizontal, QObject::tr("ID"));
model->setHeaderData(1, Qt::Horizontal, QObject::tr("Name"));
model->setHeaderData(2, Qt::Horizontal, QObject::tr("Age"));
// 关闭数据库连接
db.close();
return a.exec();
}
QSqlRecord
这个类表示从数据库查询结果中检索到的一条记录。它包含记录中的字段及其值,封装了数据库记录的功能和特征,通常是数据库中表或视图中的一行。通过QSqlRecord
,可以访问和修改数据库记录中的字段。
常用成员函数:
value(int i)
:返回指定索引i
的字段的值。value(const QString &name)
:返回指定名称name
的字段的值。fieldName(int i)
:返回指定索引i
的字段的名称。count()
:返回记录中的字段数量。isEmpty()
:如果记录为空,则返回true
。clear()
:清除记录中的所有字段。contains(const QString &name)
:如果记录包含指定名称name
的字段,则返回true
。setValue(int index, const QVariant &val)
:将位置索引处的字段值设置为val。如果该字段不存在,则不发生任何操作。setValue(const QString &name, const QVariant &val)
:将名为name的字段的值设置为val。
使用例子:
#include <QApplication>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QDebug>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// 添加数据库连接(这里以SQLite为例)
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("path/to/your/database.db");
if (!db.open()) {
qDebug() << "无法连接到数据库: " << db.lastError().text();
return -1;
}
// 执行查询
QSqlQuery query;
if (!query.exec("SELECT * FROM employee")) {
qDebug() << "查询失败: " << query.lastError().text();
return -1;
}
// 遍历查询结果
while (query.next()) {
// 获取当前行的 QSqlRecord
const QSqlRecord &record = query.record();
// 访问记录中的字段
for (int i = 0; i < record.count(); ++i) {
QString fieldName = record.fieldName(i);
QVariant fieldValue = record.value(i);
qDebug() << fieldName << ": " << fieldValue;
}
}
// 关闭数据库连接
db.close();
return a.exec();
}
QSqlField
这个类表示数据库表或视图中单个列的特征,QSqlField类
操作SQL数据库表和视图中的字段。通常通过QSqlRecord
或QSqlQueryModel
等类间接访问。
常用成员函数:
name() const
:返回字段的名称。setName(const QString &name)
:将字段的名称设置为name。value() const
:返回字段的值。setValue(const QVariant &value)
设置字段的值,实际不改变数据库内值。type() const
:返回字段的数据类型。setType(QVariant::Type type)
:设置字段的变量类型为type。isNull() const
:如果字段的值是 NULL,则返回true
。clear()
:清除字段的值。
使用例子:
#include <QApplication>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlRecord>
#include <QSqlField>
#include <QDebug>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// 添加数据库连接(这里以SQLite为例)
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("path/to/your/database.db");
if (!db.open()) {
qDebug() << "无法连接到数据库: " << db.lastError().text();
return -1;
}
// 执行查询
QSqlQuery query;
if (!query.exec("SELECT id, name FROM employee")) {
qDebug() << "查询失败: " << query.lastError().text();
return -1;
}
// 遍历查询结果
while (query.next()) {
// 获取当前行的 QSqlRecord
const QSqlRecord &record = query.record();
// 访问记录中的特定字段
QSqlField idField = record.field("id");
QSqlField nameField = record.field("name");
// 打印字段信息
qDebug() << "ID:" << idField.value();
qDebug() << "Name:" << nameField.value().toString();
// 修改字段值
// 注意:在实际应用中,直接修改查询结果中的字段值可能不是一个好主意,
// 因为这不会改变数据库中的实际数据。这里只是为了演示如何设置字段值。
nameField.setValue("Modified Name");
qDebug() << "Modified Name:" << nameField.value().toString();
}
// 关闭数据库连接
db.close();
return a.exec();
}
QSqlTableModel
这个类是一个基于数据库表的模型,为单个数据库表提供可编辑的数据模型。QSqlTableModel
是一个高级接口,用于从单个表中读写数据库记录, 它建立在较低级别的QSqlQuery
之上,可用于向QTableView
等视图类提供数据。
常用成员函数:
setTable(const QString &tableName)
:设置要查询的数据库表名。tableName() const
:返回当前选定表的名称。setEditStrategy(QSqlTableModel::EditStrategy strategy)
:将数据库中编辑值的策略设置为strategy。select()
:使用通过setTable()
设置的表中的数据填充模型,使用指定的筛选和排序条件。setFilter(const QString &filter)
:设置筛选条件,用于限制查询结果。setSort(int column, Qt::SortOrder order)
:将列的排序顺序设置为order
。submitAll()
:提交所有挂起的更改revertAll()
:重置所有缓存操作。index(int row, int column, const QModelIndex &parent = QModelIndex()) const
:返回模型中指定行和列的 QModelIndex。data(const QModelIndex &index, int role = Qt::DisplayRole) const
:返回模型中指定索引的数据,可以根据不同的角色(如显示、编辑等)返回不同的数据。setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole)
:设置模型中指定索引的数据。
使用例子:
#include <QApplication>
#include <QSqlDatabase>
#include <QSqlTableModel>
#include <QSqlRelationalTableModel>
#include <QTableView>
#include <QHeaderView>
#include <QDebug>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// 设置数据库连接(这里以SQLite为例)
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("path/to/your/database.db");
if (!db.open()) {
qDebug() << "Failed to open database";
return -1;
}
// 创建 QSqlTableModel 实例
QSqlTableModel *model = new QSqlTableModel();
model->setTable("students"); // 设置要查询的表名
model->setEditStrategy(QSqlTableModel::OnFieldChange); // 设置编辑策略,这里为字段更改时提交
// 设置过滤器,只显示年龄大于20的学生
model->setFilter("age > 20");
// 设置排序,按年龄升序排序
model->setSort(model->fieldIndex("age"), Qt::AscendingOrder);
model->select(); // 执行查询并填充模型
// 显示数据
QTableView *view = new QTableView();
view->setModel(model);
view->horizontalHeader()->setSortIndicator(model->fieldIndex("age"), Qt::AscendingOrder); // 设置表头排序指示器
view->show();
// 假设用户编辑了数据,我们需要提交这些更改到数据库
if (model->submitAll()) {
qDebug() << "Changes submitted successfully";
} else {
qDebug() << "Failed to submit changes";
}
// 关闭数据库连接
db.close();
return app.exec();
}
QSqlDriverPlugin
这个类为自定义的QSqlDriver
插件提供了一个抽象基类。通过子类化这个基类,可以创建自己的SQL驱动插件,这些插件可以通过Qt动态加载,这些插件为Qt提供了扩展数据库驱动支持的能力。进阶能力,大部分用不到,使用 Qt 已经提供的驱动程序即可。
使用例子:
#include <QSqlDriverPlugin>
#include <QSqlDriver>
#include <QSqlError>
#include <QString>
class MyCustomSqlDriverPlugin : public QSqlDriverPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QSqlDriverFactoryInterface" FILE "mydriver.json")
public:
MyCustomSqlDriverPlugin() = default;
QSqlDriver *create(const QString &name) override
{
if (name == "MYCUSTOMDB") {
MyCustomSqlDriver *driver = new MyCustomSqlDriver();
return driver;
}
return nullptr;
}
};
class MyCustomSqlDriver : public QSqlDriver
{
Q_OBJECT
public:
MyCustomSqlDriver() : QSqlDriver("MYCUSTOMDB") {}
bool open(const QString &db, const QString &user, const QString &password,
const QString &host, int port, const QString &connOpts) override
{
// 实现打开数据库连接的逻辑
// ...
return true; // 假设成功
}
// 实现其他必要的方法,如 close(), exec(), isOpen() 等
// ...
};
在这个例子中,MyCustomSqlDriverPlugin
类继承自 QSqlDriverPlugin
,并重写了 create
方法。这个方法根据提供的名称来创建并返回一个新的 QSqlDriver
实例。在这个例子中,如果名称是 “MYCUSTOMDB”,则创建一个 MyCustomSqlDriver
的实例。
MyCustomSqlDriver
类是 QSqlDriver
的子类,它必须实现打开数据库连接、执行 SQL 语句、关闭连接等必要的方法。在这个简化的例子中,这些方法并没有实际的实现。
为了使用这个插件,你需要将其编译为一个动态链接库(.dll、.so 或 .dylib 文件),并根据你的操作系统和 Qt 的配置将其放置在正确的插件目录中。然后,Qt SQL 模块在尝试连接数据库时会自动加载和使用这个插件。
QSqlTableModel
不直接支持外键。
如果要解析外键,请使用QSqlRelationalTableModel,QSqlRelationalDelegate。
QSqlRelationalTableModel
这个类为单个数据库表提供了一个可编辑的数据模型,它支持外键和关系数据的展示和编辑。QSqlTableModel
和QSqlRelationalTableModel
,它们没有太大的不同,唯一的就是后者在前者的基础之上添加了外键(或者叫外码)的支持。
具体来说,外键是约束定义从一个表(称为子表或引用表)到另一个表(称为父表或被引用表)的字段之间的关系,说简单点就是将两个相关的表建立一个桥梁,让它们关联起来。
常用成员函数:
setRelation(int column, const QSqlRelation &relation)
:在模型的列和另一个数据库表之间建立关系。这通常用于处理外键。主要是这个,其它成员函数以及显示数据方法和QSqlTableModel
几乎无差。setTable(const QString &tableName)
:设置要查询的数据库表名。tableName() const
:返回当前选定表的名称。setEditStrategy(QSqlTableModel::EditStrategy strategy)
:将数据库中编辑值的策略设置为strategy。select()
:使用通过setTable()
设置的表中的数据填充模型,使用指定的筛选和排序条件。setFilter(const QString &filter)
:设置筛选条件,用于限制查询结果。setSort(int column, Qt::SortOrder order)
:将列的排序顺序设置为order
。submitAll()
:提交所有挂起的更改revertAll()
:重置所有缓存操作。index(int row, int column, const QModelIndex &parent = QModelIndex()) const
:返回模型中指定行和列的 QModelIndex。data(const QModelIndex &index, int role = Qt::DisplayRole) const
:返回模型中指定索引的数据,可以根据不同的角色(如显示、编辑等)返回不同的数据。setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole)
:设置模型中指定索引的数据。
使用例子:
我们有两个数据库表:employees
和 departments
。employees
表有一个字段 department_id
,它是 departments
表中 id
字段的外键。
CREATE TABLE departments (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE employees (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
department_id INTEGER,
FOREIGN KEY(department_id) REFERENCES departments(id)
);
使用 QSqlRelationalTableModel
来表示这两个表之间的关系,并通过QTableView
显示员工及其所在部门的信息。
#include <QApplication>
#include <QTableView>
#include <QSqlDatabase>
#include <QSqlRelationalTableModel>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// 初始化数据库连接
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("path/to/your/database.db");
if (!db.open()) {
qDebug() << "Error opening database:" << db.lastError();
return -1;
}
// 创建 QSqlRelationalTableModel 实例
QSqlRelationalTableModel *model = new QSqlRelationalTableModel;
model->setTable("employees"); // employees 表已经存在
model->setRelation(model->fieldIndex("department_id"), // department_id 是外键字段
QSqlRelation("departments", "id", "name")); // departments 表和字段已经存在
model->select(); // 查询数据
// 显示模型数据
QTableView *view = new QTableView;
view->setModel(model);
view->show();
// 关闭数据库连接
db.close();
return app.exec();
}