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