[英]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.