需链接 libmysqlcppconn(非 libmysqlclient),头文件仅需 #include 和 ;Ubuntu 安装 libmysqlcppconn-dev,编译加 -lmysqlcppconn,运行时确保 libmysqlcppconn.so.x 在 LD_LIBRARY_PATH 中。
必须链接 mysqlcppconn(即 MySQL Connector/C++ 8.0+ 的库),不是旧版 libmysqlclient。头文件只需包含 #include 和 #include ,其他如 sql::Statement、sql::ResultSet 等类型都从这里导出。
常见错误是混用 Connector/C++ 1.1(已废弃)和 8.0+:前者用 mysql_driver.h,后者用 mysql_connection.h;链接时若写错库名(比如写成 -lmysqlclient),会报 undefined reference to 'sql::mysql::MySQL_Driver::get_mysql_driver_instance()'。
sudo apt install libmysqlcppconn-dev
-lmysqlcppconn,不是 -lmysqlclient
libmysqlcppconn.so.7(或对应版本)在 LD_LIBRARY_PATH 中连接不能只靠 sql::mysql::MySQL_Driver::get_mysql_driver_instance() 就完事。必须显式设置连接属性,尤其是 OPT_SET_CHARSET_NAME 和 SSL_MODE,否则中文乱码或远程连接被拒很常见。
认证失败时,driver->connect() 不抛异常而是返回空指针(C++ 8.0.29+ 默认行为),直接解引用会 crash。必须检查返回值。
sql::SQLString url("tcp://127.0.0.1:3306");
sql::Properties props;
props["user"] = "root";
props["password"] = "123456";
props["OPT_SET_CHARSET_NAME"] = "utf8mb4";
props["SS
L_MODE"] = "disabled"; // 本地开发可关,生产环境建议 enabled
std::unique_ptr conn(driver->connect(url, props));
if (!conn) {
throw std::runtime_error("Connection failed");
} @、/)需 URL 编码,否则解析失败caching_sha2_password,Connector/C++ 8.0.23+ 才原生支持;旧版需在 MySQL 中执行:ALTER USER 'user'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd';
sql::Statement 拼 SQL 字符串极易引发 SQL 注入,且无法复用执行计划。而 sql::PreparedStatement 支持占位符 ?,自动转义参数,性能也更好。
注意:MySQL Connector/C++ 中 executeUpdate() 对 INSERT/UPDATE/DELETE 返回影响行数(int64_t),但 executeQuery() 才返回 sql::ResultSet;误用会导致编译失败或运行时异常。
auto pstmt = conn->prepareStatement("INSERT INTO users(name, age) VALUES (?, ?)");
pstmt->setString(1, "张三");
pstmt->setInt(2, 25);
int64_t rows = pstmt->executeUpdate(); // 返回 1rs->next() 才能读数据,否则 rs->getString(1) 会抛 sql::InvalidArgumentException
prepareStatement,应复用 pstmt 对象字段索引从 1 开始(不是 0),且 getString() 等方法对 NULL 值返回空字符串而非 nullptr —— 无法靠判空判断是否为 NULL。必须先调 wasNull()。
另外,ResultSet 生命周期绑定到 PreparedStatement,一旦 pstmt 被销毁或执行新查询,旧 rs 自动失效。不能缓存 rs 指针跨作用域使用。
if (rs->next()) {
std::string name = rs->getString(1);
if (rs->wasNull()) {
// 字段实际是 NULL
}
}TEXT)用 getString() 没问题,但二进制字段(BLOB)必须用 getBytes(),否则乱码conn 和 rs->next() 返回值 —— 这些地方不加防护,程序跑一两天就 core dump。