
用 mysql-connector-c++ 连接数据库前,先确认是否装对了库
很多人卡在第一步:编译通不过,报 mysqlx::Session 找不到、mysqlx::Schema 未声明,或链接时提示 undefined reference to mysqlx::get_session。这不是代码写错了,大概率是装了 libmysqlclient(C API)却误当成了 C++ connector,或者装了旧版(8.0.22 之前)但用了新版 API。
必须用官方 mysql-connector-c++(不是 mysql-client),且推荐 8.0.33+ 版本,它默认启用 X DevAPI(支持 mysqlx:: 命名空间),也兼容传统 SQL 模式。安装后检查关键头文件是否存在:
#include// 新版 X DevAPI // 或 #include #include // 旧版 JDBC 风格 API(已逐步弃用)
链接时加 -lmysqlcppconn(注意不是 -lmysqlclient),CMake 中要 find_package(mysqlcppconn REQUIRED)。
连接 MySQL 用 mysqlx::Session 还是 sql::Connection?
选 mysqlx::Session。它基于 X Protocol,支持 JSON 文档、集合操作、事务自动管理,API 更现代;而 sql::Connection 是仿 JDBC 的老接口,不支持 MySQL 8.0+ 的新特性(如角色、缓存 SHA2 登录),且文档维护停滞。
立即学习“C++免费学习笔记(深入)”;
连接字符串格式也不同:
-
mysqlx::Session:用mysqlx://user:password@host:port/database -
sql::Connection:用tcp://host:port+ 单独 setSchema(),且密码需通过sql::SQLString传
示例连接代码(带异常捕获):
try {
mysqlx::Session session("mysqlx://root:pass@127.0.0.1:33060/testdb");
std::cout << "Connected successfully\n";
} catch (const mysqlx::Error& e) {
std::cerr << "Connection failed: " << e.what() << " (" << e.getErrorCode() << ")\n";
}
执行 INSERT/UPDATE/DELETE 必须用 execute(),不能用 sql::Statement::executeUpdate()
在 mysqlx::Session 下,没有 executeUpdate() 这种方法。所有 DML 都走 session.sql("...").execute(),返回 mysqlx::SqlResult;查询才用 session.sql("SELECT ...").execute() 得到 mysqlx::RowResult。
常见错误写法:session.sql("INSERT ...").executeUpdate() → 编译失败,因为 mysqlx::SqlStatement 没这方法。
正确写法要点:
- INSERT 返回影响行数:
auto res = session.sql("INSERT INTO t1 VALUES (?, ?)").bind(123, "abc").execute(); res.getAffectedItemsCount(); - UPDATE/DELETE 同理,用
bind()防止 SQL 注入,参数位置从 1 开始(不是 0) - 事务控制:用
session.startTransaction()+session.commit()/session.rollback()
SELECT 查询结果取值时,别直接用 [] 索引访问 Row
mysqlx::Row 不支持 row[0] 这种语法。必须用 row[0].get、row[1].get<:string>() 显式指定类型,否则运行时报 std::bad_cast 或静默截断。
字段名访问更安全(尤其涉及 NULL):
auto result = session.sql("SELECT id, name FROM users WHERE id = ?").bind(42).execute();
if (auto row = result.fetchOne()) {
int id = row["id"].get(); // 推荐:按列名
std::string name = row["name"].get();
// 若 name 可能为 NULL,改用:row["name"].isNull() ? "" : row["name"].get()
}
注意:字段名大小写敏感,且必须和 SELECT 中写的完全一致(包括别名)。
最易被忽略的是连接池和生命周期管理:mysqlx::Session 对象不是线程安全的,不要跨线程复用;频繁创建销毁开销大,建议封装成连接池,或至少用 RAII 管理(例如放在局部作用域内,靠析构自动关闭)。另外,X Protocol 默认端口是 33060,不是传统 3306,连不上时先检查端口配置。











