SQL報了一個不常見的錯誤,讓新來的實習生懵了

摘要:前些天一個很簡單的SQL報了一個不常見的錯誤。

本文分享自華爲雲社區《記一次mysql關聯查詢格式衝突問題【五月04】》,作者: KevinQ 。

問題起源

作爲CRUD程序員,最常用的功能當然是數據庫查詢了。

前些天一個很簡單的SQL報了一個不常見的錯誤:

Illegal mix of collations (utf8mb4_general_ci,IMPLICIT) and (utf8mb4_unicode_ci,IMPLICIT) for operation '='

今天我們就來看看mysql的utf8mb4的兩種格式問題,以及如何解決這個問題?

mysql的utf8格式與排序規則

字符集uft8與uft8mb4

在mysql中創建表並添加字段的時候,想選utf8字符集時會有兩個選擇:

  1. utf8
  2. utf8mb4

這兩個有什麼區別呢?

MySQL是在5.5.3之後纔有utf8mb4的字符集可選,mb4的意思是:Most Bytes 4,可以兼容unicode。

而utf8最多支持3個字節,比如3個字節的uft8無法支持Emoji表情和不常用的漢字,以及任何新增的Unicode字符等,因此才引入了uft8mb4。

排序規則

我們這次的問題是排序規則衝突引起的:

查詢語句:

SELECT * FROM table1 t1 
left join table2 on t1.username = t2.username

關聯字段的編碼字符集均爲utf8mb4,但是t1.username的排序規則是utf8mb4_general_ci,而t2.username的排序規則是utf8mb4_unicode_ci。

兩種排序規則的區別與特點是什麼呢?

特點

utf8mb4_unicode_ci 是基於標準的 Unicode 來排序和比較,即能夠支持所有Unicode字符的精確排序;
而utf8mb4_general_ci沒有實現Unicode排序規則,在遇到特殊字符時,排序可能不同。

區別

也因此,uft8mb4_general_ci相比utf8mb4_unicode_ci,前者的準確性雖然打了折扣,但是比較和排序執行的速度更快,並且,通常遇到特殊字符的順序並不重要。

排序規則不兼容的解決方案

在mysql中,排序規則不兼容的解決方案有兩種:

1、第一種,修改表字段的格式一致。

即修改表的排序規則統一爲utf8mb4_unicode_ci,或者另一種。官方更推薦使用utf8mb4_unicode_ci的排序規則,借用StackOverflow上的一段話:

There is almost certainly no reason to use utf8mb4_general_ci anymore, as we have left behind the point where CPU speed is low enough that the performance difference would be important. Your database will almost certainly be limited by other bottlenecks than this.

大概意思是說,當前CPU的運行速度已經快到可以讓我們不再將此排序作爲一個考慮參數,而更應該開了其他開銷。

2、另一種方式則是藉助關鍵字,COLLATE

通過COLLATE屬性,可以指定列的排序和比較方式。

我們在使用時,將它放在關聯查詢需要修改排序規則的地方:

SELECT
    u.guid
FROM
    `test`  t
LEFT JOIN user u ON u.guid = t.guid COLLATE utf8mb4_unicode_ci
WHERE t.state = 1

如此,使用COLLATE屬性,可以讓使用不同排序規則的字段進行關聯查詢。

但是,經過測試,這樣會減慢SQL查詢的速度。

具體採用哪種方式,需要細細考量。

 

點擊關注,第一時間瞭解華爲雲新鮮技術~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章