項目從 SQL Server 遷移至 MySQL,原使用 ADO 連接。MySQL 官方提供兩種 C++ 介面:
為快速搭建原型,團隊選擇直接封裝 C API,輕量、可控、無第三方依賴,暫不實現連接池與事務管理。
MYSQL:連接句柄,必須先 mysql_init() 初始化。MYSQL_RES:結果集指針,mysql_store_result() / mysql_use_result() 獲取。MYSQL_ROW:行數據指針數組,mysql_fetch_row() 迭代。MYSQL_FIELD:列元數據(名稱、類型、長度等)。#ifndef __MYSQL_INTERFACE_H__ #define __MYSQL_INTERFACE_H__ #include#include #include #include #include #pragma comment(lib, "ws2_32.lib") #pragma comment(lib, "libmysql.lib") using namespace std; class MySQLInterface { public: MySQLInterface(); virtual ~MySQLInterface(); // 連接管理 bool connectMySQL(const char* server, const char* user, const char* pass, const char* db, int port); void closeMySQL(); // 庫/表操作 bool createDatabase(string& dbname); bool createTable(const string& ddl_sql); // 數據操作 bool executeUpdate(const string& sql); // INSERT/UPDATE/DELETE/DDL bool executeQuery(const string& sql, // SELECT vector >& data); // 返回二維字串表 // 錯誤信息 int getErrorNo() const { return errorNum; } const char* getErrorMsg() const { return errorInfo; } private: void handleError(); MYSQL mysqlInstance_; // 連接對象 MYSQL_RES* result_ = nullptr; // 結果集 int errorNum = 0; const char* errorInfo = "ok"; }; #endif
MySQLInterface::MySQLInterface() {
mysql_library_init(0, NULL, NULL);
mysql_init(&mysqlInstance_);
mysql_options(&mysqlInstance_, MYSQL_SET_CHARSET_NAME, "utf8mb4"); // 或 gbk
}
bool MySQLInterface::connectMySQL(const char* server, const char* user,
const char* pass, const char* db, int port) {
if (mysql_real_connect(&mysqlInstance_, server, user, pass, db, port, NULL, 0))
return true;
handleError();
return false;
}
bool MySQLInterface::createDatabase(string& dbname) {
string sql = "CREATE DATABASE IF NOT EXISTS " + dbname;
if (mysql_query(&mysqlInstance_, sql.c_str())) { handleError(); return false; }
sql = "USE " + dbname;
if (mysql_query(&mysqlInstance_, sql.c_str())) { handleError(); return false; }
return true;
}
bool MySQLInterface::executeUpdate(const string& sql) {
if (mysql_query(&mysqlInstance_, sql.c_str()) == 0)
return true;
handleError();
return false;
}
bool MySQLInterface::executeQuery(const string& sql,
vector>& data) {
if (mysql_query(&mysqlInstance_, sql.c_str())) {
handleError();
return false;
}
result_ = mysql_store_result(&mysqlInstance_);
if (!result_) { handleError(); return false; }
int fields = mysql_num_fields(result_);
MYSQL_ROW row;
while ((row = mysql_fetch_row(result_))) {
vector record;
record.reserve(fields);
for (int i = 0; i < fields; ++i) {
record.emplace_back(row[i] ? row[i] : "");
}
data.emplace_back(std::move(record));
}
mysql_free_result(result_);
result_ = nullptr;
return true;
}
void MySQLInterface::handleError() {
errorNum = mysql_errno(&mysqlInstance_);
errorInfo = mysql_error(&mysqlInstance_);
}
void MySQLInterface::closeMySQL() {
if (result_) { mysql_free_result(result_); result_ = nullptr; }
mysql_close(&mysqlInstance_);
mysql_library_end();
}
int main() {
MySQLInterface db;
if (!db.connectMySQL("127.0.0.1", "root", "password", "test_db", 3306)) {
cerr << "Connect failed: " << db.getErrorMsg() << endl;
return 1;
}
// 建表
db.executeUpdate("CREATE TABLE IF NOT EXISTS t_user("
"id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,"
"name VARCHAR(50) NOT NULL,"
"age TINYINT UNSIGNED NOT NULL DEFAULT 0)");
// 寫入
db.executeUpdate("INSERT INTO t_user(name,age) VALUES('Alice',25),('Bob',30)");
// 查詢
vector> rows;
if (db.executeQuery("SELECT id,name,age FROM t_user", rows)) {
for (auto& r : rows) {
cout << "ID:" << r[0] << " Name:" << r[1] << " Age:" << r[2] << endl;
}
}
db.closeMySQL();
return 0;
}
std::queue<MYSQL*> + std::mutex + std::condition_variable 實現線程安全池。BEGIN/COMMIT/ROLLBACK,提供 RAII 風格 TransactionGuard。MYSQL_STMT、MYSQL_BIND 防注入、提升重複執行效能。mysql_real_connect_nonblocking、mysql_send_query 實現高併發。