必须同时满足三点:安装libmysqlclient或mysqlclient.lib+libmysql.dll、下载并链接mysqlcppconn(8.0+)、编译时按目标文件→mysqlcppconn→mysqlclient顺序链接;所有操作需用try/catch捕获SQLException。

用 MySQL Connector/C++ 连接前先确认环境是否配齐
直接连不上基本是环境没对齐,不是代码写错。C++ 连 MySQL 不像 Python 那样 pip 一下就完事,它依赖原生 C 库和 C++ 封装层,缺一不可。
必须同时满足这三点:
- 已安装 libmysqlclient(Linux/macOS)或 mysqlclient.lib + libmysql.dll(Windows)
- 已下载并正确链接 mysqlcppconn(即 MySQL Connector/C++ 8.0+ 的库,注意不是旧版 1.1.x)
- 编译时链接顺序不能错:你的目标文件 → mysqlcppconn → mysqlclient(Linux/macOS)或 mysqlcppconn-static(Windows 静态链接更稳)
常见报错 undefined reference to 'sql::mysql::MySQL_Driver::get_driver_instance()' 就是链接了错误版本的库,或者漏了 -lmysqlcppconn。
初始化连接时别跳过 SQL 异常捕获
Connector/C++ 所有操作都抛异常,不检查 try/catch 就等于裸奔。哪怕只是测试连通性,也得包住 sql::mysql::MySQL_Driver::get_driver_instance() 和 driver->connect()。
典型写法:
立即学习“C++免费学习笔记(深入)”;
try {
sql::mysql::MySQL_Driver *driver = sql::mysql::MySQL_Driver::get_driver_instance();
std::unique_ptr<sql::Connection> conn(driver->connect("tcp://127.0.0.1:3306", "user", "pass"));
conn->setSchema("testdb");
} catch (sql::SQLException &e) {
std::cerr << "SQL Error: " << e.what() << " (MySQL error code: " << e.getErrorCode()
<< ", SQLState: " << e.getSQLState() << ")" << std::endl;
}注意:connect() 的第一个参数是 URL 格式,不是纯 host;setSchema() 必须显式调用,不会自动选库;sql::SQLException 是唯一要 catch 的类型,别用 std::exception 模糊兜底。
预处理语句(PreparedStatement)不是可选项,是必选项
拼接 SQL 字符串(比如 "INSERT INTO t VALUES ('" + name + "')" )在 C++ 里既危险又低效。Connector/C++ 的 PreparedStatement 不仅防注入,还减少服务端解析开销。
关键点:
- 占位符用 ?,不是 :name 或 $1
- 设置参数必须用对应类型的 setXXX() 方法,比如 stmt->setString(1, "alice"),不能传 const char* 给 setString()
- executeUpdate() 返回影响行数,executeQuery() 返回 ResultSet*,别混淆
漏掉 setXXX() 类型匹配会触发运行时异常,且错误信息不直观,比如传 int 给 setString() 会崩在内部类型转换上。
连接生命周期管理容易被忽略的坑
Connector/C++ 的对象不是 RAII 友好型。比如 ResultSet 必须在关联的 PreparedStatement 或 Statement 销毁前读完或显式 close(),否则下一次查询可能失败或返回脏数据。
几个硬性规则:
- Connection 对象析构会自动断开,但不保证事务已提交(需手动 commit() 或 rollback())
- PreparedStatement 析构会释放服务端预处理资源,但若之前执行过 executeQuery(),其 ResultSet 必须先 close()
- 多线程共用一个 Connection 是未定义行为,每个线程该有自己的 Connection 实例
最隐蔽的问题:在函数里局部创建 Connection,然后返回一个从它派生的 PreparedStatement —— 连接对象一出作用域就销毁,后续执行必然崩溃。


















