我正在从多个页面抓取数据并插入我的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的一部分,但是......
修改:
mb_strlen()
会返回与上面提到的strlen()
相同的结果。utf8_encode()
或mb_convert_encoding()
没有任何区别;不可见的N
仍然是从数据库中检索的字符串的前缀。备注:
mysql_real_escape_string(trim(preg_replace('/\s\s+/', ' ', $str)))
,用单个空格替换双空格,删除前导和后缀。拖尾空间并将其转义为MySQL插入。 utf8
,其归类为utf8_general_ci
,我也使用SET NAMES 'utf8' COLLATE 'utf8_general_ci';
命令作为预防措施。*
我也强行退出刮擦。 **
主键只是一个ID(VARCHAR(10)
),我从页面中删除。 ***
常见字符数答案 0 :(得分:0)
当MySQL认为合适时,TEXT字段受字符集转换的影响。但是,MySQL不会在没有理由的情况下随机添加/删除数据。虽然文本字段DO将数据的长度存储为包含文本字段数据的磁盘上数据blob的头部的2个额外字节,但是这2个字节永远不会暴露给最终用户。假设整个客户端 - >数据库 - > on-disk->数据库 - >客户端管道中的字符集设置相同,则任何地方的字符串长度都不应发生变化。