首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C 語言 MySQL 開發實戰筆記:編譯配置、常見錯誤與最佳實踐

     編輯:關於C語言

前言

C 語言操作 MySQL 是後端儲存、嵌入式設備、高效能服務的常見選擇。本文匯總實戰中遇到的編譯鏈接配置、API 陷阱、錯誤碼分析與最佳實踐,作為快速查閱手冊。

一、編譯鏈接配置

Makefile 模板


INCLUDE = /usr/include/mysql
LIBS    = /usr/lib/mysql

all:
	gcc -I$(INCLUDE) -L$(LIBS) -lmysqlclient xxx.c -o xxx

clean:
	rm -f xxx

不同安裝路徑對應

安裝方式INCLUDELIBS
系統預設/usr/include/mysql/usr/lib/mysql
原始碼安裝 /usr/local/mysql/usr/local/mysql/include/mysql/usr/local/mysql/lib/mysql

動態庫載入失敗解決

錯誤:libmysqlclient.so.16: cannot open shared object file


ln -s /usr/local/mysql/lib/mysql/libmysqlclient.so.16 /usr/lib/libmysqlclient.so.16
# 或永久生效
echo "/usr/local/mysql/lib/mysql" >> /etc/ld.so.conf.d/mysql.conf
ldconfig

二、常見 API 錯誤與解決

1. "Unknown column 'xxx' in 'where clause'"

  • **原因**:SQL 語句欄位名拼寫錯誤、未加反引號導致保留字衝突、或表結構不一致。
  • **排查**:直接在 MySQL Client 執行該 SQL 驗證。

2. "Commands out of sync; you can't run this command now"

典型錯誤碼:呼叫順序錯誤。


// 錯誤示範
mysql_real_query(mysql, sql, strlen(sql));
num = mysql_affected_rows(mysql); // 未先取結果集

// 正確流程(查詢類)
mysql_real_query(mysql, sql, strlen(sql));
MYSQL_RES *res = mysql_store_result(mysql); // 或 mysql_use_result
num = mysql_num_rows(res);
// ... 處理資料 ...
mysql_free_result(res);

原則:mysql_real_query 後,**必須**呼叫 mysql_store_result/mysql_use_result 取得結果集指標,才能進一步操作。

3. 執行期 "浮點數例外"

  • **原因**:除零運算(整數或浮點數)。
  • **防禦**:除法前檢查除數 != 0。

三、核心操作範例

1. 插入查詢結果到另一張表


INSERT INTO new_table (col1, col2, col3)
SELECT col1, col2, col3 FROM old_table WHERE condition;

2. 完整查詢與取值流程


MYSQL *mysql;
MYSQL_RES *res;
MYSQL_ROW row;

char *sql = "SELECT uid, uname FROM users WHERE uid=123";

mysql_real_connect(mysql, "host", "user", "pass", "db", 3306, NULL, 0);
mysql_real_query(mysql, sql, strlen(sql));
res = mysql_store_result(mysql);
row = mysql_fetch_row(res);

if (row) {
    long uid = atol(row[0]);
    char *uname = row[1] ? strdup(row[1]) : "";
    // 使用 uid, uname
}
mysql_free_result(res);
mysql_close(mysql);

3. 參數化查詢(防注入)


MYSQL_STMT *stmt = mysql_stmt_init(mysql);
const char *sql = "SELECT * FROM users WHERE uid=? AND status=?";
mysql_stmt_prepare(stmt, sql, strlen(sql));

MYSQL_BIND bind[2];
long uid = 123; int status = 1;
memset(bind, 0, sizeof(bind));
bind[0].buffer_type = MYSQL_TYPE_LONG; bind[0].buffer = &uid;
bind[1].buffer_type = MYSQL_TYPE_LONG; bind[1].buffer = &status;
mysql_stmt_bind_param(stmt, bind);
mysql_stmt_execute(stmt);
// ... bind_result + fetch ...
mysql_stmt_close(stmt);

四、最佳實踐清單

  1. 連線池化: 高併發場景使用連線池(如 libmysqlclient 內建或第三方)。
  2. 錯誤處理: 每個 API 呼叫檢查回傳值,mysql_error(mysql) 記錄日誌。
  3. 資源釋放: mysql_free_result、mysql_stmt_close、mysql_close 必配對,防洩漏。
  4. 字符集: 連線後執行 SET NAMES utf8mb4,確保 Emoji/多語言支援。
  5. 事務控制: autocommit=0,COMMIT/ROLLBACK 顯式管理。
  6. 預處理語句: 所有動態參數查詢**強制**使用 MYSQL_STMT,杜絕拼接 SQL 注入風險。

五、除錯技巧

  • 開啟 MySQL 一般查詢日誌:SET GLOBAL general_log=1;
  • 使用 mysql_options(mysql, MYSQL_REPORT_DATA_TRUNCATION, ...) 捕獲截斷警告。
  • Valgrind/ASan 檢測記憶體洩漏(特別是 mysql_store_result 未釋放)。

總結

C 操作 MySQL 核心在於**正確的編譯鏈接**、**嚴格遵循 API 呼叫順序**、**參數化查詢防注入**、**完善的錯誤與資源管理**。掌握上述要點,即可構建穩健高效的資料存取層。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved