检索TEXT值后出现奇怪的字符串比较结果

时间:2012-02-19 01:32:18

标签: php mysql encoding character-encoding string-comparison

我正在从多个页面抓取数据并插入我的MySQL数据库。可能有重复;我只想存储唯一的条目。为了防止我的主键不够用,我输入了一个测试,当我收到MySQL 1062错误*(主键**上的重复输入)时检查。测试检查要插入的元组的所有部分是否与存储的元组相同。我发现当我得到1062错误时,存储的元组和被擦除的元组仅由一个元素/字段TEXT字段不同。

首先,我检索已存储的条目并将它们都传递到htmlspecialchars()以便直观地比较输出;他们看起来很相似。

根据strlen(),从数据库中检索的字符串长度为304个字符,但新删除的字符串为305. similar_text()通过返回304 ***支持该字符串。

然后我通过一个字符串循环比较字符与另一个字符串,在不匹配时停止。问题是第一个角色。在来自数据库的字符串中,它是N,但两个字符串似乎都以I开头(即使在htmlspecialchars()的输出中)。再加上DB字符串应该是一个字符更短,而不是更长。

然后我再次检查了输出(打印htmlspecialchars())和strlen(),但这次插入了原始字符串(最终在数据库中的字符串)之前,并且在复制之前插入。它们看起来和以前一样,strlen()两者都返回305。

所以这让我觉得他们必须在PHP和我的MySQL之间发生一些事情。因此,我不是将新删除的字符串与数据库中具有相同主键(ID)的字符串进行比较,而是尝试检索一个元组,其中每个字段都等于其新截取的部分中的各自部分,如SELECT * FROM table WHERE value1='{$MYSQL_ESCAPED['value1']}' .... AND valueN='{$MYSQL_ESCAPED['valueN']}';并返回元组。因此,它们在各方面都是相同的,包括有问题的TEXT字段。

这里发生了什么?

当我在字符串前面看到N时我会想到来自MSSQL的NVARCHAR等,但我知道这不是MySQL的一部分,但是......

这可能与"Each TEXT value is stored using a two-byte length prefix that indicates the number of bytes in the value."

的事实有关

或者这只是指向字符编码问题?


修改:

  • 数据库中没有存储多字节字符。
  • mb_strlen()会返回与上面提到的strlen()相同的结果。
  • 在插入数据库之前使用utf8_encode()mb_convert_encoding()没有任何区别;不可见的N仍然是从数据库中检索的字符串的前缀。

备注

  • 在将任何字符串插入我的数据库之前,我将其传递给mysql_real_escape_string(trim(preg_replace('/\s\s+/', ' ', $str))),用单个空格替换双空格,删除前导和后缀。拖尾空间并将其转义为MySQL插入。
  • 我打印输出的页面&测试是UTF-8。
  • 创建后,我的数据库的字符集设置为utf8,其归类为utf8_general_ci,我也使用SET NAMES 'utf8' COLLATE 'utf8_general_ci';命令作为预防措施。
  • 脚注:
    • *我也强行退出刮擦。
    • **主键只是一个ID(VARCHAR(10)),我从页面中删除。
    • ***常见字符数

1 个答案:

答案 0 :(得分:0)

当MySQL认为合适时,TEXT字段受字符集转换的影响。但是,MySQL不会在没有理由的情况下随机添加/删除数据。虽然文本字段DO将数据的长度存储为包含文本字段数据的磁盘上数据blob的头部的2个额外字节,但是这2个字节永远不会暴露给最终用户。假设整个客户端 - >数据库 - > on-disk->数据库 - >客户端管道中的字符集设置相同,则任何地方的字符串长度都不应发生变化。