[英]MySQL select UTF-8 string with '=' but not with 'LIKE'
我有一张桌子,里面有一些来自中世纪书籍的文字,并且有一些重音字母,在现代拉丁字母表中不再存在。 我可以使用UTF-8组合字符轻松表示这些字母。 例如,要创建一个带波形符的“J”,我使用UTF-8序列\\ u004A + \\ u0303,J用波浪号重音。
该表使用utf8编码,字段排序规则为utf8_unicode_ci。
我的问题如下:如果我尝试选择整个字符串,我会收到正确的答案。 如果我尝试选择使用'LIKE',我会收到错误的答案。
例如:
mysql> select word, hex(word) from oldword where word = 'hua';
+--------+--------------+
| word | hex(word) |
+--------+--------------+
| hũa | 6875CC8361 |
| huã | 6875C3A3 |
| hua | 687561 |
| hũã | 6875CC83C3A3 |
+--------+--------------+
4 rows in set (0,04 sec)
mysql> select word, hex(word) from oldword where word like 'hua';
+-------+------------+
| word | hex(word) |
+-------+------------+
| huã | 6875C3A3 |
| hua | 687561 |
+-------+------------+
2 rows in set (0,04 sec)
我不想只搜索整个单词。 我想搜索以某些子字符串开头的单词。 最终搜索到的单词是整个单词。
如何使用like选择部分字符串并匹配所有字符串?
我尝试使用此信息创建自定义排序规则,但服务器变得不稳定,只有经过大量试验和错误后,我才能再次恢复到utf8_unicode_ci排序规则并且服务器恢复正常状态。
编辑:这个网站有问题,一些字符无法正确显示。 请查看这些pastebins的结果:
在看到Marcus Adams的回答后,我意识到REPLACE功能可能是解决这个问题的方法,尽管他没有提到这个功能。
因为我只有两个不同的组合字符(锐角和波形符号),与其他ASCII字符组合,例如j代表波浪号,j代表尖锐,m代表波浪号,s代表波浪号,等等。 我只需要在使用LIKE时替换这两个字符。
在查阅手册后,我了解了UNHEX函数,它帮助我在查询中正确表示组合字符以删除它们。
组合波浪号由HEX代码中的CC83
表示, CC83
由HEX中的CC81
表示。
所以,解决我的问题的查询就是这个。
SELECT word, REPLACE(REPLACE(word, UNHEX("CC83"), ""), UNHEX("CC81"), "")
FROM oldword WHERE REPLACE(REPLACE(word, UNHEX("CC83"), ""), UNHEX("CC81"), "")
LIKE 'hua%';`
问题是LIKE
逐个字符地执行比较,当使用“组合tilda”时,它实际上是两个字符,尽管它显示为一个(假设您的客户端支持显示它)。
绝不会有比较哪里的情况下,例如hu~a
到hua
字符一个字符将匹配,因为它比较~
用a
第三字符。
排序(和强制)对你有利,在比较整个字符串时处理这些事情,但在逐个字符比较时则不然。
即使您考虑使用SUBSTRING()
作为hack而不是使用LIKE
和通配符%
来执行前缀搜索,请考虑以下事项:
SELECT SUBSTRING('hũa', 1, 3) = 'hua'
-> 0
SELECT SUBSTRING('hũa', 1, 4) = 'hua'
-> 1
你需要知道你想要的长度或者像这样蛮力:
SELECT * FROM oldword
WHERE SUBSTRING(word, 1, 3) = 'hua'
OR SUBSTRING(word, 1, 4) = 'hua'
OR SUBSTRING(word, 1, 5) = 'hua'
OR SUBSTRING(word, 1, 6) = 'hua'
根据这个 :
ũ
在5.6的所有utf8排序规则中,整数等于普通U
在大多数校对中, j́
collates等于plain J
; 例外:
utf8_general*ci
因为它实际上是j
加上重音。 并且“常规”排序规则一次只查看一个字符 (区别于字节 )。 大多数排序都会考虑多个字符,例如西班牙语中的ch
或ll
或德语中的ss
。 utf8_roman_ci
,这是一个非常奇怪的事。 j́=i=j
( LIKE
并不完全遵循常规的整理规则。我并不精通细节,但我认为J
表示为2个字符会导致它在LIKE
工作方式与在WHERE
或ORDER BY
工作方式不同。此外,我不是知道REPLACE()
是否像LIKE
或其他地方一样整理。)
您可以像使用通配符一样使用%符号。 例如:
SELECT word
FROM myTable
WHERE word LIKE 'hua%';
这将拉出所有以hua开头且后面跟着0+字符的记录。 这是一个SQL小提琴示例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.