我需要从数据库中找到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
我添加了一些换行符以帮助提高可读性。
答案 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