重新审视德语元音变音和 UTF8 排序规则

5 mysql collation diacritics

我确信这里很多人都知道,处理德语元音变音和 UTF8 排序规则至少可以说是有问题的。a = \xc3\xa4像, o = \xc3\xb6,之类的东西u = \xc3\xbc不仅能够影响结果的排序顺序,而且还能影响实际结果。这里有一个例子,清楚地展示了简单地尝试区分名词的单数和复数版本(Bademantel- 单数,Badem\xc3\xa4ntel- 复数)会如何出错。

\n\n
CREATE TABLE keywords (\n    id INT (11) PRIMARY KEY AUTO_INCREMENT,\n    keyword VARCHAR (255) NOT NULL\n) ENGINE = MyISAM DEFAULT CHARACTER\nSET = utf8 COLLATE = utf8_unicode_ci;\n\nINSERT INTO keywords (keyword) VALUES (\'Bademantel\'), (\'Badem\xc3\xa4ntel\');\n\nSELECT * FROM keywords WHERE keyword LIKE (\'%Badem\xc3\xa4ntel%\');\n
Run Code Online (Sandbox Code Playgroud)\n\n

结果应该是

\n\n
+----+------------+\n| id | keyword    |\n+----+------------+\n|  1 | Badem\xc3\xa4ntel |\n+----+------------+\n
Run Code Online (Sandbox Code Playgroud)\n\n

utf8_unicode_ci输出是

\n\n
+----+------------+\n| id | keyword    |\n+----+------------+\n|  1 | Bademantel |\n|  2 | Badem\xc3\xa4ntel |\n+----+------------+\n
Run Code Online (Sandbox Code Playgroud)\n\n

这显然不是所需的结果。

\n\n

实际问题与我当前的项目有关。它涉及编写一个关键字解析器,该解析器基本上应该用指向适当产品页面的链接替换网站上出现的每个关键字。为了避免不必要的资源浪费,仅获取不同的关键字,但使用

\n\n
SELECT keyword FROM keywords GROUP BY keyword ORDER BY LENGTH(keyword) DESC\n
Run Code Online (Sandbox Code Playgroud)\n\n

或者

\n\n
SELECT DISTINCT keyword FROM keywords ORDER BY LENGTH(keyword) DESC\n
Run Code Online (Sandbox Code Playgroud)\n\n

将导致无法处理(链接)单词的所有非元音变音版本,因为它们在查询期间没有被获取(即所有包含的关键字Badem\xc3\xa4ntel将被获取但Bademantel将被省略)。

\n\n

现在我意识到我有几个选择来解决这个问题。

\n\n

1)utf8_swedish_ci用于关键字表或在查询期间使用,这将有效地使我不必修改大量现有代码。

\n\n
SELECT DISTINCT keyword COLLATE utf8_swedish_ci AS keyword FROM keywords ORDER BY LENGTH(keyword) DESC;\n
Run Code Online (Sandbox Code Playgroud)\n\n

不幸的是,我并不是那么不愿意放弃, utf8_unicode_ci因为a)它提供了一个非常好的排序“Eszett”的功能(ss并且\xc3\x9f被认为是相同的),b)不知何故,使用瑞典语排序规则来处理德语相关的东西感觉是错误的。

\n\n

2)修改现有代码以使用utf8_bin.

\n\n
SELECT DISTINCT keyword COLLATE utf8_bin AS keyword FROM keywords ORDER BY LENGTH(keyword) DESC;\n
Run Code Online (Sandbox Code Playgroud)\n\n

这按预期工作,但它有一个令人讨厌的缺点,即所有比较都是区分大小写的,这意味着如果我决定依赖它utf8_bin作为问题的解决方案,我将很难执行不区分大小写的查询,这样LIKE(\'%M\xc3\xa4ntel%\')肯定会省略记录喜欢Badem\xc3\xa4ntel

\n\n

我知道这个问题时不时地出现,但有些答案现在已经很旧了,我只是想知道同时是否有其他解决方案出现。我的意思是,我真的无法回避允许简单的排序规则完全改变查询结果的想法。排序顺序是的,但是结果本身呢?

\n\n

抱歉,帖子有点长,并提前感谢您的任何建议或评论。

\n

小智 3

对于遇到此问题的其他人来说,值得注意的是,从 MySQL 5.6 开始,官方支持utf8_german2_ci排序规则,它解决了上述所有问题。我想迟到总比不到好。