mysql结果集

本文详细介绍了MySQL查询结果集的内部结构及其操作API,包括mysql_store_result、mysql_use_result、mysql_fetch_row等函数的使用方法及注意事项。

MySQL进行数据查询的时候,mysql会返回一个结果集给我们。接着我们需要调用mysql的api,从这个结果集中取得我们要的数据。

取完数据之后,需要释放这个结果集。

 

mysql的结果集其实就是一个MYSQL_RES结构,其定义如下:

 

 

typedef struct st_mysql_res {

  my_ulonglong row_count;                               // 结果集的行数

  unsigned int field_count, current_field;            // 结果集的列数,当前列

  MYSQL_FIELD *fields;                                    // 结果集的列信息

  MYSQL_DATA *data;                                      // 结果集的数据

  MYSQL_ROWS *data_cursor;                        // 结果集的光标

  MEM_ROOT field_alloc;                                   // 内存结构

  MYSQL_ROW row;                                         // 非缓冲的时候用到

  MYSQL_ROW current_row;                           //mysql_store_result时会用到。当前行

  unsigned long *lengths;                                //每列的长度

  MYSQL *handle;                                           // mysql_use_result会用。

  my_bool eof;                                                 //是否为行尾

} MYSQL_RES;

typedef char ** MYSQL_ROW; /* 返回的每一行的值,全部用字符串来表示*/
typedef struct st_mysql_rows {
  struct st_mysql_rows *next; /* list of rows */
  MYSQL_ROW data;
MYSQL_ROWS;        //mysql的数据的链表节点。可见mysql的结果集是链表结构
typedef struct st_mysql_data {
  my_ulonglong rows;
  unsigned int fields;
  MYSQL_ROWS *data;
  MEM_ROOT alloc;
MYSQL_DATA; // 数据集的结构
typedef struct st_mysql_field {
  char *name; /* Name of column */
  char *table;                                            /* Table of column if column was a field */
  char *def;                                               /* Default value (set by mysql_list_fields) */
  enum enum_field_types type;                /* Type of field. Se mysql_com.h for types */
  unsigned int length;                               /* Width of column */
  unsigned int max_length;                       /* Max width of selected set */
  unsigned int flags;                                  /* Div flags */
  unsigned int decimals;                            /* Number of decimals in field */
MYSQL_FIELD;  //列信息的结构

 

 

typedef struct st_used_mem { /* struct for once_alloc */

  struct st_used_mem *next; /* Next block in use */

  unsigned int left; /* memory left in block  */

  unsigned int size; /* Size of block */

USED_MEM; //内存结构

 

typedef struct st_mem_root {

  USED_MEM *free;

  USED_MEM *used;

  USED_MEM *pre_alloc;

  unsigned int min_malloc;

  unsigned int block_size;

  void (*error_handler)(void);

MEM_ROOT;  //内存结构

 

 

 

之所以列出这些结构,是想让大家对mysql的结果集有更清晰的认识。

以下是取得数据的相关API:

1. . mysql_store_result()

MYSQL_RES *mysql_store_result(MYSQL *mysql)

描述

对于成功检索了数据的每个查询(SELECT、SHOW、DESCRIBE、EXPLAIN、CHECK TABLE等),必须调用mysql_store_result()或mysql_use_result() 。

对于其他查询,不需要调用mysql_store_result()或mysql_use_result(),但是如果在任何情况下均调用了mysql_store_result(),它也不会导致任何伤害或性能降低。通过检查mysql_store_result()是否返回0,可检测查询是否没有结果集(以后会更多)。

如果希望了解查询是否应返回结果集,可使用mysql_field_count()进行检查。请参见25.2.3.22节,“mysql_field_count()”

mysql_store_result()将查询的全部结果读取到客户端,分配1个MYSQL_RES结构,并将结果置于该结构中。

如果查询未返回结果集,mysql_store_result()将返回Null指针(例如,如果查询是INSERT语句)。

如果读取结果集失败,mysql_store_result()还会返回Null指针。通过检查mysql_error()是否返回非空字符串,mysql_errno()是否返回非0值,或mysql_field_count()是否返回0,可以检查是否出现了错误。

如果未返回行,将返回空的结果集。(空结果集设置不同于作为返回值的空指针)。

一旦调用了mysql_store_result()并获得了不是Null指针的结果,可调用mysql_num_rows()来找出结果集中的行数。

可以调用mysql_fetch_row()来获取结果集中的行,或调用mysql_row_seek()和mysql_row_tell()来获取或设置结果集中的当前行位置。

一旦完成了对结果集的操作,必须调用mysql_free_result()。

 

 

2. mysql_use_result()

MYSQL_RES *mysql_use_result(MYSQL *mysql)

描述

对于成功检索数据的每个查询(SELECT、SHOW、DESCRIBE、EXPLAIN),必须用mysql_store_result()或mysql_use_result()。


mysql_use_result()将初始化结果集检索,但并不像mysql_store_result()那样将结果集实际读取到客户端。它必须通过对mysql_fetch_row()的调用,对每一行分别进行检索。这将直接从服务器读取结果,而不会将其保存在临时表或本地缓冲区内,与mysql_store_result()相比,速度更快而且使用的内存也更少。客户端仅为当前行和通信缓冲区分配内存,分配的内存可增加到max_allowed_packet字节。

 

另一方面,如果你正在客户端一侧为各行进行大量的处理操作,或者将输出发送到了用户可能会键入“^S”(停止滚动)的屏幕,就不应使用mysql_use_result()。这会绑定服务器,并阻止其他线程更新任何表(数据从这类表获得)。

使用mysql_use_result()时,必须执行mysql_fetch_row(),直至返回NULL值,否则,未获取的行将作为下一个检索的一部分返回。C API给出命令不同步错误,如果忘记了执行该操作,将不能运行该命令。

不能对结果集用mysql_data_seek()、mysql_row_seek()、mysql_row_tell()、mysql_num_rows()或mysql_affected_rows(),也不应发出其他查询,直至mysql_use_result()完成为止。(但是,提取了所有行后,mysql_num_rows()将准确返回提取的行数)。

一旦完成了对结果集的操作,必须调用mysql_free_result()。

 

返回值

MYSQL_RES结果结构。如果出现错误,返回NULL。

 

3.取得一行的数据:

mysql_fetch_row()

 

MYSQL_ROW mysql_fetch_row(MYSQL_RES *result)

描述

检索结果集的下一行。在mysql_store_result()之后使用时,如果没有要检索的行,mysql_fetch_row()返回NULL。

在mysql_use_result()之后使用时,如果没有要检索的行或出现了错误,mysql_fetch_row()返回NULL。

结果集的列数目由mysql_num_fields(result)给出。如果行中保存了调用mysql_fetch_row()返回的值,将按照row[0]到row[mysql_num_fields(result)-1],访问这些值的指针。行中的NULL值由NULL指针指明。

可以通过调用mysql_fetch_lengths()来获得行中字段值的长度。对于空字段以及包含NULL的字段,长度为0。通过检查字段值的指针,能够区分它们。如果指针为NULL,字段为NULL,否则字段为空。


返回值

下一行的MYSQL_ROW结构。如果没有更多要检索的行或出现了错误,返回NULL。

 

示例代码:

 

//假设mysql已经连接好

 

MYSQL_RES* result = mysql_store_result(mysql);

 

if (result  == NULL)

  return;

 

MYSQL_ROW row;
unsigned int num_fields;
unsigned int i;
num_fields = mysql_num_fields(result);
while ((row = mysql_fetch_row(result)))
{
   unsigned long *lengths;
   lengths = mysql_fetch_lengths(result);
   for(i = 0; i < num_fields; i++)
   {
       printf("[%.*s] ", (int) lengths[i], row[i] ? row[i] : "NULL");
   }
   printf("/n");
}

 

 

4. 取得列的信息。

mysql_fetch_field()


MYSQL_FIELD *mysql_fetch_field(MYSQL_RES *result)

描述

返回采用MYSQL_FIELD结构的结果集的列。重复调用该函数,以检索关于结果集中所有列的信息。未剩余字段时,mysql_fetch_field()返回NULL。

每次执行新的SELECT查询时,将复位mysql_fetch_field(),以返回关于第1个字段的信息。调用mysql_field_seek()也会影响mysql_fetch_field()返回的字段。

如果调用了mysql_query()以在表上执行SELECT,但未调用mysql_store_result(),如果调用了mysql_fetch_field()以请求BLOB字段的长度,MySQL将返回默认的Blob长度(8KB)。之所以选择8KB是因为MySQL不知道BLOB的最大长度。应在日后使其成为可配置的。一旦检索了结果集,field->max_length将包含特定查询中该列的最大值的长度。

返回值

当前列的MYSQL_FIELD结构。如果未剩余任何列,返回NULL。

错误

无。

示例:

MYSQL_FIELD *field; 
while((field = mysql_fetch_field(result)))
{
    printf("field name %s/n", field->name);
}

 

 

 

5. 同4.

 mysql_fetch_fields()

MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *result)

描述

对于结果集,返回所有MYSQL_FIELD结构的数组。每个结构提供了结果集中1列的字段定义。

返回值

关于结果集所有列的MYSQL_FIELD结构的数组。

 

示例:

unsigned int num_fields;
unsigned int i;
MYSQL_FIELD *fields;
 
num_fields = mysql_num_fields(result);
fields = mysql_fetch_fields(result);
for(i = 0; i < num_fields; i++)
{
   printf("Field %u is %s/n", i, fields[i].name);
}

 

6. 

 mysql_free_result()


void mysql_free_result(MYSQL_RES *result)

描述

释放由mysql_store_result()、mysql_use_result()、mysql_list_dbs()等为结果集分配的内存。完成对结果集的操作后,必须调用mysql_free_result()释放结果集使用的内存。


释放完成后,不要尝试访问结果集。

 

返回值

无。

 

永远记得要释放结果集!!!

 

对于mysql的结果集操作,就先讲这么多了。

欢迎大家互相交流。有问题请联系本博主:bicheng.gui@gmail.com

 

 

 

 

 

<think> 首先,用户的问题是关于C++中对MySQL结果进行封装的对象的信息。用户想了解实现和使用这种对象的方法。 从系统级指令来看: - 所有行内数学表达式必须使用$...$格式,但这个问题似乎不涉及数学表达式,所以可能不需要。 - 独立公式用$$...$$,但同样,这里可能不适用。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,如[^1]。 - 回答结构清晰,帮助用户逐步解决问题。 参考提供的引用: - 引用[1]讨论了C++中封装MySQL操作的类,包括数据库连接、执行SQL、获取结果等。 - 引用[2]提到了封装MySQL常用的API,特别是查询获取结果。 - 引用[3]展示了一个类定义MySQLInterface,其中包含方法如getDatafromDB,用于从数据库中获取数据,结果存储在vector<vector<string>>中。 - 引用[4]显示了错误处理的代码片段。 用户的具体问题是:“我想查找C++中对Mysql结果进行封装的对象相关信息 请问C++ Mysql结果封装对象的实现和使用”。这表明用户需要知道如何实现和使用一个封装MySQL结果的对象。 我的回答应该: 1. **结构清晰**:逐步解释实现和使用。 2. **基于引用**:使用提供的引用作为基础。 3. **使用中文**。 4. **生成相关问题**:在回答后添加相关问题。 关键点从引用中提取: - 引用[3]定义了一个类MySQLInterface,其中有一个方法: ```cpp bool getDatafromDB(string queryStr, std::vector<std::vector<std::string> >& data); ``` 这个方法执行查询并将结果存储在vector<vector<string>>中,这就是对结果的封装。 - 引用[2]提到封装是为了方便使用,弥补C API的不足。 - 引用[1]强调了面向对象编程原则来简化数据库交互。 实现思路: - 使用MySQL C API(如mysql.h)。 - 封装结果:查询后,将结果MYSQL_RES)转换为更易用的格式,如二维vector或自定义对象。 - 方法包括连接数据库、执行查询、处理结果、关闭连接。 使用示例: - 从引用中,可以推断出如何使用。例如,创建一个MySQLInterface对象,调用connectMySQL连接,然后调用getDatafromDB执行查询并获取结果。 回答结构: 1. **介绍**:简述封装的目的和好处。 2. **实现**:解释如何实现一个封装结果的对象。包括类定义、关键方法(如获取结果)。 3. **使用**:提供一个简单的使用示例。 4. **引用标识**:自然地添加引用,如基于[^3]。 5. **相关问题**:在最后生成相关问题。 生成相关问题: - 基于主题,如优化、错误处理、其他封装库等。 最终回答框架: - 开头:回应用户问题。 - 主体: - 解释封装对象的概念。 - 详细实现步骤。 - 使用示例。 - 结尾:相关问题。 </think> ### C++中对MySQL结果进行封装对象的实现与使用 在C++中封装MySQL结果对象,主要是为了解决MySQL C API(基于C语言)使用不便的问题。通过面向对象封装,可以将查询结果映射为易于操作的C++数据结构(如`std::vector`或自定义类),提升代码可读性和维护性。以下是基于引用内容的逐步解析,包括实现和使用方法。 #### 1. **封装对象的基本实现** 封装结果的核心是定义一个类,该类内部使用MySQL C API(如`MYSQL_RES`和`MYSQL_ROW`),但对外暴露简洁的接口。关键步骤包括: - **类定义**:创建一个类(如`MySQLInterface`),包含成员变量存储结果和错误信息。 - **结果处理**:将MySQL查询结果(多行多列)转换为C++容器(如`std::vector<std::vector<std::string>>`),每行数据存储为一个子vector。 - **错误处理**:成错误码和错误提示,便于调试。 参考引用[^3]中的`MySQLInterface`类,其关键部分如下: ```cpp class MySQLInterface { public: // ... 其他方法(如连接数据库) bool getDatafromDB(string queryStr, std::vector<std::vector<std::string>>& data); // 查询并封装结果 void errorIntoMySQL(); // 错误处理 private: MYSQL_RES *result; // MySQL原生结果指针 MYSQL mysqlInstance; // MySQL连接对象 int errorNum; // 错误代号 const char* errorInfo; // 错误提示 }; ``` - **实现细节**: - **查询执行**:在`getDatafromDB`方法中,使用`mysql_query()`执行SQL语句。 - **结果转换**:通过`mysql_store_result()`获取`MYSQL_RES`,遍历行和列,将数据存入`std::vector<std::vector<std::string>>`。 - **释放资源**:查询后调用`mysql_free_result()`释放内存,避免泄漏。 - **错误处理**:在方法内部调用`errorIntoMySQL()`捕获错误[^4],例如: ```cpp void MySQLInterface::errorIntoMySQL() { errorNum = mysql_errno(&mysqlInstance); errorInfo = mysql_error(&mysqlInstance); std::cout << errorNum << " : " << errorInfo << std::endl; // 输出错误信息 } ``` #### 2. **使用封装对象执行查询** 使用封装类时,开发者无需直接操作C API,只需调用类方法即可获取格式化结果。以下是典型使用流程: 1. **连接数据库**:创建对象并建立连接。 2. **执行查询**:调用封装方法传入SQL语句。 3. **处理结果**:操作返回的容器数据(如遍历或读取)。 4. **错误处理**:检查错误码或输出错误信息。 **示例代码**(基于引用[^3]): ```cpp #include "MySQLInterface.h" // 包含封装类头文件 int main() { MySQLInterface db; // 步骤1: 连接数据库 if (!db.connectMySQL("localhost", "root", "password", "test_db", 3306)) { db.errorIntoMySQL(); // 输出连接错误 return -1; } // 步骤2: 执行查询并获取结果 std::vector<std::vector<std::string>> resultData; std::string query = "SELECT id, name FROM users WHERE age > 20"; if (db.getDatafromDB(query, resultData)) { // 步骤3: 处理结果 for (const auto& row : resultData) { // 遍历每一行 for (const auto& col : row) { // 遍历每一列 std::cout << col << "\t"; } std::cout << std::endl; } } else { db.errorIntoMySQL(); // 查询失败时输出错误 } // 步骤4: 关闭连接 db.closeMySQL(); return 0; } ``` - **优点**: - **简化操作**:无需手动管理`MYSQL_RES`生命周期。 - **类型安全**:结果以`std::string`存储,避免C API的指针风险。 - **可扩展性**:可扩展为ORM(对象关系映射),例如将结果映射为自定义类对象[^1]。 #### 3. **注意事项** - **内存管理**:确保在析构函数中释放`MYSQL_RES`资源。 - **性能优化**:对于大结果,使用`mysql_use_result()`替代`mysql_store_result()`减少内存占用。 - **跨平台**:封装类应处理不同平台兼容性(如Windows需链接`libmysql.lib`)[^3]。 这种封装方式显著提升了开发效率,特别适合需要频繁数据库交互的C++应用场景[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值