【问题标题】:MySQL C API Handle TEXT fieldMySQL C API 句柄 TEXT 字段
【发布时间】:2011-09-30 16:59:08
【问题描述】:

当使用 MySQL C API 中的 Prepared Statements 处理 TEXT 字段结果时,必须为 out 绑定指定字符串的长度:

 MYSQL_BIND    out_bind;
 char          str_data[STRING_SIZE]; 
 my_bool       is_null;
 my_bool       error;

 ....
 /* STRING COLUMN */
 out_bind.buffer_type = MYSQL_TYPE_STRING;
 out_bind.buffer = str_data;
 out_bind.buffer_length = STRING_SIZE;
 out_bind.is_null= &is_null;
 out_bind.length= &length;
 out_bind.error= &error;

 mysql_stmt_bind_result(statement, out_bind)

在给定的示例中,STRING_SIZE 是已知常量,但如何处理数据长度从小到兆不等的 TEXT 字段?

这有标准的方法吗?

【问题讨论】:

  • 呃! str_data 本身(衰减后)是 char *。你为什么要转换成char *? :)
  • 你是对的。在从真实代码转移到这个简化示例之后,它只是留在这里的一个雏形。没关系。
  • 我记不太清了,但是你可以在返回结构中得到这个
  • 喜欢本例中的 out_bind.length 吗? ;) 但是您必须在调用语句之前进行绑定,这意味着您也必须事先分配内存。而且您必须知道要分配的内存量。我们有一种复杂的查询,做两次会是一种丑陋的解决方案......我相信......
  • 如何在同一个查询中使用 mysql 内置函数以 OCTET_LENGTH() 返回字段的大小,这样您就可以先分配足够的数据,然后一次实际读取它 --- select count( *) 作为“文档”,sum(octet_length(document_data)) 作为 total_size,avg(octet_length(document_data)) 作为 DOCUMENTS 中的 avg_size;

标签: mysql c mysql-connector


【解决方案1】:

manual page for mysql_stmt_fetch 说:

在某些情况下,您可能希望在使用 mysql_stmt_fetch() 获取列值之前确定其长度。 ...要做到这一点,您可以使用以下策略:

  • 在调用mysql_stmt_fetch() 检索单个行之前,将STMT_ATTR_UPDATE_MAX_LENGTH 传递给mysql_stmt_attr_set(),然后调用mysql_stmt_store_result() 在客户端缓冲整个结果。设置STMT_ATTR_UPDATE_MAX_LENGTH 属性会导致列值的最大长度由mysql_stmt_result_metadata() 返回的结果集元数据的max_length 成员指示。

  • 调用mysql_stmt_fetch(),为所讨论的列提供一个零长度缓冲区和一个可以存储实际长度的指针。然后使用mysql_stmt_fetch_column() 的实际长度。

您可能还想阅读manual page for mysql_stmt_bind_result

【讨论】:

    【解决方案2】:

    我有同样的问题。我已经解决了这个问题,就像pmg在第一点说的那样,使用STMT_ATTR_UPDATE_MAX_LENGTH设置,这是我的代码:

    MYSQL_STMT    *stmt;
    MYSQL_BIND    bind[1];
    MYSQL_BIND    bind_result[1];
    
    // _con your mysql connection 
    stmt = mysql_stmt_init(_con);
    if (!stmt)
    {
      fprintf(stderr, " mysql_stmt_init(), out of memory\n");
      exit(0);
    }
    
    char* aQuery = (char*) "'your query'";
    if (mysql_stmt_prepare(stmt, aQuery, strlen(aQuery)))
    {
      fprintf(stderr, " mysql_stmt_prepare(), INSERT failed\n");
      fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
      exit(0);
    }
    
        // Here fill binded parameters (here a string)
    memset(bind, 0, sizeof(bind));
    
    const char* aStr = ioType.c_str();
    long unsigned int aSize = ioType.size();
    
    bind[0].buffer_type= MYSQL_TYPE_STRING;
    bind[0].buffer= (char *) aStr;
    bind[0].buffer_length= 2048;
    bind[0].is_null= 0;
    bind[0].length= &aSize;
    
    /* Bind the buffers */
    if (mysql_stmt_bind_param(stmt, bind))
    {
      fprintf(stderr, " mysql_stmt_bind_param() failed\n");
      fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
      exit(0);
    }
    
        // Reauest meta data information
    MYSQL_RES* aRes = mysql_stmt_result_metadata(stmt);
    
        // Set STMT_ATTR_UPDATE_MAX_LENGTH attribute
    my_bool aBool = 1;
    mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &aBool);
    
    /* Execute the select statement - 1*/
    if (mysql_stmt_execute(stmt))
    {
      fprintf(stderr, " mysql_stmt_execute(), 1 failed\n");
      fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
      exit(0);
    }
    
    if (mysql_stmt_store_result(stmt)) {
      fprintf(stderr, " mysql_stmt_execute(), 1 failed\n");
      fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
      exit(0);
    }       
    
    // Retrieving meta data information
    MYSQL_FIELD* aField = &aRes->fields[0];
    
    fprintf(stdout, " field %s \n",aField->name);
    fprintf(stdout, " field length %d \n",(int) aField->length);
    fprintf(stdout, " field max length %d \n", (int) aField->max_length);
    
    
    int totalrows = mysql_stmt_num_rows(stmt);
    fprintf(stdout, " fetched %d description\n",totalrows);
    fprintf(stdout, " field count %d \n",(int) aRes->field_count);
    
    long unsigned int aMaxSize;
    char* aBuffer = (char*) malloc(aField->max_length);
    
    memset (bind_result, 0, sizeof (bind_result));
    bind_result[0].buffer_type= MYSQL_TYPE_BLOB;
    bind_result[0].is_null= 0;
    bind_result[0].buffer= (char *) aBuffer;
    bind_result[0].buffer_length= aField->max_length;
    bind_result[0].length= &aMaxSize;
    
    mysql_stmt_bind_result(stmt, bind_result);
    
    std::string aStrData;
    while(!mysql_stmt_fetch(stmt))
    {
        fprintf(stdout, " size %d\n", (int) aMaxSize);
        aStrData = std::string(aBuffer,aMaxSize);
        fprintf(stdout, " data %s\n", aStrData.c_str());
    }
    
    free(aBuffer);
    
    mysql_free_result(aRes);
    
    if (mysql_stmt_close(stmt))
    {
      fprintf(stderr, " failed while closing the statement\n");
      fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
      exit(0);
    }
    

    希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多