当前位置: 首页 > news >正文

Qt中使用MySQL数据库

一、MySQL 入门

核心概念

在 QT 中操作数据库,主要使用两个模块:

  1. QSqlDatabase:代表一个数据库连接。

  2. QSqlQuery:用于执行 SQL 语句(如 SELECTINSERTUPDATEDELETE)并处理结果。

环境准备

在编写代码之前,你需要确保系统已具备以下条件:

1. 安装 MySQL
  • 从 MySQL 官网 下载并安装 MySQL 服务器和客户端。

  • 记住你设置的 root 密码,或者创建一个用于测试的新数据库用户。

2. 安装 QT
  • 确保你的 QT 安装包含了 Qt SQL 模块。在安装 QT 时,通常默认会包含。

3. 安装 MySQL 驱动(最关键的一步)

QT 默认可能不包含 MySQL 的驱动插件,你需要自己编译或确保它存在。

检查现有驱动:
你可以写一个简单的程序来查看当前可用的数据库驱动。

cpp

#include <QCoreApplication>
#include <QSqlDatabase>
#include <QDebug>int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);qDebug() << "Available drivers:";QStringList drivers = QSqlDatabase::drivers();foreach(QString driver, drivers)qDebug() << driver;return 0;
}

如果输出中包含 "QMYSQL" 或 "QMYSQL3",说明驱动已安装。如果没有,你需要手动编译。

如何编译 MySQL 驱动?

  1. 找到 QT 的源码目录:确保你有 QT 的源代码。路径通常像 ~/Qt/5.15.2/Src (5.15.2 是版本号)。

  2. 找到驱动代码:进入 ~/Qt/5.15.2/Src/qtbase/src/plugins/sqldrivers/mysql

  3. 编译

    • Windows: 使用 Qt Creator 打开该目录下的 .pro 工程文件进行编译。你需要确保在项目的构建设置中指定 MySQL 的 include 和 lib 目录。

    • Linux (Ubuntu/Debian):

      bash

      # 安装 MySQL 开发文件
      sudo apt-get install libmysqlclient-dev# 进入驱动目录
      cd ~/Qt/5.15.2/Src/qtbase/src/plugins/sqldrivers# 使用 qmake 生成 Makefile,指定 MySQL 的路径(如果不在标准路径)
      qmake -- MYSQL_PREFIX=/usr/include/mysql # 或者你的 MySQL 安装路径
      make
      make install # 将编译好的插件复制到 QT 的插件目录
    • macOS (使用 Homebrew):

      bash

      # 安装 MySQL
      brew install mysql# 进入驱动目录
      cd ~/Qt/5.15.2/Src/qtbase/src/plugins/sqldrivers# 使用 qmake
      qmake "INCLUDEPATH+=/usr/local/opt/mysql/include" "LIBS+=-L/usr/local/opt/mysql/lib -lmysqlclient" mysql.pro
      make
      make install

编译成功后,生成的 libqsqlmysql.so (Linux), qsqlmysql.dll (Windows),或 libqsqlmysql.dylib (macOS) 文件会被复制到 QT 的插件目录(如 Qt/5.15.2/gcc_64/plugins/sqldrivers)。确保你的程序运行时能找到这个插件。

编写代码

假设我们已经有一个名为 test_db 的数据库,其中有一张表 users

sql

CREATE TABLE users (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(100) NOT NULL,email VARCHAR(100) NOT NULL
);
步骤 1:项目配置 (.pro 文件)

在你的 QT 项目文件 (.pro) 中,添加 sql 模块。

pro

QT += core gui sql # 添加 sql 模块
步骤 2:C++ 代码实现

以下是完整的示例代码,包含连接数据库、插入、查询、更新和删除操作。

cpp

#include <QCoreApplication>
#include <QtSql> // 包含所有 SQL 相关的头文件
#include <QDebug>int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);// 1. 建立并打开数据库连接QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL"); // 指定数据库类型db.setHostName("localhost");      // 数据库服务器 IP,本地则为 localhostdb.setPort(3306);                // 端口号,默认 3306db.setDatabaseName("test_db");    // 要连接的数据库名db.setUserName("root");           // 数据库用户名db.setPassword("your_password"); // 数据库密码if (!db.open()) {qDebug() << "Failed to connect to database:" << db.lastError().text();return -1;} else {qDebug() << "Database connected successfully!";}// 2. 执行 SQL 语句 (使用 QSqlQuery)QSqlQuery query;// --- INSERT 示例 ---query.prepare("INSERT INTO users (name, email) VALUES (:name, :email)");query.bindValue(":name", "Alice");query.bindValue(":email", "alice@example.com");if (!query.exec()) {qDebug() << "Insert failed:" << query.lastError().text();} else {qDebug() << "Insert successful!";}// --- SELECT 示例 ---if (!query.exec("SELECT id, name, email FROM users")) {qDebug() << "Select failed:" << query.lastError().text();} else {qDebug() << "\nQuery results:";while (query.next()) { // 遍历结果集int id = query.value(0).toInt();        // 通过索引获取字段QString name = query.value("name").toString(); // 通过字段名获取QString email = query.value(2).toString();     // 通过索引获取字段qDebug() << "ID:" << id << "Name:" << name << "Email:" << email;}}// --- UPDATE 示例 ---query.prepare("UPDATE users SET email = ? WHERE name = ?");query.addBindValue("new_alice@example.com"); // 绑定第一个问号的值query.addBindValue("Alice");                // 绑定第二个问号的值if (!query.exec()) {qDebug() << "Update failed:" << query.lastError().text();}// --- DELETE 示例 ---query.prepare("DELETE FROM users WHERE name = :name");query.bindValue(":name", "Alice");if (!query.exec()) {qDebug() << "Delete failed:" << query.lastError().text();}// 3. 关闭数据库连接 (可选,程序结束时会自动关闭)db.close();return 0; // return a.exec(); 如果是 GUI 应用
}
代码详解
  • QSqlDatabase::addDatabase(“QMYSQL”): 创建一个 MySQL 类型的数据库连接。"QMYSQL" 是驱动的名称。

  • setHostName(), setDatabaseName(), ...: 设置连接数据库所需的参数。

  • db.open(): 尝试连接数据库。如果失败,可以通过 db.lastError() 获取错误信息。

  • QSqlQuery: 用于执行 SQL 语句的核心类。

  • query.prepare() + query.bindValue()推荐使用 的预处理语句方式。它可以防止 SQL 注入攻击,并且更高效。:name 是命名占位符,? 是位置占位符。

  • query.exec(): 执行 SQL 语句。对于 SELECT 语句,它会返回一个结果集。

  • query.next(): 遍历结果集中的每一条记录。初始时,指针位于第一条记录之前。

  • query.value(): 获取当前记录中某个字段的值。可以通过数字索引(从 0 开始)或字段名称的字符串来访问。

高级主题 - 模型/视图编程

QT 提供了更高级的 QSqlTableModel 和 QSqlQueryModel,可以将数据库中的数据直接与 QTableView 等视图组件绑定,实现数据的自动显示和编辑。

示例:使用 QSqlTableModel 在表格视图中显示数据

cpp

#include <QApplication>
#include <QTableView>
#include <QSqlTableModel>
#include <QSqlDatabase>
#include <QSqlError>int main(int argc, char *argv[]) {QApplication app(argc, argv);// ... (数据库连接代码,同上) ...// 创建模型并设置表QSqlTableModel *model = new QSqlTableModel;model->setTable("users");model->setEditStrategy(QSqlTableModel::OnManualSubmit); // 设置编辑策略model->select(); // 从数据库获取数据// 创建视图并设置模型QTableView *view = new QTableView;view->setModel(model);view->show();return app.exec();
}

常见错误与调试

  1. QSqlDatabase: QMYSQL driver not loaded

    • 原因:MySQL 驱动未正确安装或部署。

    • 解决:按照本指南第一部分的步骤编译驱动,并确保生成的驱动文件在程序的运行时可访问路径下(通常是程序所在目录的 sqldrivers 子文件夹,或者 QT 安装目录的 plugins/sqldrivers 文件夹)。

  2. Unknown database ‘test_db’

    • 原因:MySQL 中不存在该数据库。

    • 解决:先用 MySQL 客户端(如命令行或 Workbench)创建数据库。

  3. Access denied for user ‘root’@‘localhost’

    • 原因:用户名或密码错误,或者该用户没有从本地主机连接的权限。

    • 解决:检查登录凭据,或在 MySQL 中为用户授权。

  4. Can’t connect to MySQL server on ‘localhost’ (10061)

    • 原因:MySQL 服务没有启动。

    • 解决:去服务管理器中启动 MySQL 服务。

调试技巧

  • 始终检查 open() 和 exec() 的返回值

  • 使用 lastError().text() 来获取人类可读的错误信息。这是你最好的朋友!

二、MySQL 数据类型

核心关系对应表

MySQL 数据类型 推荐 / 对应的 C++ 类型 Qt 中常用的读取方法 (从 QSqlQuery 或 QSqlRecord) Qt 中常用的写入方法 (到 QSqlQuery 预处理语句) 注意事项
整数类型
TINYINT int / bool .toInt() / .toBool() :value 绑定 int / bool TINYINT(1) 通常被视为布尔值。
SMALLINT int .toInt() :value 绑定 int
MEDIUMINT int .toInt() :value 绑定 int
INT / INTEGER int .toInt() :value 绑定 int
BIGINT qint64 .toLongLong() :value 绑定 qint64 确保编译器支持 64 位整数。
浮点数类型
FLOAT float .toFloat() :value 绑定 float 可能存在精度问题。
DOUBLE / REAL double .toDouble() :value 绑定 double
DECIMAL(M, D) QString .toString() :value 绑定 QString 最佳实践:为避免浮点精度损失,金额等精确数值建议用 QString 读取。也可以用 .toDouble() 但需谨慎。
字符串类型
CHAR(N) QString .toString() :value 绑定 QString Qt 会自动处理编码转换(通常使用 UTF-8)。
VARCHAR(N) QString .toString() :value 绑定 QString
TINYTEXT QString .toString() :value 绑定 QString
TEXT QString .toString() :value 绑定 QString 对于非常大的文本,确保有足够的内存。
BLOB QByteArray .toByteArray() :value 绑定 QByteArray 用于存储二进制数据,如图片、文件等。
LONGTEXT QString .toString() :value 绑定 QString
LONGBLOB QByteArray .toByteArray() :value 绑定 QByteArray
日期时间类型
DATE QDate .toDate() :value 绑定 QDate MySQL 的日期格式与 QDate 兼容。
TIME QTime .toTime() :value 绑定 QTime
DATETIME QDateTime .toDateTime() :value 绑定 QDateTime 注意:MySQL 5.6.4+ 支持小数秒,但 QDateTime 不直接支持,读取时会被截断。
TIMESTAMP QDateTime .toDateTime() :value 绑定 QDateTime 存储的是 UTC 时间,读取时 Qt 会将其转换为本地时间。写入时,Qt 会将本地时间转换为 UTC 存储。行为需确认
其他类型
ENUM('val1', 'val2') QString .toString() :value 绑定 QString 读取其字符串值。
SET('val1', 'val2') QString .toString() :value 绑定 QString 读取逗号分隔的字符串集合。
BOOL / BOOLEAN bool .toBool() :value 绑定 bool 本质上是 TINYINT(1) 的别名。
JSON (MySQL 5.7.8+) QString .toString() :value 绑定 QString 在 Qt 中作为字符串处理,解析可使用 QJsonDocument

如何使用:代码示例

1. 读取数据 (SELECT)

cpp

QSqlQuery query;
query.exec("SELECT id, name, salary, birth_date FROM employees");while (query.next()) {// 通过字段索引读取 (从0开始)int id = query.value(0).toInt(); // 通过字段名读取 (更安全可靠)QString name = query.value("name").toString();double salary = query.value("salary").toDouble(); // 注意DECIMAL的精度问题QDate birthDate = query.value("birth_date").toDate();qDebug() << "ID:" << id << "Name:" << name << "Salary:" << salary << "Birth Date:" << birthDate.toString(Qt::ISODate);
}
2. 写入数据 (INSERT / UPDATE) - 使用预处理语句(推荐,可防SQL注入

cpp

QSqlQuery query;
// 使用命名占位符
query.prepare("INSERT INTO employees (name, salary, hire_date, avatar) ""VALUES (:name, :salary, :hire_date, :avatar)");// 将C++/Qt类型的值绑定到占位符
query.bindValue(":name", "John Doe");
query.bindValue(":salary", 75000.50);
query.bindValue(":hire_date", QDate::currentDate()); // 绑定QDate// 插入BLOB数据(例如图片)
QFile file("avatar.png");
if (file.open(QIODevice::ReadOnly)) {QByteArray imageData = file.readAll();query.bindValue(":avatar", imageData); // 绑定QByteArray
} else {query.bindValue(":avatar", QVariant(QVariant::ByteArray)); // 绑定空值
}// 执行查询
if (
http://www.dtcms.com/a/347266.html

相关文章:

  • git实战(8)git高阶命令分析【结合使用场景】
  • ADC系统中的信噪比(SNR)
  • 容器安全实践(二):实践篇 - 从 `Dockerfile` 到 Pod 的权限深耕
  • 多模态医学图像融合:解锁顶会顶刊中的医学影像新视界
  • 【GaussDB】使用MySQL客户端连接到GaussDB的M-Compatibility数据库
  • 智慧零售漏扫率↓79%!陌讯多模态融合算法在智能收银与货架管理的实战解析
  • 【Linux】深度学习Linux下的包管理器yum/apt
  • Day22: Python涡轮增压计划:用C扩展榨干最后一丝性能!
  • 微前端架构常见框架
  • 深度学习之PyTorch框架(安装,手写数字识别)
  • pid自适应调节实战设计-基于输出电流的PI参数切换方案
  • deepseek应用技巧-MCP服务操作网页和文档
  • ESP32应用——UDP组播/广播(ESP-IDF框架)
  • AI 辅助编程完全新手指南 - 从零基础到高效协作
  • Java试题-选择题(15)
  • flink常见问题之超出文件描述符限制
  • frp v0.64.0 更新:开源内网穿透工具,最简洁教程
  • 生成一个256 点 Q15 正弦表,deepseek载了
  • TK 直播网络串流 通过VLC本地播放
  • 合合信息acge模型获C-MTEB第一,文本向量化迎来新突破
  • 数据库服务语句应用
  • Vmware虚拟机 处理器配置选项配置介绍
  • 香橙派板子Orange Pi 5 Max开启 WiFi 热点
  • Java 线程相关的三个常见接口、类
  • pytorch与torchvision版本对应情况
  • SHAP分析+KOA-RIME开普勒结合霜冰算法双重优化BP神经网络+9种映射方法+新数据预测!机器学习可解释分析!
  • Excel 条件高亮工具,秒高亮显示符合筛选条件的行数据
  • 数据结构与算法-字符串、数组和广义表(String Array List)
  • pixijs基础学习
  • Huggingface入门实践 图像处理CV与多模态模型调用(二)