在高效能、高安全性場景下,C 語言直接呼叫 MySQL C API (libmysqlclient) 是最佳選擇。本文系統介紹核心結構體、高頻函數原型、完整可編譯執行的查詢範例、GCC 編譯鏈結參數,助你快速上手 C/C++ 開發 MySQL 應用。
typedef struct st_mysql {
NET net; // 通訊參數
char *host, *user, *passwd, *unix_socket, *db;
unsigned int port, client_flag, server_capabilities, protocol_version;
unsigned int field_count;
unsigned long thread_id; // 連線 ID
my_ulonglong affected_rows; // 影響行數
my_ulonglong insert_id; // 自增 ID
MYSQL_FIELD *fields; // 結果集欄位資訊
struct st_mysql_options options;
// ... 省略其他欄位
} MYSQL;
用途:mysql_init() 初始化、mysql_real_connect() 建立連線、後續所有操作的句柄。
typedef struct st_mysql_res {
my_ulonglong row_count; // 總行數
unsigned int field_count; // 欄位數
MYSQL_FIELD *fields; // 欄位定義陣列
MYSQL_DATA *data; // 資料緩衝
MYSQL_ROWS *data_cursor; // 當前行游標
MYSQL_ROW row; // 當前行資料(字串陣列)
unsigned long *lengths; // 各欄位長度
MYSQL *handle; // 關聯連線
my_bool eof; // 是否讀完
} MYSQL_RES;
用途:mysql_store_result() / mysql_use_result() 取得、mysql_fetch_row() 逐行讀取、mysql_free_result() 釋放。
| 函數 | 功能 | 關鍵參數 / 返回值 |
|---|---|---|
| mysql_init(MYSQL *mysql) | 初始化/分配 MYSQL 結構 | 返回初始化後指針,失敗返回 NULL |
| mysql_real_connect(MYSQL*, host, user, passwd, db, port, unix_socket, client_flag) | 真正建立 TCP/Unix Socket 連線 | 成功返回 MYSQL*,失敗返回 NULL;client_flag 常用 CLIENT_MULTI_STATEMENTS 支援多語句/存儲過程 |
| mysql_close(MYSQL *mysql) | 關閉連線並釋放記憶體 | 無返回值 |
| mysql_query(MYSQL *mysql, const char *sql) | 執行 SQL(不含二進位資料) | 成功返回 0,失敗非 0 |
| mysql_real_query(MYSQL*, const char*, unsigned long) | 執行含二進位資料的 SQL | 同上 |
| mysql_store_result(MYSQL *mysql) | 取得完整結果集至客戶端緩衝 | 返回 MYSQL_RES*,失敗 NULL |
| mysql_use_result(MYSQL *mysql) | 無緩衝逐行讀取(串流) | 返回 MYSQL_RES*,需手動 fetch 完畢才能發下一條 SQL |
| mysql_fetch_row(MYSQL_RES *res) | 取得下一行(字串陣列 MYSQL_ROW) | 無更多行返回 NULL |
| mysql_num_fields(MYSQL_RES *res) | 取得欄位數 | 返回 unsigned int |
| mysql_affected_rows(MYSQL *mysql) | 最近 INSERT/UPDATE/DELETE 影響行數 | 返回 my_ulonglong;-1 表錯誤 |
| mysql_insert_id(MYSQL *mysql) | 最近 AUTO_INCREMENT 生成的 ID | 返回 my_ulonglong |
| mysql_error(MYSQL *mysql) | 取得最近錯誤訊息字串 | 返回 const char* |
| mysql_select_db(MYSQL*, const char *db) | 切換預設資料庫 | 成功 0,失敗非 0 |
| mysql_create_db / mysql_drop_db | 建立/刪除資料庫(舊 API,建議用 SQL) |
場景:連線本地 9tmd_bbs_utf8 資料庫,查詢 tbb_user 表指定 userid 的 username。
#if defined(_WIN32) || defined(_WIN64) #include#endif #include #include #include "mysql.h" #define SELECT_QUERY "SELECT username FROM tbb_user WHERE userid = %d" int main(int argc, char **argv) { MYSQL mysql, *sock; MYSQL_RES *res; MYSQL_ROW row; char qbuf[160]; if (argc != 2) { fprintf(stderr, "usage: %s \n", argv[0]); exit(1); } mysql_init(&mysql); // 關鍵:CLIENT_MULTI_STATEMENTS 支援 CALL 存儲過程/多語句 if (!(sock = mysql_real_connect(&mysql, "localhost", "dbuser", "dbpwd", "9tmd_bbs_utf8", 0, NULL, CLIENT_MULTI_STATEMENTS))) { fprintf(stderr, "Connect failed: %s\n", mysql_error(&mysql)); exit(1); } sprintf(qbuf, SELECT_QUERY, atoi(argv[1])); if (mysql_query(sock, qbuf)) { fprintf(stderr, "Query failed: %s\n", mysql_error(sock)); exit(1); } if (!(res = mysql_store_result(sock))) { fprintf(stderr, "Store result failed: %s\n", mysql_error(sock)); exit(1); } printf("Fields returned: %d\n", mysql_num_fields(res)); while ((row = mysql_fetch_row(res))) { printf("User #%s name: %s\n", argv[1], (row[0] && strlen(row[0])) ? row[0] : "NULL"); puts("Query OK"); } mysql_free_result(res); mysql_close(sock); return 0; }
gcc -o mysql_select mysql_select.c \ -I/usr/local/include/mysql \ -L/usr/local/lib/mysql \ -lmysqlclient -lz -lm
-I:指定 mysql.h 頭檔目錄-L:指定 libmysqlclient.so 庫目錄-lmysqlclient:鏈結 MySQL 客戶端庫-lz -lm:部分系統需額外鏈結 zlib 與數學庫$ ./mysql_select 1 Fields returned: 1 User #1 name: Michael Query OK
mysql_stmt_prepare()、mysql_stmt_bind_param()、mysql_stmt_execute() 防 SQL 注入、提升重複執行效能。mysql_error()。mysql_set_character_set(sock, "utf8mb4") 或在 mysql_real_connect 前設 mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, "utf8mb4")。libmysqlclient 無內建池,可參考 libdrizzle 或自行實現)。掌握 C API 核心流程 init → real_connect → query → store_result → fetch_row → free_result → close,即可在嵌入式、高頻交易、系統級服務中發揮 MySQL 最大效能。