首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

Linux 下 C/C++ 連接 MySQL 實戰(二):結果集檢索兩種模式與完整流程

     編輯:MySQL 綜合教學

前言

本文承接「環境與連接」篇,詳細講解 發出查詢 → 檢索結果集 → 處理行數據 → 釋放資源 的標準四步流程,重點對比 mysql_store_result(緩存全量)與 mysql_use_result(流式讀取)的適用場景、API 序列與完整示例代碼。

一、標準四步流程

  1. mysql_query(conn, sql) — 發送 SQL,0 成功。
  2. mysql_store_result(conn) 或 mysql_use_result(conn) — 獲取結果集句柄 MYSQL_RES*。
  3. 循環 mysql_fetch_row(res) — 逐行取得 MYSQL_ROW(char**),返回 NULL 結束。
  4. mysql_free_result(res) — 必須調用,釋放客戶端內存並通知 Server 清理臨時資源。

二、模式 A:mysql_store_result(緩存模式)

MYSQL_RES *res = mysql_store_result(conn);
if (!res) { /* 錯誤處理 */ }

cout << "Total rows: " << mysql_num_rows(res) << '\n';

MYSQL_ROW row;
while ((row = mysql_fetch_row(res))) {
    // 處理 row[0]...row[n-1]
}
mysql_free_result(res);

特點:一次性拉取所有行到客戶端內存,mysql_num_rows 立即可用,適合中小結果集;釋放快,不阻塞 Server。

三、模式 B:mysql_use_result(流式模式)

MYSQL_RES *res = mysql_use_result(conn);
if (!res) { /* 錯誤處理 */ }

MYSQL_ROW row;
while ((row = mysql_fetch_row(res))) {
    // 處理行數據
}
mysql_free_result(res);

特點:按需從 Server 讀取,客戶端內存恆定;但 mysql_num_rows 需遍歷完才知總數;長時間持有會佔用 Server 線程、表鎖,嚴重影響併發,僅適合超大結果集且需流式處理的離線任務。

四、完整示例:緩存模式(推薦生產環境默認)

#include <iostream>
#include <mysql/mysql.h>
#include <string>
using namespace std;

void err(MYSQL *c) {
    if (mysql_errno(c)) {
        cerr << "Err " << mysql_errno(c) << ": " << mysql_error(c) << '\n';
        exit(-1);
    }
}

int main() {
    MYSQL *conn = mysql_init(NULL);
    if (!conn) err(conn);

    if (!mysql_real_connect(conn, "localhost", "root", "123456", "test", 0, NULL, 0))
        err(conn);

    cout << "Connected.\n";
    string sql;
    getline(cin, sql);

    if (mysql_query(conn, sql.c_str())) err(conn);

    MYSQL_RES *res = mysql_store_result(conn);
    if (!res) err(conn);

    cout << "Retrieved " << mysql_num_rows(res) << " rows\n";

    MYSQL_ROW row;
    while ((row = mysql_fetch_row(res))) {
        for (unsigned int i = 0; i < mysql_num_fields(res); ++i)
            cout << (row[i] ? row[i] : "NULL") << '\t';
        cout << '\n';
    }
    mysql_free_result(res);
    mysql_close(conn);
    return 0;
}

五、完整示例:流式模式(大結果集離線導出)

// ... 連接代碼同上 ...
MYSQL_RES *res = mysql_use_result(conn);
if (!res) err(conn);

MYSQL_ROW row;
while ((row = mysql_fetch_row(res))) {
    // 直接寫入文件/網絡流,不留內存
    fwrite(row[0], 1, strlen(row[0]), fp);
    // ...
}
mysql_free_result(res);

六、常見錯誤與避坑

錯誤現象原因修正
調用 mysql_num_rows 返回 0 但有數據使用了 mysql_use_result 未遍歷完改用 mysql_store_result 或先遍歷計數
程序卡住、CPU 100%流式模式下未及時 fetch_row,Server 端阻塞加快消費速度或改用緩存模式
內存暴增 OOM緩存模式處理百萬行大結果集分批查詢(LIMIT 分頁)或改用流式模式
二進制數據截斷/亂碼MYSQL_ROW 不含長度,遇 \0 截斷配合 mysql_fetch_lengths(res) 獲取每列真實長度

下一篇預告:「結果集元數據獲取:列名、類型、長度、標誌、自增判斷」

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