数据库
要使用以下类,需要在项目文件(.pro文件)中添加“QT十=sql”这一行代码
Qt中的SQL模块基本分为3层
在用户接口层,有以下三个类:
- QSqlQueryModel:用于管理SQL查询结果的模型。它提供了一个表格格式的数据模型,可以用来在界面上展示数据库查询的结果。
- QSqlTableModel:这是一个结合了数据表和编辑功能的模型。它提供了直接操作数据库表的能力,并可以显示和编辑表中的数据。
- QSqlRelationalTableModel:与QSqlTableModel类似,但它还支持处理表之间的关系,特别适用于处理包含外键的数据库表。
在SQL接口层,有以下类:
- QSqlDatabase:代表一个数据库连接,用于执行SQL命令和查询。
- QSqlQuery:用于执行SQL查询和命令的对象。
- QSqlError:描述在数据库操作期间发生的错误。
- QSqlField:表示数据库表中的字段或列。
- QSqlIndex:表示数据库表的索引。
- QSqlRecord:封装了数据库记录的功能和特性(通常是数据库中表或视图中的一行)。QSqlRecord 支持添加和移除字段,以及设置和检索字段值。
在驱动层,有以下类:
- QSqlDriver:提供了数据库驱动的抽象接口,具体的数据库实现需要继承此类。
- QSqlDriverCreator:用于创建特定数据库驱动的工厂类。
- QSqlDriverCreatorBase:可能是QSqlDriverCreator的基类或辅助类。
- QSqlDriverPlugin:插件机制的一部分,用于加载和管理数据库驱动。
- QSqlResult:表示数据库查询的结果集。
-
连接数据库
SQL数据库驱动
Qt SQL模块使用数据库驱动插件来和不同的数据库接口进行通信。由于Qt SQL模块的接口是独立于数据库的,所以所有数据库特定的代码都包含在这些驱动中。Qt默认支持一些驱动,也可以添加其他驱动,Qt中包含的驱动如下表所示。
创建数据库连接
要想使用QSqIQuery或者QSqlQuery Model来访问数据库,那么先要创建并打开一个或者多个数据库连接。数据库连接使用连接名来定义,而不是使用数据库名,可以向相同的数据库创建多个连接。QSqlDatabase也支持默认连接的概念,默认连接就是一个没有命名的连接。在使用QSqlQuery或者QSqlQueryModel的成员函数时需要指定一个连接名作为参数,如果没有指定,那么就会使用默认连接。如果应用程序中只需要有一个数据库连接,那么使用默认连接是很方便的。创建一个连接会创建了一个QSqlDatabase类的实例,只有调用open()函数后该连接才可以被使用。下面的代码片段显示了怎样创建一个默认的连接,然后打开它:
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL"); // 创建一个名为db的QSqlDatabase对象,并设置数据库驱动为MySQL
db.setHostName("bigblue"); // 设置主机名为bigblue
db.setDatabaseName("flightdb"); // 设置数据库名为flightdb
db.setUserName("acarlson"); // 设置用户名为acarlson
db.setPassword("1uTbSbAs"); // 设置密码为1uTbSbAs
bool ok = db.open(); // 打开数据库连接,并将连接状态保存在变量ok中
以上为默认连接,以下创建了两个名为first和second的连接
QSqlDatabase firstDB =QSqlDatabase:addDatabase("OMYSOL","first");
QSqlDatabase secondDBQSqlDatabase:addDatabase("OMYSOL","second");
执行SQL语句
执行一个查询
调用QSqlQuery::exec()函数即可
QSqlQuery query;
query.exec("select * from student");
浏览结果集
执行完exec()函数后,QSqlQuery的内部指针会位于第一条记录前面的位置,必须调用一次next()函数来使其前进到第一条记录,然后可以重复使用next()函数来访问其他记录,直到该函数的返回值为false
while(query.next())
{
qDebug()<<query.value(0).toInt()<<query.value(1).toString();
}
其中,QSqlQuery::value()函数可以返回当前记录的一个字段值。比如value(0)就是第一个字段的值,各个字段从0开始编号。该函数返回一个QVariant,不同的数据库类型自动映射为Qt中最接近的相应类型,这里的toInt()和toString()就是将QVariant转换为int和QString类型。
用SQL模型类
SQL查询模型
QSqlQueryModel是Qt框架中用于在Qt应用程序中显示数据库查询结果的模型类。它继承自QAbstractItemModel类,因此可以与Qt的视图部件(如QTableView、QListView等)进行无缝集成。下面是QSqlQueryModel中一些常用的函数:
- setQuery(const QSqlQuery& query): 这个函数用于设置QSqlQueryModel的查询语句。传入一个QSqlQuery对象,该对象包含了要执行的SQL查询语句。一旦设置了查询,QSqlQueryModel会根据该查询从数据库中检索数据,并将结果保存在模型中。
- query() const: 返回当前QSqlQueryModel对象所使用的查询。
- lastError() const: 如果最后一次执行的查询出现错误,此函数返回一个描述错误的QSqlError对象。如果查询成功,返回一个空的QSqlError对象。
- record() const: 返回模型中的字段信息。返回一个QSqlRecord对象,该对象描述了查询结果中的字段名称和类型。
- clear(): 清除模型中的数据。调用此函数后,模型中的所有数据将被清除,并且模型将成为空模型。
- rowCount(const QModelIndex& parent = QModelIndex()) const: 返回模型中行的数量。如果提供了parent参数,则返回指定父索引下的子项数量。如果parent参数为空,则返回顶级项的数量。
- columnCount(const QModelIndex& parent = QModelIndex()) const: 返回模型中列的数量。如果提供了parent参数,则返回指定父索引下的子项的列数。如果parent参数为空,则返回顶级项的列数。
- data(const QModelIndex& index, int role = Qt::DisplayRole) const: 返回指定索引处的数据。可以通过role参数指定要获取的数据角色,常见的角色包括Qt::DisplayRole(用于显示数据)、Qt::EditRole(用于编辑数据)等。
这里先创建了QSqlQuery Model对象,然后使用setQuery()来执行SQL语句查询整张student表,并使用setHeaderData()来设置显示的标头。后面创建了视图,并将
QSqIQuery Model对象作为其要显示的模型。注意,其实QSqlQuery Model中存储的是执行完setQuery()函数后的结果集,所以视图中显示的是结果集的内容。
还要注意一点就是,如果现在又使用setQuery()进行了新的查询,比如进行了插入操作,这时要想视图中可以显示操作后的结果,那么就必须再次查询整张表
SQL表格模型
QSqlTableModel
是Qt框架提供的一个用于连接数据库表格的模型类,它是QSqlQueryModel
的子类。与QSqlQueryModel
只能用于执行查询不同,QSqlTableModel
提供了对单个数据库表格的读写操作,可以方便地进行数据的增删改查。
以下是QSqlTableModel
的一些重要特点和使用方法:
- 编辑操作:
QSqlTableModel
允许对数据库表格进行编辑操作,包括插入、删除和修改数据。这些操作可以通过模型提供的接口函数实现,也可以通过视图部件(如QTableView
)提供的默认编辑功能完成。 - 保存操作:一旦对模型中的数据进行了修改,可以通过
submitAll()
或submit()
函数将修改保存到数据库中。submitAll()
函数会保存所有的修改,而submit()
函数只会保存当前行的修改。 - 撤销操作:如果修改操作出现错误或者需要取消已经进行的修改,可以使用
revertAll()
或revert()
函数将模型中的数据恢复到最初状态。 - 数据校验:
QSqlTableModel
提供了数据校验的机制,可以通过重写setData()
函数来对数据进行校验,确保输入的数据符合预期的格式和要求。 - 信号与槽:
QSqlTableModel
会发出一系列与数据修改相关的信号,如dataChanged()
、rowsInserted()
、rowsRemoved()
等,可以通过连接这些信号与自定义的槽函数来实现特定的功能。 - 过滤与排序:可以通过
setFilter()
函数设置过滤条件,只显示符合条件的数据;通过setSort()
函数设置排序规则,对数据进行排序显示。 - 关联外键:
QSqlTableModel
可以自动处理外键之间的关联关系,使得在视图中显示外键对应的实际数据而不是外键值。 - 线程安全性:
QSqlTableModel
并不是线程安全的,通常情况下应该在主线程中使用。
下面是一个简单的例子,展示了如何使用 QSqlTableModel
从 SQLite 数据库中读取数据并在 QTableView
中显示这些数据:
#include <QApplication>
#include <QTableView>
#include <QSqlDatabase>
#include <QSqlTableModel>
#include <QSqlQuery>
#include <QSqlError>
#include <QDebug>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
// 创建数据库连接
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(":memory:"); // 使用内存数据库,仅作为示例
if (!db.open()) {
qDebug() << "Error opening database:" << db.lastError();
return -1;
}
// 创建表格(仅作为示例)
QSqlQuery query;
query.exec("CREATE TABLE person (id INTEGER PRIMARY KEY, name VARCHAR(20))");
// 插入一些数据(仅作为示例)
query.exec("INSERT INTO person (name) VALUES ('Alice')");
query.exec("INSERT INTO person (name) VALUES ('Bob')");
query.exec("INSERT INTO person (name) VALUES ('Charlie')");
// 使用 QSqlTableModel
QSqlTableModel *model = new QSqlTableModel();
model->setTable("person"); // 设置要查询的表格
model->select(); // 执行查询并填充模型
model->setHeaderData(0, Qt::Horizontal, QObject::tr("ID")); // 设置列标题
model->setHeaderData(1, Qt::Horizontal, QObject::tr("Name"));
// 创建并设置视图
QTableView *view = new QTableView();
view->setModel(model); // 将模型设置为视图的模型
view->show();
return app.exec();
}
SQL关系表格
QSqlRelationalTableModel
是QSqlTableModel
的一个子类,它提供了对数据库中具有关联关系的表格数据的支持。在关系型数据库中,有时候表格之间会存在关联关系,比如外键约束,这种情况下就可以使用QSqlRelationalTableModel
来处理这些关联关系。
QSqlRelationalTableModel
与QSqlTableModel
相比,增加了一些额外的功能:
- 外键关联:
QSqlRelationalTableModel
可以根据外键约束自动加载关联表格的数据,并在视图中显示关联表格的实际数据而不是外键值。 - 编辑关联数据:可以在视图中编辑关联表格的数据,
QSqlRelationalTableModel
会自动将编辑的数据映射到关联表格中。 - 排序与过滤关联数据:可以对关联表格的数据进行排序和过滤,
QSqlRelationalTableModel
会处理关联表格之间的关联关系,确保排序和过滤的正确性。 - 信号与槽:与
QSqlTableModel
类似,QSqlRelationalTableModel
也会发出与数据修改相关的信号,可以连接这些信号与槽函数来实现特定的功能。
下面是一个简单的示例,演示了如何使用QSqlRelationalTableModel
类连接数据库中具有外键关联的表格,并在Qt应用程序中显示关联数据:
#include <QApplication>
#include <QSqlDatabase>
#include <QSqlRelationalTableModel>
#include <QTableView>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
// 连接数据库
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("company.db");
if (!db.open()) {
qDebug() << "Failed to open database!";
return -1;
}
// 创建QSqlRelationalTableModel并设置表格名称和外键关联
QSqlRelationalTableModel model;
model.setTable("employees");
// 第三个字段departments是一个外键指向它映射到了员工表中的id字段而视图需要显示员工表中的name字段
model.setRelation(2, QSqlRelation("departments", "id", "name"));
// 从数据库加载数据
if (!model.select()) {
qDebug() << "Failed to select data from table!";
return -1;
}
// 创建视图部件并设置模型
QTableView tableView;
tableView.setModel(&model);
tableView.resize(600, 400);
tableView.show();
return app.exec();
}
在这个例子中,我们连接了一个SQLite数据库,然后创建了一个QSqlRelationalTableModel
对象,并通过setRelation()
函数设置了员工表格与部门表格之间的外键关联。接着,通过调用select()
函数从数据库中加载数据到模型中。最后,创建了一个QTableView
视图部件,并将模型设置为QSqlRelationalTableModel
对象,以显示关联数据。运行该示例,将会在窗口中显示员工表格的数据,并且在部门字段中显示部门名称而不是部门ID。