【发布时间】:2012-03-09 21:22:26
【问题描述】:
我正在从多个页面中抓取数据并插入到我的 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。
- 创建后,我的 DB 将其字符集设置为
utf8,将其排序规则设置为utf8_general_ci,并且我也使用了SET NAMES 'utf8' COLLATE 'utf8_general_ci';命令,以防万一。 - 脚注:
-
*然后我也强制退出爬取。 -
**主键只是我从页面中抓取的 ID (VARCHAR(10))。 -
***常用字符数
-
【问题讨论】:
-
使用base64_encode()给我们二进制安全字符串,一个前后db问题。
-
@chris Base64 编码版本的抓取(重复)字符串:
SW50ZXJwZXJzb25hbCBjb21tdW5pY2F0aW9uOyBDb21tdW5pY2F0aW9uIGluIGdyb3VwcyBhbmQgdGVhbXMuIExlYWRlcnNoaXAgYW5kIG1vdGl2YXRpb24gYXMgY3JpdGljYWwgZmFjdG9ycyBpbiB0aGUgbWFuYWdlbWVudCBvZiBlZmZlY3RpdmUgY29tbXVuaWNhdGlvbi4gIFRoZSBlc3NlbnRpYWwgY29tcG9uZW50cyBvZiBlZmZlY3RpdmUgcmVwb3J0IHdyaXRpbmcgYW5kIGVuaGFuY2UgcHJlc2VudGF0aW9uIHNraWxscy4gQ29tbXVuaWNhdGlvbiBza2lsbHMgYXMgYW4gZWZmZWN0aXZlIHRvb2wgZm9yIG1hbmFnaW5nIGNoYW5nZS4=. -
@chris Base64 编码的原始字符串版本(从数据库中检索后):
SW50ZXJwZXJzb25hbCBjb21tdW5pY2F0aW9uOyBDb21tdW5pY2F0aW9uIGluIGdyb3VwcyBhbmQgdGVhbXMuIExlYWRlcnNoaXAgYW5kIG1vdGl2YXRpb24gYXMgY3JpdGljYWwgZmFjdG9ycyBpbiB0aGUgbWFuYWdlbWVudCBvZiBlZmZlY3RpdmUgY29tbXVuaWNhdGlvbi4gVGhlIGVzc2VudGlhbCBjb21wb25lbnRzIG9mIGVmZmVjdGl2ZSByZXBvcnQgd3JpdGluZyBhbmQgZW5oYW5jZSBwcmVzZW50YXRpb24gc2tpbGxzLiBDb21tdW5pY2F0aW9uIHNraWxscyBhcyBhbiBlZmZlY3RpdmUgdG9vbCBmb3IgbWFuYWdpbmcgY2hhbmdlLg== -
@chris 在进入数据库之前,两个字符串(经过 Base64 编码)都等于
SW50ZXJwZXJzb25hbCBjb21tdW5pY2F0aW9uOyBDb21tdW5pY2F0aW9uIGluIGdyb3VwcyBhbmQgdGVhbXMuIExlYWRlcnNoaXAgYW5kIG1vdGl2YXRpb24gYXMgY3JpdGljYWwgZmFjdG9ycyBpbiB0aGUgbWFuYWdlbWVudCBvZiBlZmZlY3RpdmUgY29tbXVuaWNhdGlvbi4gIFRoZSBlc3NlbnRpYWwgY29tcG9uZW50cyBvZiBlZmZlY3RpdmUgcmVwb3J0IHdyaXRpbmcgYW5kIGVuaGFuY2UgcHJlc2VudGF0aW9uIHNraWxscy4gQ29tbXVuaWNhdGlvbiBza2lsbHMgYXMgYW4gZWZmZWN0aXZlIHRvb2wgZm9yIG1hbmFnaW5nIGNoYW5nZS4=
标签: php mysql encoding character-encoding string-comparison