核心 API 概覽
| 函數 | 用途 |
mysql_query() | 執行 SQL 語句(不含結束分號) |
mysql_real_query() | 處理含二進制數據的查詢 |
mysql_affected_rows() | 獲取 INSERT/UPDATE/DELETE 影響行數 |
mysql_store_result() | 一次性取回所有結果集(客戶端緩存) |
mysql_use_result() | 逐行讀取結果集(服務端緩存,適合大數據) |
mysql_fetch_row() | 從結果集獲取下一行 |
mysql_free_result() | 釋放結果集內存 |
不返回數據的語句(INSERT/UPDATE/DELETE)
關鍵點:mysql_affected_rows() 行為差異
- INSERT:返回實際插入行數(通常為 1)
- UPDATE:默認只返回真正被修改的行數;若需返回匹配行數,連接時需加
CLIENT_FOUND_ROWS 標志
- DELETE:帶
WHERE 時返回刪除行數;無 WHERE 刪全表時返回 0(優化機制,不受 CLIENT_FOUND_ROWS 影響)
代碼範例:批量插入與錯誤處理
MYSQL conn;
mysql_init(&conn);
if (mysql_real_connect(&conn, "localhost", "user", "pass", "db", 0, NULL, 0)) {
int res = mysql_query(&conn, "INSERT INTO t(name) VALUES('test')");
if (!res) {
printf("Inserted %lu rows\n", (unsigned long)mysql_affected_rows(&conn));
} else {
fprintf(stderr, "Error %d: %s\n", mysql_errno(&conn), mysql_error(&conn));
}
mysql_close(&conn);
}
返回數據的語句(SELECT/SHOW/DESCRIBE/EXPLAIN)
兩種讀取模式對比
| 特性 | mysql_store_result | mysql_use_result |
| 數據位置 | 客戶端內存 | 服務端,逐行傳輸 |
| 適用場景 | 小/中結果集,需隨機訪問 | 大結果集,流式處理 |
| 併發影響 | 釋放服務端資源快 | 長時間佔用服務端線程 |
| 錯誤處理 | 數據已在本地,網絡斷開不影響 | 讀取過程中斷開會報錯 |
完整查詢流程範例
res = mysql_query(&conn, "SELECT id, name FROM users WHERE age > 20");
if (!res) {
MYSQL_RES *result = mysql_store_result(&conn);
if (result) {
printf("Total rows: %lu\n", (unsigned long)mysql_num_rows(result));
MYSQL_ROW row;
while ((row = mysql_fetch_row(result))) {
printf("ID: %s, Name: %s\n", row[0], row[1] ? row[1] : "NULL");
}
mysql_free_result(result);
}
}
結果集導航函數
mysql_data_seek(result, offset):跳轉到指定行號(0-based)
mysql_row_tell(result) / mysql_row_seek(result, offset):基於內部偏移量的精確定位(非行號)
最佳實踐建議
- 必檢查返回值:每個 API 調用後檢查錯誤,使用
mysql_errno()/mysql_error()
- 參數化查詢:生產環境請用
mysql_stmt_prepare() 防注入
- 資源釋放:
mysql_free_result() 必須成對調用,避免內存洩漏
- 連接復用:長連接池優於頻繁建立/銷毀連接
- 大數據集:優先用
mysql_use_result() + 批量處理