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

Linux 下 C/C++ 連接 MySQL 實戰(三):結果集處理深度解析與元數據獲取

     編輯:MySQL 綜合教學

前言

承接前兩篇,本文聚焦 結果集檢索的兩種模式(mysql_store_result vs mysql_use_result)、逐行處理、列元數據獲取(列名、類型、長度、標誌),並提供兩個可直接編譯運行的完整示例。

一、兩種結果集檢索模式對比

特性mysql_store_resultmysql_use_result
數據傳輸一次性將全結果集從 Server 拉取到 Client 內存按需流式讀取,Server 端保持結果集
Client 內存佔用大(與結果集大小成正比)小(僅當前行)
mysql_num_rows 可用性立即可用,準確需遍歷完才知總行數,調用前返回 0
適用場景中小結果集、需隨機訪問、需預知行數大結果集、流式處理、內存受限環境
併發影響釋放 Server 資源快長時間佔用 Server 線程與表鎖,慎用

二、核心 API 速查

MYSQL_RES *mysql_store_result(MYSQL *conn);
MYSQL_RES *mysql_use_result(MYSQL *conn);
MYSQL_ROW  mysql_fetch_row(MYSQL_RES *res);      // 返回 NULL 表示結束或出錯
unsigned int mysql_num_rows(MYSQL_RES *res);     // 僅 store_result 可靠
unsigned int mysql_num_fields(MYSQL_RES *res);   // 列數
void mysql_free_result(MYSQL_RES *res);          // 必須調用,釋放客戶端/服務端資源

三、示例 1:基礎逐行打印(使用 mysql_store_result)

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

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

void print_row(MYSQL *conn, MYSQL_ROW row) {
    for (unsigned int i = 0; i < mysql_field_count(conn); ++i)
        cout << (row[i] ? row[i] : "NULL") << ' ';
    cout << '\n';
}

int main() {
    MYSQL *conn = mysql_init(NULL);
    if (!mysql_real_connect(conn, "localhost", "root", "123456", "test", 0, NULL, 0))
        err(conn);

    if (mysql_query(conn, "SELECT * FROM tmp15")) err(conn);

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

    MYSQL_ROW row;
    while ((row = mysql_fetch_row(res)))
        print_row(conn, row);

    mysql_free_result(res);
    mysql_close(conn);
    return 0;
}

四、列元數據結構 MYSQL_FIELD

typedef struct st_mysql_field {
    char *name;           // 列名
    char *table;          // 所屬表名
    char *org_table;      // 原始表名(別名時)
    char *db;             // 數據库名
    char *def;            // 默認值
    unsigned long length; // 列定義寬度
    unsigned long max_length; // 結果集中最大顯示寬度
    unsigned int flags;   // 標誌位(NOT_NULL, PRI_KEY, AUTO_INCREMENT...)
    unsigned int decimals;// 小數位數
    enum enum_field_types type; // 類型代碼
} MYSQL_FIELD;

五、常用類型判斷宏

IS_NUM(field->type)        // 數值類型
field->type == FIELD_TYPE_VAR_STRING  // VARCHAR
field->type == FIELD_TYPE_LONG        // INT
field->flags & AUTO_INCREMENT_FLAG    // 自增列

六、示例 2:打印列定義再輸出數據(展示元數據用法)

void print_metadata(MYSQL_RES *res) {
    MYSQL_FIELD *field;
    cout << "Column Describe:\n";
    while ((field = mysql_fetch_field(res))) {
        cout << "\tName: " << field->name << '\n';
        cout << "\tType: ";
        if (IS_NUM(field->type)) cout << "Numeric";
        else {
            switch(field->type) {
                case FIELD_TYPE_VAR_STRING: cout << "Varchar"; break;
                case FIELD_TYPE_LONG:       cout << "Long"; break;
                default: cout << "Type code " << field->type;
            }
        }
        cout << "\n\tMax width: " << field->length << '\n';
        if (field->flags & AUTO_INCREMENT_FLAG)
            cout << "\tAUTO_INCREMENT\n";
        cout << '\n';
    }
    mysql_field_seek(res, 0); // 重置游標,以便後續 fetch_row
}

七、編譯與運行

g++ -lmysqlclient demo3.cc -o demo3
./demo3

關鍵提醒:

  • MYSQL_ROW 只是 char**,不含長度信息;含 NULL 或二進制數據時必須配合 mysql_fetch_lengths(res) 使用。
  • 務必成對調用 mysql_free_result,否則會洩漏內存並導致 Server 端臨時表殘留。
  • 長時間持有 mysql_use_result 會阻塞其他寫入,生產環境優先 mysql_store_result 或限制查詢規模。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved