MySQL:查询unicode实体

时间:2012-11-08 10:27:13

标签: mysql unicode

我需要从数据库中找到Lämmönmyyntipalvelut这个词。只是,在数据库中,它位于一个字段中,其值是一个PHP数组,使用json_encode()转换为JSON,因此特殊字符被分成十六进制unicode。

所以我的查询是

SELECT * FROM table WHERE (services LIKE '%Lämmönmyyntipalvelut%')

没有结果。没有惊喜。接下来,使用转换的特殊字符进行查询:

SELECT * FROM table WHERE (services LIKE '%L\u00e4mm\u00f6nmyyntipalvelut%')

没有结果,我想知道为什么。接下来我测试了只查询特殊字符:

SELECT * FROM table WHERE (services LIKE '%\u00e4%')

找到应该找到的东西。接下来我开始添加东西(L到开头)以查看它出错的地方:

SELECT * FROM table WHERE (services LIKE '%L\u00e4%')

没有结果。另一个测试:

SELECT * FROM table WHERE (services LIKE '%\u00e4mm%')

找到应该找到的东西。

所以我的结论是反斜杠在某种程度上弄乱了,但我不明白怎么回事?

修改

服务字段的确切内容:

["Neuvonta","L\u00e4mm\u00f6nmyyntipalvelut",
"Mets\u00e4-\/energiapuunkorjuupalvelut"]

确切查询:

SELECT id, uid, company_name, services, logo FROM rekisteroeidy_toimijaks 
WHERE 
    (services LIKE '%L\u00e4mm\u00f6nmyyntipalvelut%' AND 
    services LIKE '%Mets\u00e4-\/energiapuunkorjuupalvelut%') 
ORDER BY company_name ASC

我添加了一些换行符以帮助提高可读性。

3 个答案:

答案 0 :(得分:8)

  

我完全不知道为什么,但三重逃避有帮助!

嗯,这只是双重逃避,但是它是有效的,这就是原因:在MySQL中,使用LIKE运算符时会涉及第二层转义。

services LIKE '%L\\\\u00e4mm\\\\u00f6n%'

解析MySQL字符串文字可以与LIKE查询%L\\u00e4mm\\u00f6n%进行比较。因为MySQL将LIKE查询中的\视为转义符,所以它实际上会匹配包含L\u00e4mm\u00f6n的文字字符串。

这样做的原因是您可以将字符串与包含文字%_字符的查询表达式匹配。例如,如果我想在列中搜索文字字符串100%,我可以将其与100\%匹配(在查询中写为'100\\%'),并确保我真正得到一个百分之百,而不是任何以百元开头的字符串。

令人遗憾的是,MySQL使用反斜杠进行LIKE查询转义和字符串文字转义,特别是考虑到您可能正在编写一种也使用它们的封闭编程语言,最后会使用实际的三重编码,这看起来像"services LIKE '%L\\\\\\\\u00e4mm\\\\\\\\u00f6n%'" - 唉!

鉴于此行为不符合ANSI SQL,并且无法在任何其他数据库中运行,这是非常不幸的。 ANSI SQL表示默认情况下LIKE查询中没有转义字符,因此如果要匹配文字%_,则必须通过指定自己的转义字符来选择,例如。 :

something LIKE '100=%' ESCAPE '='

对于跨数据库兼容性,最好始终使用LIKE ... ESCAPE表单,并选择除了可怕的反斜杠之外的其他内容! (旁白 - MySQL的SQL字符串文字转义的反斜杠也不符合ANSI标准!但你可以使用NO_BACKSLASH_ESCAPES sql_mode设置关闭该错误行为。)

可能更好的想法是将services分成第二个表而不是将它们压缩成单个字符串列 - 即。将您的架构放在First Normal Form中。然后,您可以对单个值进行简单查找,而不必进行慢速全表扫描子字符串匹配。

答案 1 :(得分:3)

反斜杠是一个元字符,MySQL以这种方式理解:“删除下一个字符,不要将其解析为元字符”。

所以你需要逃避反斜杠:

SELECT * FROM table WHERE (services LIKE '%L\\u00e4%')

现在,MySQL将用“\”替换“\\”(第一个反斜杠是用来逃避第二个的元字符)

答案 2 :(得分:1)

我完全不知道为什么,但三重逃避有帮助!

SELECT id, uid, company_name, services, logo
FROM rekisteroeidy_toimijaks
    WHERE (
    services LIKE  '%L\\\\u00e4mm\\\\u00f6n%'
)
ORDER BY company_name ASC 
LIMIT 0 , 30