如何在MySQL表中查找搜索字符串的所有变体(重音等)?

时间:2015-12-25 12:31:53

标签: mysql utf-8 non-ascii-characters turkish utf8mb4

我有一个大MySQLInnoDB表,其中包含utf8mb4_unicode_ci中的数据。我有几乎所有基于拉丁字母的语言的记录。我可以轻松地搜索带有重音字符的单词并找到具有不同变化的结果(重音/非重音),但土耳其语有问题。当您指定包含大LIKE个字母的单词时,基本SQL关键字在I行中不起作用。我希望看到所有单词都包括该字母的小写版本(这是无点的i)。

因此,I的英语为i,但土耳其语中的无点 i。 (ı

SELECT * FROM words WHERE word LIKE 'SIR'没有带sır字。它只会带来sir个字,但它们都存在于同一个表中。

你有过这样的问题吗?如何使用SQL解决问题?

更新 SELECT * FROM words WHERE word LIKE 'SIR' COLLATE utf8mb4_turkish_ci 会返回sır,但不会返回sir。尽管这可以解决一些问题,但不幸的是,从这个查询返回需要23秒而不是0.00003秒(没有COLLATE关键字)

2 个答案:

答案 0 :(得分:1)

这对于一般的unicode文本处理来说是一个众所周知的棘手问题。您所能做的就是将OR用于具有不同形式的i的单词或使用正则表达式模式。

答案 1 :(得分:0)

索引或扫描?

在您的示例中,我假设word被编入索引?桌子相当大?在这种情况下,索引非常强大,可以找到与指定排序规则匹配的行。任何其他排序规则(您的COLLATE ...的情况)都需要忽略索引并扫描整个表(慢)。

使用REGEXP 还需要全表扫描 动态执行REPLACE(...)将需要全表扫描。

因此,考虑到允许进行全表扫描的“太多”行,没有简单的方法可以搜索sırsir进行任意整理。让我们寻找另一种方式......

首先,让我们看一些整理案例

在大多数utf8排序规则中,包括utf8_unicode_ci,I = i =Ì=Í=Í=Î=Ï=ì=í=í=î=ï=Ī=ī=Į=į=İ
在utf8_turkish_ci中,我=ı,但它们来自i =Ì=Í=Í=Î=Ï=ì=í=í=î=ï=Ī=ī=Į=į=İ(因此,解释了你的一部分)问题)。
大多数其他utf8校对将ı视为介于i和j之间 utf8_general_ci略有不同:I = i =Ì=Í=Í=Î=Ï=ì=í=í=î=ï=Ī=ī=Į=į=İ=ı
utf8_icelandic_ci将一些带有重音的字母视为不同的字母:I = i =Ì=Î=Ï=ì=î=ï=Ī=ī=Į=į=İ,但Í=Í=í=í介于I和J之间。那个人也在Z之后对它们进行排序:Ä=Æ=ä=æÖ=Ø=ö=øÅ=å

参见我的Reference

另一个问题:重音字母可以显示为两个utf8字符 - 字母,然后是“非间距标记”

那么,该怎么办?

计划A :构建您自己的排序规则。这需要一些工作,但并非不可能。这将是最佳的,为您提供最佳性能。正如我们将在下面看到的,utf8_unicode_520_ci非常接近,可能是一个起点。

计划B :在表格中添加其他列;我们称之为wordx。它会有word,但会剥掉高大的口音。然后索引wordx而不是word。所以word ='sır'的行会有wordx ='sir'。

计划C :使用上面讨论的等价项,如果表中定义的排序规则从每个组中选择“I”,则选择一种类型,然后将utf8_unicode_520_ciUNION一起使用:

( SELECT ... WHERE word = 'sir' )
UNION ALL
( SELECT ... WHERE word = 'sır' )

这应该涵盖i的所有风格。

哎呀,那么多个不同的可重复字母的单词怎么样?乍一看,也许这不是问题 - 所有a整理相同的utf8_unicode_520_ci。浏览其余字母,除了ı给出问题外,我看不到任何其他内容。

以下是utf8_unicode_520_ci 的有趣等价:

A=a=ª=À=Á=Á=Â=Ã=Ä=Å=à=á=á=â=ã=ä=å=Ā=ā=Ą=ą  Aa  ae=Æ=æ  az  B=b  C=c=Ç=ç=Č=č  ch  cz
D=d=Ð=ð=Ď=ď  dz  E=e=È=É=É=Ê=Ë=è=é=é=ê=ë=Ē=ē=Ĕ=ĕ=Ė=ė=Ę=ę=Ě=ě  F=f  fz  ƒ
G=g=Ğ=ğ=Ģ=ģ  gz  H=h  hz  I=i=Ì=Í=Í=Î=Ï=ì=í=í=î=ï=Ī=ī=Į=į=İ  ij=ij  iz  ı  J=j
K=k=Ķ=ķ  L=l=Ĺ=ĺ=Ļ=ļ=Ł=ł  lj=LJ=Lj=lj  ll  lz  M=m  N=n=Ñ=ñ=Ń=ń=Ņ=ņ=Ň=ň  nz
O=o=º=Ò=Ó=Ó=Ô=Õ=Ö=Ø=ò=ó=ó=ô=õ=ö=ø  oe=Œ=œ  oz  P=p  Q=q  R=r=Ř=ř  S=s=Ş=ş=Š=Š=š=š
sh  ss=ß  sz  T=t=Ť=ť  TM=tm=™  tz  U=u=Ù=Ú=Ú=Û=Ü=ù=ú=ú=û=ü=Ū=ū=Ů=ů=Ų=ų  ue  uz  V=v
W=w  X=x  Y=y=Ý=Ý=ý=ý=ÿ=Ÿ  yz  Z=z=Ž=Ž=ž=ž  zh  zz  Þ=þ  µ

如果您认为ƒ是重音字母,那么您可能也想要处理它。

你的问题很有意思。