如何让MySQL知道LIKE和REGEXP中的多字节字符?

Tim*_*Tim 13 mysql sql unicode utf-8 character-encoding

我有一个包含两列的MySQL表,两列都是utf8_unicode_ci.它包含以下行.除ASCII外,第二个字段还包含Unicode代码点,如U + 02C8(MODIFIED LETTER VERTICAL LINE)和U + 02D0(MODIFIED LETTER TRIANGULAR COLON).

 word   | ipa
--------+----------
 Hallo  | ha?lo?
 IPA    | ?i?pe???a?
Run Code Online (Sandbox Code Playgroud)

我需要使用LIKE和REGEXP搜索第二个字段,但MySQL(5.0.77)似乎将这些字段解释为字节,而不是字符.

SELECT * FROM pronunciation WHERE ipa LIKE '%ha?lo%';  -- 0 rows
SELECT * FROM pronunciation WHERE ipa LIKE '%ha??lo%'; -- 1 row

SELECT * FROM pronunciation WHERE ipa REGEXP 'ha.lo';  -- 0 rows
SELECT * FROM pronunciation WHERE ipa REGEXP 'ha..lo'; -- 1 row
Run Code Online (Sandbox Code Playgroud)

我很确定数据是否正确存储,因为当我检索它并在phpMyAdmin中显示正常时它似乎很好.我在共享主机上,所以我无法真正安装程序.

我怎么解决这个问题?如果不可能:是否有合理的解决方法,不涉及每次都使用PHP处理整个数据库?有40 000行,我并没有使用MySQL(或UTF8,就此而言).我只能在主机上访问PHP和MySQL.

编辑:有一个开放的4年MySQL漏洞报告, Bug#30241正则表达式问题,它指出正则表达式引擎按字节顺序工作.因此,我正在寻找一种解决方法.

Boh*_*ian 9

已编辑以修复有效的批评

使用该HEX()函数将您的字节渲染为十六进制,然后RLIKE在其上使用,例如:

select * from mytable
where hex(ipa) rlike concat('(..)*', hex('needle'), '(..)*'); -- looking for 'needle' in haystack, but maintaining hex-pair alignment.
Run Code Online (Sandbox Code Playgroud)

奇数unicode字符始终呈现其十六进制值,因此您正在搜索标准的0-9A-F字符.

这也适用于"普通"列,您根本不需要它.

ps @Kieren的(有效)点rlike用于强制执行char对

  • 我不认为这会奏效.两个字节"BA","AB"将呈现为"BAAB",然后匹配搜索字节"AA",该字节不在源中.假设`hex()`呈现没有空格或分隔符. (2认同)