MySQL 提供官方 C API(libmysqlclient),讓 C/C++ 程式能直接連線、查詢、管理資料庫。本文整理核心資料結構、常用函數表,並提供完整可編譯的範例程式。
| 結構體 | 用途 | 關鍵說明 |
|---|---|---|
MYSQL | 連線控制代碼 | 幾乎所有 API 函數的第一個參數,需先呼叫 mysql_init() 初始化 |
MYSQL_RES | 結果集 | 儲存 SELECT、SHOW 等查詢回傳的完整結果,需呼叫 mysql_free_result() 釋放 |
MYSQL_ROW | 單列資料 | 型別為 char **,由 mysql_fetch_row() 逐列取得,**非以 null 結尾**,含二進位資料時不可當字串處理 |
MYSQL_FIELD | 欄位中繼資料 | 包含欄位名、型別、長度等,透過 mysql_fetch_field() 取得 |
| 函數 | 功能 |
|---|---|
mysql_init() | 初始化/取得 MYSQL 結構 |
mysql_real_connect() | 建立真實連線(取代舊版 mysql_connect()) |
mysql_real_query() | 執行 SQL(支援二進位資料,需傳長度) |
mysql_store_result() | 將完整結果集讀入客戶端記憶體 |
mysql_use_result() | 啟動逐列串流讀取(省記憶體,但鎖表久) |
mysql_fetch_row() | 取得下一列資料(傳回 MYSQL_ROW) |
mysql_num_fields() / mysql_num_rows() | 取得欄位數/列數 |
mysql_free_result() | 釋放結果集記憶體 |
mysql_close() | 關閉連線 |
mysql_errno() / mysql_error() | 取得最後一次錯誤碼/訊息 |
mysql_affected_rows() | 取得 INSERT/UPDATE/DELETE 影響列數 |
mysql_insert_id() | 取得 AUTO_INCREMENT 生成的 ID |
mysql_options() | 設定連線選項(字元集、超時、SSL 等) |
mysql_ping() | 檢查連線存活,必要時自動重連 |
mysql_autocommit() / mysql_commit() / mysql_rollback() | 事務控制 |
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mysql.h>
int main() {
MYSQL mysql;
MYSQL_RES *res;
MYSQL_ROW row;
char *query = "SELECT id, name, age FROM students";
mysql_init(&mysql);
// 連線參數:host, user, passwd, db, port, unix_socket, client_flag
if (!mysql_real_connect(&mysql, "localhost", "root", "password", "testdb", 0, NULL, 0)) {
fprintf(stderr, "連線失敗: %s\n", mysql_error(&mysql));
return EXIT_FAILURE;
}
printf("連線成功\n");
if (mysql_real_query(&mysql, query, (unsigned long)strlen(query))) {
fprintf(stderr, "查詢失敗: %s\n", mysql_error(&mysql));
mysql_close(&mysql);
return EXIT_FAILURE;
}
res = mysql_store_result(&mysql);
if (!res) {
fprintf(stderr, "取得結果集失敗: %s\n", mysql_error(&mysql));
mysql_close(&mysql);
return EXIT_FAILURE;
}
// 列印欄位名
unsigned int num_fields = mysql_num_fields(res);
MYSQL_FIELD *fields = mysql_fetch_fields(res);
for (unsigned int i = 0; i < num_fields; i++) {
printf("%s\t", fields[i].name);
}
printf("\n");
// 逐列列印
while ((row = mysql_fetch_row(res))) {
for (unsigned int i = 0; i < num_fields; i++) {
printf("%s\t", row[i] ? row[i] : "NULL");
}
printf("\n");
}
mysql_free_result(res);
mysql_close(&mysql);
return EXIT_SUCCESS;
}
# 取得編譯旗標與連結庫 mysql_config --cflags --libs # 輸出範例:-I/usr/include/mysql -L/usr/lib64/mysql -lmysqlclient gcc -o mysql_demo mysql_demo.c $(mysql_config --cflags --libs)
mysql_store_result() 必須配對 mysql_free_result()。NULL byte 的欄位(如 BLOB)不可用 strlen(),需搭配 mysql_fetch_lengths() 取得真實長度。SET NAMES utf8mb4 或呼叫 mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, "utf8mb4")。mysql_stmt_prepare() 系列 API,防止 SQL Injection 並提升效能。