MySQL用' ='选择UTF-8字符串但不喜欢' LIKE'

时间:2015-02-11 19:47:06

标签: mysql unicode utf-8 collation

我有一张桌子,里面有一些来自中世纪书籍的文字,并且有一些重音字母在现代拉丁字母表中不再存在。我可以使用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选择部分字符串并匹配所有字符串?

我尝试使用this information创建自定义归类,但服务器变得不稳定,只有经过大量试验和错误后,我才能再次恢复到utf8_unicode_ci归类,服务器恢复正常状态。 / p>

编辑:此网站存在问题,某些字符无法正常显示。请查看这些pastebins的结果:

http://pastebin.com/mckJTLFX

http://pastebin.com/WP87QvgB

4 个答案:

答案 0 :(得分:3)

看到马库斯亚当斯'回答我意识到REPLACE功能可以解决这个问题,虽然他没有提到这个功能。

因为我只有两个不同的组合字符(急性和波浪形),与其他ASCII字符组合,例如j代表波浪号,j代表尖锐,m代表波浪号,s代表波浪号,等等。我只需要在使用LIKE时替换这两个字符。

在搜索手册后,我了解了UNHEX函数,它帮助我在查询中正确表示组合字符以删除它们。

组合波浪号在HEX代码中由CC83表示,而急性在HEX中由CC81表示。

因此,解决我问题的查询就是这个。

SELECT word, REPLACE(REPLACE(word, UNHEX("CC83"), ""), UNHEX("CC81"), "")
FROM oldword WHERE REPLACE(REPLACE(word, UNHEX("CC83"), ""), UNHEX("CC81"), "") 
LIKE 'hua%';`

答案 1 :(得分:1)

问题是LIKE逐个字符地执行比较,当使用“合并tilda”时,它实际上是两个字符,虽然它显示为一个(假设您的客户端支持显示它)

永远不会有比较例如逐个字符hu~ahua会匹配,因为第三个字符会比较~a

整理(和强制)对你有利,并且在比较整个字符串时处理这些事情,但在逐个字符比较时却没有。

即使您考虑使用SUBSTRING()作为黑客而不是使用带有通配符LIKE的{​​{1}}来执行前缀搜索,请考虑以下事项:

%

你必须知道自己要去的长度或者像这样蛮力:

SELECT SUBSTRING('hũa', 1, 3) = 'hua'
-> 0
SELECT SUBSTRING('hũa', 1, 4) = 'hua'
-> 1

答案 2 :(得分:1)

根据this

在5.6版的所有utf8归类中,

ũ的归类等于普通U

在大多数排序规则中,

的排序规则与普通J相同;例外:

  • utf8_general*ci,因为它实际上是j加上一个重音符号。而“一般”归类一次只查看一个字符(与 byte 区别)。大多数排序规则都会考虑多个字符,例如西班牙语的chll或德语的ss
  • utf8_roman_ci,这很奇怪。 j́=i=j

({LIKE并不完全遵循常规的排序规则。我不熟悉细节,但是我认为J被表示为2个字符会导致其在{{1 }},而不是LIKEWHERE。此外,我不知道ORDER BY是否像REPLACE()或其他地方那样整理。)

答案 3 :(得分:-1)

您可以像使用通配符一样使用%符号。例如:

SELECT word
FROM myTable
WHERE word LIKE 'hua%';

这将拉出所有以hua开头的记录,并且后面跟着0+个字符。这是一个SQL Fiddle示例。