Qt数据库模块概述与使用详解
软件安装教程:https://subingwen.cn/qt/sql-driver/
1. 概述
Qt框架中对数据库操作提供了很好的支持,我们可以通过Qt提供的类非常方便地和本地或者远程数据库进行连接。
众所周知,数据库是 C-S(client-server)结构的,我们要连接的数据库属于服务器端,通过Qt编写的应用程序属于客户端。
如果想通过Qt访问数据库,首先我们需要在项目中添加数据库模块,模块名为 sql
。
找到项目文件 xxx.pro
,把模块名加进去:
Cpp
QT += core gui sql
💡 这个
sql
模块对应的是一个动态库,包含数据库相关类的二进制源码。使用时会被加载到内存中,按需提供服务。
Qt中常用的数据库相关类:
QSqlDatabase
:添加/删除/复制/关闭数据库实例QSqlQuery
:数据库查询类QSqlRecord
:代表一行记录(表或视图中的一行)QSqlField
:代表一个字段(列)的信息QSqlQueryModel
:可用于视图展示的结果集接口QSqlError
:用于获取数据库操作失败的信息
!NOTE\] Qt中操作数据库的大致流程如下: 1. 创建数据库实例并初始化 2. 连接数据库 3. 执行增删查改等SQL语句 4. 关闭数据库
2. 类的使用
2.1 QSqlDatabase
QSqlDatabase
类提供了连接数据库的接口,一个实例表示一个连接。
常用静态函数
- 获取支持的数据库驱动名列表:
cpp
QStringList QSqlDatabase::drivers();
输出示例:
text
("QSQLITE", "QMYSQL", "QMYSQL3", "QOCI", "QOCI8", "QODBC", "QODBC3", "QPSQL", "QPSQL7")
💡 有些驱动如 MySQL、Oracle 在高版本 Qt 中需要手动编译。
- 添加数据库连接实例:
cpp
QSqlDatabase QSqlDatabase::addDatabase(const QString &type, const QString &connectionName = QLatin1String("defaultConnection"));
参数说明:
type
:数据库驱动名(如 "QMYSQL", "QOCI")connectionName
:连接名,默认是 "defaultConnection"- 通过连接名获取数据库实例:
cpp
QSqlDatabase QSqlDatabase::database(const QString &connectionName = QLatin1String("defaultConnection"), bool open = true);
- 判断连接是否存在:
cpp
bool QSqlDatabase::contains(const QString &connectionName = QLatin1String("defaultConnection"));
常用成员函数
- 设置连接参数:
cpp
void setDatabaseName(const QString &name);
void setHostName(const QString &host);
void setPort(int port);
void setUserName(const QString &name);
void setPassword(const QString &password);
- 连接和关闭数据库:
cpp
bool open(); // 成功返回 true,失败返回 false
bool isOpen() const;
void close();
- 获取错误信息:
cpp
QSqlError lastError() const;
QString QSqlError::text() const;
事务控制:Qt 数据库模块(QSqlDatabase
)中用于事务处理 的核心方法,目的是保证数据库操作的数据一致性与完整性。
bool transaction();
🔹 作用:开启事务
- 启动一个事务块,在事务块内进行的所有操作要么全部执行成功 ,要么全部不生效(可回滚)。
它告诉数据库:"从现在开始,我要执行一系列操作,这些操作要么全部成功、要么一个都不生效。
- 适用于需要多步写操作的场景 ,比如插入多行数据、更新多个表等。
🔸 使用场景示例:
cpp
db.transaction(); // 开启事务
bool commit();
🔹 作用:提交事务->(让所有更改"落盘"保存)
- 如果事务块中的所有 SQL 操作都成功,就使用
commit()
提交,表示这些操作将永久写入数据库 。
🔸 使用场景示例:
cpp
if (flag) {
db.commit(); // 所有操作成功,提交事务
}
bool rollback();
🔹 作用:回滚事务 ->撤销自 transaction()
以来的所有更改
- 如果事务中的任意操作失败 ,使用
rollback()
将数据库状态恢复到事务开始之前的样子。 - 防止数据处于"部分成功"状态,保持一致性。
🔸 使用场景示例:
cpp
else {
db.rollback(); // 有操作失败,全部撤销
}
2.2 QSqlQuery
QSqlQuery
封装了执行 SQL 查询的操作,支持 DML(如 INSERT)与 DDL(如 CREATE)语句。
构造函数:
cpp
QSqlQuery(const QString &query = QString(), QSqlDatabase db = QSqlDatabase());
参数说明:
query
:要执行的 SQLdb
:数据库实例对象(可选)
执行 SQL:
cpp
bool exec(); // 执行构造时传入的 SQL
bool exec(const QString &query); // 执行指定 SQL
遍历结果集:
cpp
bool next(); // 移动到下一条记录,成功返回 true
获取字段值:
cpp
QVariant value(int index) const;
QVariant value(const QString &name) const;
💡
QVariant
是 Qt 中的通用类型包装器,需调用.toString()
.toInt()
等取出真实类型。
3. 示例代码(以 Oracle 数据库为例)
cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//获取本地支持的数据库驱动(建议首次使用时执行,便于确认可用驱动)
// QSqlDatabase::drivers() 是一个静态函数,
//返回当前Qt环境支持的数据库驱动名列表。
QStringList ls = QSqlDatabase::drivers();
qDebug() << ls;
// 示例输出: ("QSQLITE", "QMYSQL", "QOCI", ...)
// 添加一个数据库连接实例
// addDatabase("QOCI") 表示使用 Oracle 驱动创建一个数据库连接实例,默认连接名为 "defaultConnection"
QSqlDatabase db = QSqlDatabase::addDatabase("QOCI");
// 设置连接参数信息(包括主机名、端口、数据库名、用户名和密码)
// 这些函数分别对应服务器连接的必要参数,必须在调用 open() 之前设置
db.setHostName("110.22.80.130");
// setHostName(): 设置数据库服务器主机IP
db.setPort(1521);
// setPort(): 设置端口号,Oracle 默认端口为 1521
db.setDatabaseName("orcl");
// setDatabaseName(): 设置数据库服务名或实例名
db.setUserName("scott");
// setUserName(): 设置用户名
db.setPassword("scott");
// setPassword(): 设置用户密码
//尝试连接数据库,调用 open() 方法后根据返回值判断连接是否成功
bool bl = db.open();
// open(): 尝试与数据库建立连接,成功返回 true
if(!bl)
{
// lastError().text() 获取连接失败的错误描述信息
qDebug() << db.lastError().text();
// 打印错误信息
return;
}
else
{
qDebug() << "数据库连接成功了...";
}
QSqlQuery query;
// 创建一个默认连接的查询对象
//插入数据前开启事务,保障操作的原子性和一致性
//transaction():启动一个事务,适用于写入类操作(insert/update/delete)
QString sql = "insert into dept values(23, '火影忍者', '东京')";
db.transaction();
// 启动事务
//执行插入语句
bool flag = query.exec(sql);
// exec(sql): 执行 SQL 语句,成功返回 true
if(flag)
{
db.commit();
// commit(): 提交事务,将改动写入数据库
}
else
{
db.rollback();
// rollback(): 回滚事务,恢复到事务开启前的状态
}
//执行 SELECT 查询,获取结果集
query.exec("select dname, loc from dept");
//通过 while 循环遍历结果集
// next(): 将查询游标移动到下一行,成功返回 true
while(query.next())
{
// value(int index): 根据字段索引获取字段值
// value(QString name): 根据字段名获取字段值
// toString(): 将 QVariant 类型转换为 QString 输出
qDebug() << query.value(0).toString()
// 输出字段索引 0 的值(dname)
<< query.value(1).toString()
// 输出字段索引 1 的值(loc)
<< query.value("dname").toString()
// 输出字段名为 dname 的值
<< query.value("loc").toString();
// 输出字段名为 loc 的值
}
//关闭数据库连接,释放资源
db.close(); // close(): 断开数据库连接,通常在程序结束或数据库操作完成后调用
}
数据库实例 = 运行中的数据库软件 + 占用的内存结构 + 后台进程,它让数据库"活着",能接受你连接、查询、存储数据。
!NOTE\] 想象你有一个图书馆系统软件(比如 Oracle 或 MySQL): * 📁 **数据库**:就是图书馆里的一堆书架(存储数据的结构) * ⚙️ **数据库实例**:就是图书管理员(负责接待查询、借书、维护的"运行中进程")
名称 | 含义 | 你在 Qt 中怎么用 |
---|---|---|
数据库 | 存储结构(表、索引等) | 用 SQL 操作(SELECT、INSERT) |
实例 | 数据库运行时的进程和内存 | setDatabaseName("orcl") 指定要连的 Oracle 实例 |
表 | 实际存数据的结构 | SELECT * FROM dept |
📚 作者:苏丙榅
🔗 来源:爱编程的大丙
📄 著作权归作者所有,非商业转载请注明出处。