在C++和Qt中操作MySQL,核心都是数据库连接 + SQL语句执行 。Qt中操作更简便,但关键在于驱动加载;C++中则需通过不同API手动管理连接与资源。
⚙️ 方案对比:原生 C++ vs. Qt C++
| 特性 | 原生 C++ (C API / Connector/C++) | Qt C++ (Qt SQL) |
|---|---|---|
| 核心库/模块 | <mysql.h> (C API) / <mysql_driver.h> (Connector/C++) [8†L12-L13] |
QtSql 模块 [1†L26] |
| 连接对象 | MYSQL* (C API) / sql::Connection* (Connector/C++) [7†L10] |
QSqlDatabase [9†L13] |
| SQL执行 | mysql_query + mysql_store_result (C API) / sql::Statement* (Connector/C++) [7†L15][8†L19] |
QSqlQuery [9†L12] |
| 结果处理 | mysql_fetch_row / sql::ResultSet* [8†L21] |
QSqlQuery::next() + value() [9†L18-L19] |
| 资源管理 | 需手动释放:mysql_free_result、mysql_close [7†L20-L21] |
QObject 父子机制,或使用智能指针管理 |
| 平台集成 | 需自行处理编译链接、头文件路径 [7†L6-L8] | .pro文件添加QT += sql,无缝集成到Qt项目 [1†L30] |
🔧 环境准备
使用C++/Qt操作MySQL前,需要确保开发环境准备就绪。
1. Qt 端:解决"QMYSQL driver not loaded"错误
- 根本原因:Qt默认不包含QMYSQL驱动,需要手动提供。
- 解决方法 :将MySQL客户端库
libmysql.dll(Windows) 或libmysqlclient.so(Linux) 复制 到Qt编译器的bin目录下。同时确保Qt、MySQL、编译器(MinGW/MSVC)的架构一致(如均为64位)。 - 注意 :Qt 5的SDK默认提供了驱动插件,位于
plugins/sqldrivers/,但可能仍需libmysql.dll才能正常工作。
2. C++ 端(通用):安装连接库
- 安装MySQL开发库 :这是C/C++连接MySQL的基础。
- Windows (MSVC):通常包含在MySQL安装包中。
- Linux (Debian/Ubuntu) :
sudo apt-get install libmysqlclient-dev - Linux (CentOS/RHEL) :
sudo yum install mysql-devel
- 连接器选项 :
- Connector/C++:官方C++库,支持面向对象接口,功能更完整。配置和编译稍显复杂,适合C++开发者。
- C API (
libmysqlclient):稳定通用,但接口是过程化的,相对底层。C++中也可用,但通常推荐Connector/C++。
🚀 连接与查询实践
📝 Qt C++ 示例
首先,在项目文件(.pro)中添加sql模块支持:
qmake
QT += core sql
然后,在代码中实现数据库操作:
cpp
#include <QCoreApplication>
#include <QtSql>
#include <QDebug>
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
// 1. 添加数据库驱动并创建连接
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
db.setHostName("localhost");
db.setPort(3306);
db.setDatabaseName("my_database");
db.setUserName("my_user");
db.setPassword("my_password");
// 2. 打开连接
if (!db.open()) {
qDebug() << "Connection failed:" << db.lastError().text();
return -1;
}
qDebug() << "Connected!";
// 3. 执行查询
QSqlQuery query;
if (!query.exec("SELECT id, name FROM users")) {
qDebug() << "Query failed:" << query.lastError().text();
return -1;
}
// 4. 处理结果
while (query.next()) {
int id = query.value(0).toInt();
QString name = query.value(1).toString();
qDebug() << "id:" << id << "name:" << name;
}
// 5. 关闭连接(可选,QSqlDatabase析构时会自动关闭)
db.close();
return 0;
}
📝 原生C++示例
根据项目需求和风格,可以选择不同的API实现。
方式一:使用C API (libmysqlclient)
cpp
#include <mysql/mysql.h>
#include <iostream>
int main() {
MYSQL *conn = mysql_init(nullptr); // 1. 初始化句柄
if (!conn) {
std::cerr << "mysql_init failed" << std::endl;
return -1;
}
// 2. 连接服务器
conn = mysql_real_connect(conn, "localhost", "my_user", "my_password", "my_database", 3306, nullptr, 0);
if (!conn) {
std::cerr << "Connect failed: " << mysql_error(conn) << std::endl;
return -1;
}
std::cout << "Connected!" << std::endl;
// 3. 执行查询
if (mysql_query(conn, "SELECT id, name FROM users")) {
std::cerr << "Query failed: " << mysql_error(conn) << std::endl;
return -1;
}
// 4. 获取并处理结果
MYSQL_RES *result = mysql_store_result(conn);
if (!result) {
std::cerr << "Store result failed" << std::endl;
return -1;
}
MYSQL_ROW row;
while ((row = mysql_fetch_row(result))) {
std::cout << "id: " << (row[0] ? row[0] : "NULL") << ", name: " << (row[1] ? row[1] : "NULL") << std::endl;
}
// 5. 释放结果并关闭连接
mysql_free_result(result);
mysql_close(conn);
return 0;
}
方式二:使用Connector/C++ (JDBC风格)
此API更符合C++开发者习惯,结构清晰,推荐用于新项目。
cpp
#include <mysql_driver.h>
#include <mysql_connection.h>
#include <cppconn/statement.h>
#include <cppconn/resultset.h>
#include <cppconn/exception.h>
#include <iostream>
#include <memory>
int main() {
try {
// 1. 获取驱动实例
sql::mysql::MySQL_Driver *driver = sql::mysql::get_mysql_driver_instance();
// 2. 创建连接(注意URL格式)
std::unique_ptr<sql::Connection> conn(driver->connect("tcp://127.0.0.1:3306", "my_user", "my_password"));
conn->setSchema("my_database");
std::cout << "Connected!" << std::endl;
// 3. 创建Statement并执行查询
std::unique_ptr<sql::Statement> stmt(conn->createStatement());
std::unique_ptr<sql::ResultSet> res(stmt->executeQuery("SELECT id, name FROM users"));
// 4. 处理结果集
while (res->next()) {
std::cout << "id: " << res->getInt("id") << ", name: " << res->getString("name") << std::endl;
}
} catch (sql::SQLException &e) {
std::cerr << "SQL Error: " << e.what() << " (SQLState: " << e.getSQLState() << ")" << std::endl;
return -1;
}
return 0;
}
编译时,记得链接libmysqlclient库:g++ your_program.cpp -o your_program -lmysqlclient。
🗄️ 常用SQL语法指南
无论使用哪种方式,核心都是SQL语句本身。常用语法可以分为三类:
1. 数据定义 (DDL):创建、修改、删除数据库中的结构
sql
CREATE DATABASE school; -- 创建数据库
USE school; -- 切换/使用数据库
CREATE TABLE students ( -- 创建表
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
age INT
);
ALTER TABLE students ADD COLUMN grade INT; -- 修改表
DROP TABLE students; -- 删除表
2. 数据操作 (DML):处理(插入、更新、删除)表中的实际数据
sql
INSERT INTO students (name, age) VALUES ('张三', 18); -- 插入单条
INSERT INTO students (name, age) VALUES ('李四', 19), ('王五', 20); -- 插入多条
UPDATE students SET age = 19 WHERE name = '张三'; -- 更新
DELETE FROM students WHERE id = 3; -- 删除指定
DELETE FROM students; -- 删除所有(危险,请谨慎)
3. 数据查询 (DQL):最常用的部分,用于从数据库中检索数据
sql
SELECT * FROM students; -- 查询所有列
SELECT name, age FROM students; -- 查询指定列
SELECT name, age FROM students WHERE age > 18; -- 条件查询
SELECT name, age FROM students ORDER BY age DESC; -- 排序
SELECT COUNT(*), AVG(age) FROM students WHERE age > 18; -- 聚合函数
SELECT name FROM students WHERE name LIKE '张%'; -- 模糊匹配
查询书写顺序与执行顺序 :SELECT -> FROM -> WHERE -> GROUP BY -> HAVING -> ORDER BY -> LIMIT。
🐞 常见问题与调试技巧
- 驱动未加载 :如上所述,通过复制
libmysql.dll并确保架构一致解决。 - 连接失败:检查服务、主机、端口、用户名/密码。
- 查询失败:SQL语法错误,表/库不存在,或用户权限不足。
- SQL注入与参数化查询 :避免直接拼接字符串,务必 使用参数化查询/占位符 。
- Qt :
query.prepare("INSERT INTO users (name) VALUES (:name)"); query.bindValue(":name", name); - Connector/C++ :
std::unique_ptr<sql::PreparedStatement> pstmt(conn->prepareStatement("SELECT * FROM users WHERE name = ?")); pstmt->setString(1, name);
- Qt :
本文档由AI生成