代码之家  ›  专栏  ›  技术社区  ›  Tony Fontenot

从MySQL中选择LONGTEXT列时,CRecordset中出现“内存不足”异常

  •  0
  • Tony Fontenot  · 技术社区  · 17 年前

    我使用COBCRecordset(CodeProject上的一个类)在一个有39列的表中查找单个记录。如果没有找到记录,那么调用CRecordset::Open就可以了。如果记录符合条件,那么当调用CRecordset::Open时,我会收到内存不足异常。我正在选择查询中的所有列(如果我更改查询,只选择其中一个具有相同where子句的列,则没有例外)。

    我认为这是由于CRecordset中的一些限制,但我找不到任何东西告诉我任何限制。该表只有39列。

    有人遇到过这个问题吗?如果是这样,你有解决方案吗?

    这是一个使用Visual Studio 6.0的MFC项目。

    这是查询(格式如下,因此不会显示滚动条):

        SELECT `id`, `member_id`, `member_id_last_four`, `card_number`, `first_name`,
               `mi`, `last_name`, `participant_title_id`, `category_id`, `gender`, 
               `date_of_birth`, `address_line_1`, `address_line_2`, `city`, `state`, 
               `zip`, `phone`, `work_phone`, `mobile_phone`, `fax`, `email`, 
               `emergency_name`, `emergency_phone`, `job_title`, `mail_code`, 
               `comments`, `contract_unit`, `contract_length`, `start_date`, 
               `end_date`, `head_of_household`, `parent_id`, `added_by`, `im_active`, 
               `ct_active`, `organization`, `allow_members`, `organization_category_id`,  
               `modified_date` 
       FROM `participants` 
       WHERE `member_id` = '27F7D0982978B470C5CF94B1B833CC93F997EE23'
    

    复制并粘贴到我的查询浏览器中只会给我一个结果。

    更多信息:

    注释掉select语句中除id之外的每一列。运行查询,没有异常。

    然后,我系统地逐一检查并取消注释每一列,并在每次取消注释之间重新运行查询。

    当我取消注释栏的注释时,就会出现错误。

    这定义如下(使用MySQL):LONGTEXT

    3 回复  |  直到 17 年前
        1
  •  2
  •   paxdiablo    17 年前

    我们可以假设你的意思是你在给C打电话吗 ODBC数据库 记录集::Open(),是吗?或者更确切地说,类似于:

    CDatabase db;
    db.Open (NULL,FALSE,FALSE,"ODBC;",TRUE);
    CODBCRecordSet rs (&db);
    rs.Open ("select blah, blah, blah from ...");
    

    回复后编辑:

    各种ODBC驱动程序存在一些已知的错误,这些错误似乎是由检索无效字段长度引起的。请查看以下链接:

    这个特殊的原因似乎是CRecordset将分配一个足够大的缓冲区来保存该字段。由于列返回的长度为零,因此它被解释为最大32位大小(~2G),而不是最大8位大小(255字节)。不用说,它无法为字段分配足够的内存。

    微软已经承认这是一个问题,看看这些解决方案:

    问题后编辑附录:

    因此,鉴于MySQL字段是LONGTEXT,CRecordSet似乎正在尝试为其分配最大可能大小(2G)。你真的需要2 gig来创建评论字段吗?打字速度为每分钟80个字,每小时6个字,打字员需要7年多一点的时间来填写这个字段,每天24小时不间断地工作:-)。

    查看数据库中的所有列,看看它们是否具有适当的数据类型,这可能是一个有用的练习。我不是说你 不能 有一个2G列,只是你应该确定这是必要的,特别是考虑到当前的ODBC类无法处理那么大的字段。

        2
  •  0
  •   Bill Karwin    17 年前

    阅读帕克斯的回复。它让你很好地理解了问题发生的原因。

    工作周围:

    只有当定义为(TEXT、LONGTEXT等)的字段为NULL(可能为空)时才会发生此错误。如果字段中有数据,则它将仅分配字段中数据的大小,而不是最大大小(从而导致错误)。

    所以,如果有一种情况,你绝对必须拥有这些大字段。以下是一个潜在的解决方案:

    1. 在数据库中为该字段设置默认值。(即。 '<blank>' )
    2. 然后在显示该值时;如果找到默认值,则传递NULL/空。
    3. 然后在更新值时;如果发现NULL/空,则传递默认值。
        3
  •  0
  •   Tony Fontenot    17 年前

    我赞同Pax的建议,即这个错误是由于试图分配一个足够大的缓冲区来容纳最大的LONGTEXT。客户端在获取数据之前不知道数据有多大。

    LONGTEXT确实比您在大多数应用程序中所需的要大得多。考虑使用MEDIUMTEXT(最大大小16MB)或仅使用TEXT(最大尺寸64KB)。

    PHP数据库接口也存在类似的问题。PHP通常有内存大小限制,任何对LONGBLOB或LONGTEXT的读取都可能超过该限制。

    推荐文章