2014-01-06 77 views
4

我相信很多人都知道,不得不處理德語元音變音和UTF8歸類可能是有問題的。諸如a = ä,o = ö,u = ü之類的東西不僅能夠影響結果的排序順序,而且還能夠影響實際結果。下面是一個例子,通過簡單地區分名詞的單數和複數形式(Bademantel - 單數,Bademäntel - 複數),可以清楚地表明事物如何出錯。德國變音符號和UTF8歸類,重訪

CREATE TABLE keywords (
    id INT (11) PRIMARY KEY AUTO_INCREMENT, 
    keyword VARCHAR (255) NOT NULL 
) ENGINE = MyISAM DEFAULT CHARACTER 
SET = utf8 COLLATE = utf8_unicode_ci; 

INSERT INTO keywords (keyword) VALUES ('Bademantel'), ('Bademäntel'); 

SELECT * FROM keywords WHERE keyword LIKE ('%Bademäntel%'); 

結果應該是

+----+------------+ 
| id | keyword | 
+----+------------+ 
| 1 | Bademäntel | 
+----+------------+ 

尚未與utf8_unicode_ci輸出是

+----+------------+ 
| id | keyword | 
+----+------------+ 
| 1 | Bademantel | 
| 2 | Bademäntel | 
+----+------------+ 

這顯然不是所要求的結果。

實際問題與我目前的項目並列。它涉及編寫一個關鍵字解析器,該關鍵字解析器基本上應該用鏈接到相應的產品頁面來替換網站上每個關鍵字的出現。爲了避免不必要的資源浪費只是不同的關鍵字是牽強,但使用任何

SELECT keyword FROM keywords GROUP BY keyword ORDER BY LENGTH(keyword) DESC 

SELECT DISTINCT keyword FROM keywords ORDER BY LENGTH(keyword) DESC 

將導致無法處理(鏈接)的話,所有的非變音版本簡單因爲它們在查詢過程中沒有被提取(即所有包含Bademäntel的關鍵字都將被提取,但Bademantel將被忽略)。

現在我意識到我有幾個選項來解決這個問題。

1)使用utf8_swedish_ci作爲關鍵字表或在查詢期間,這將有效地節省我不必修改大量現有代碼。

SELECT DISTINCT keyword COLLATE utf8_swedish_ci AS keyword FROM keywords ORDER BY LENGTH(keyword) DESC; 

可惜我不是說不願意放棄utf8_unicode_ci因爲)它提供分揀「Eszett」的一個非常不錯的功能(ssß被認爲是相同的),B)不知何故,只是覺得不妥使用瑞典語整理來處理德國相關的東西。

2)修改現有的代碼以利用utf8_bin

SELECT DISTINCT keyword COLLATE utf8_bin AS keyword FROM keywords ORDER BY LENGTH(keyword) DESC; 

這按預期工作,但它有一個討厭的缺點,所有的比較是大小寫敏感的,這意味着如果我決定依靠utf8_bin作爲針對該問題的解決方案,我將有一個很難做到不區分大小寫像LIKE('%Mäntel%')這樣的查詢將絕對省略像Bademäntel這樣的記錄。

我知道這個問題每時每刻都會彈出,但現在有些答案已經很老了,我只想知道是否有其他解決方案可能出現在此期間。我的意思是,我真的無法繞過這樣的想法,即允許簡單的整理來完全改變查詢的結果。排序順序是,但結果本身?

對不起,有點長的帖子,並提前感謝任何形式的建議或評論。

+0

檢查這可以幫助你:* MySQL的字符集/自動分頁*](http://mysql.rjweb.org/doc.php/charcoll) –

回答

1

對於其他任何遇到此問題的人來說,值得注意的是since MySQL 5.6有對utf8_german2_ci排序的官方支持,可以解決所有上述問題。晚得多,比從未猜到。

0

您可以使用關鍵字WHERE BINARY keyword = 'Bademantel'進行二進制檢查。結果將是預期的結果。

看看這個sqlfiddle,這說明這一點:

SELECT * FROM stackoverflow WHERE BINARY keyword = 'Bademantel'; 

| id | keyword | 
|----|------------| 
| 1 | Bademantel | 

SELECT * FROM stackoverflow WHERE keyword = 'Bademantel'; 

| id | keyword | 
|----|------------| 
| 1 | Bademantel | 
| 2 | Bademäntel | 

更多有關此問題在這裏:What effects does using a binary collation have?這裏:What is the best MySQL collation for German language

因此,對於與德國變音符號或法語重音符或捷克特殊字符的應用/波蘭語言,您必須決定哪種行爲最適合您的應用程序。

大多數情況下,您可以使用utf8_general_ci,但有時您必須使用utf8_bin來處理類似Bademantel的情況。

字符串比較一點也不差,utf8_general_ci有時會幫助你。如果您保存了一個字符串,如Straße - 並且您可以搜索Strasse,這也將返回Straße

+0

感謝您的建議,但我已經在我的原稿解釋使用後注意事項是什麼明確的二進制比較,最重要的是區分大小寫。在MySQL 5.6中引入的'utf8_german2_ci'是該問題的最終解決方案。 – brezanac

+0

是的原因,除非你被困在一個生產服務器與MySQL 5.5 – CodeBrauer