在 Linux 環境下使用 C 語言開發 MySQL 客戶端應用,核心在於掌握 libmysqlclient C API 的標準化流程:初始化 → 連線 → 執行 SQL → 處理結果集 → 清理資源。本文系統梳理關鍵 API、編譯鏈接參數、錯誤處理模式與完整可編譯範例。
| 步驟 | 函數 | 關鍵參數與返回值 | 錯誤處理 |
|---|---|---|---|
| 1. 初始化 | MYSQL *mysql_init(MYSQL *mysql) | 傳 NULL 自動分配結構體;返回初始化指針或 NULL | 檢查返回值 ≠ NULL |
| 2. 建立連線 | MYSQL *mysql_real_connect(MYSQL*, host, user, passwd, db, port, unix_socket, client_flag) | host=NULL 即 localhost;port=0 用預設 3306;unix_socket=NULL 用預設 socket;返回連線指針或 NULL | mysql_error(mysql) 獲取錯誤字串 |
| 3. 執行 SQL | int mysql_query(MYSQL*, const char *stmt) | SQL 字串需以 '\0' 結尾;成功返回 0,失敗非 0 | mysql_errno()/mysql_error() |
| 4. 獲取結果集 | MYSQL_RES *mysql_store_result(MYSQL*) | SELECT/SHOW/DESC/EXPLAIN 等需調用;返回結果集指針或 NULL (無結果/錯誤) | 務必配對 mysql_free_result() |
| 5. 逐行讀取 | MYSQL_ROW mysql_fetch_row(MYSQL_RES*) | 返回下一行指針 (字串陣列) 或 NULL (結束/錯誤);欄位數 mysql_num_fields(res) | 檢查 NULL 區分結束與錯誤 |
| 6. 釋放資源 | mysql_free_result(res) / mysql_close(mysql) | 釋放結果集 / 關閉連線並釋放結構體 | 所有路徑必須釋放,防洩漏 |
gcc -o mysql_app mysql_app.c $(mysql_config --cflags --libs)
# 等價展開:
# -I/usr/include/mysql -L/usr/lib/mysql -lmysqlclient -lz -lcrypt -lpthread -lm -lssl -lcrypto
mysql_config 選項:
--cflags 編譯標頭路徑與宏
--libs 鏈接庫路徑與庫列表
--libs_r 執行緒安全版庫
gcc -o mysql_app mysql_app.c \
-I/usr/include/mysql \
-L/usr/lib/mysql \
-lmysqlclient -lz -lm -lpthread
⚠️ 庫順序敏感:-lmysqlclient 必須在 -lz -lm ... 之前。
#include
#include
#include
#include
#define DB_HOST "localhost"
#define DB_USER "app_user"
#define DB_PASS "StrongP@ss"
#define DB_NAME "mydb"
void check_error(MYSQL *conn, const char *stage) {
if (mysql_errno(conn)) {
fprintf(stderr, "[%s] Error %d: %s\n", stage, mysql_errno(conn), mysql_error(conn));
mysql_close(conn);
exit(EXIT_FAILURE);
}
}
int main() {
MYSQL *conn = mysql_init(NULL);
if (!conn) { fprintf(stderr, "mysql_init failed\n"); return 1; }
// 連線
if (!mysql_real_connect(conn, DB_HOST, DB_USER, DB_PASS, DB_NAME, 0, NULL, 0)) {
check_error(conn, "connect");
}
printf("Connected to MySQL %s\n", mysql_get_server_info(conn));
// 設定字元集
if (mysql_set_character_set(conn, "utf8mb4")) {
check_error(conn, "charset");
}
// 執行查詢
const char *sql = "SELECT id, username, email FROM users WHERE status=1 LIMIT 10";
if (mysql_query(conn, sql)) check_error(conn, "query");
// 處理結果集
MYSQL_RES *res = mysql_store_result(conn);
if (!res) check_error(conn, "store_result");
unsigned int num_fields = mysql_num_fields(res);
MYSQL_FIELD *fields = mysql_fetch_fields(res);
for (unsigned int i=0; i
mysql_stmt_prepare/bind_param/execute 防 SQL 注入、提升重複執行效能。libmysqlclient 非阻塞模式或第三方連線池 (如 mysql-connector-c++ 內建池)。mysql_real_connect_nonblocking + poll/epoll 整合事件循環。mysql_ssl_set() 配置 CA/Client Cert/Key,mysql_options(MYSQL_OPT_SSL_MODE, SSL_MODE_REQUIRED)。CR_SERVER_GONE_ERROR (連線斷開) 觸發自動重連邏輯;ER_LOCK_DEADLOCK 觸發重試退避。若需支援多種資料庫 (PostgreSQL/SQL Server/Oracle),建議使用 unixODBC + MySQL ODBC Connector,應用層面向標準 ODBC API (SQLConnect/SQLExecDirect/SQLFetch),僅更換 DSN 配置即可遷移。
掌握 C API 標準流程與資源管理鐵律,構建健壯高效的 MySQL 應用不再是難題。