1. 程式人生 > 其它 >MySQL筆記四-字符集和排序規則

MySQL筆記四-字符集和排序規則

碰巧今天遇到兩個業務詢問關於字符集和排序規則的問題,本次就研究下這個 具體的問題如下 問題1:
CREATE TABLE IF NOT EXISTS `t_todo_file` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
    ....
  PRIMARY KEY (`id`),
  KEY `status` (`status`),
    ...
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
報錯如下:(本報錯是建表預檢查系統報錯,具體原因不用在意) {"status": -1, "info": "表 t_todo_file 的字符集未通過檢測!校對字符集為: utf8mb4_0900_ai_ci"} 解決:修改為default charest=utf8mb4 collate=utf8mb4_unicode_ci 問題2: 問:欄位的varchar的編碼預設是和table相同還是和庫相同? 答:和表相同 問:有個表是utf8的,寫進去sql是utf8的,但是讀的時候是亂碼,必須用set name latin1後,查詢才是正常的,這是為什麼? 答:如圖所示: 其中的character_set_results 引數是latin1,這個引數是資料庫返回給客戶端時使用的編碼格式 問:那set name utf8後,是不是連線和返回的結果集編碼都會改? 答:set name是客戶端操作,不會影響服務端,也不能影響服務端 問:那為啥set name latin1後,再select 查詢就不顯示亂碼了呢? 答:可能是你的客戶端預設編碼的utf8,無法識別latin1的資料,所以需要顯示設定為latin1 首先要先明確,什麼是字符集,什麼是排序規則已經他們之間的關係 字符集是一組抽象字元組合的集合,是一套符號和編碼規則,通過符號的組合來表示我們所熟悉的文字,常見的有的字符集有UTF8,gbk,Latin1等 排序規則是指對字符集中字串進行的比較,排序規則。比如utf8字符集的排序規則有utf8mb4_unicode_ci ,utf8mb4_0900_ai_ci(MySQL8.0之後支援)等。 為什麼一個字符集會有多種的排序規則,難道排序規則會變麼?首先排序規則確實會變,比如是是否區分大小寫,以_ci結尾的不區分大小寫,以_cs結尾的區分大小寫。還有排序速度的差異,utf8_general_ci校對速度快,但準確度稍差。utf8_unicode_ci準確度高,但校對速度稍慢,所以要根據需求選擇不同的排序規則。 我們常用的字符集是utf8麼? 是utf8mb4,由於utf8是3位元組的,絕大多數情況下能夠存在大部分的中文漢字,但一些特殊的字元,比如emoji表情就無法儲存,故增加了utf8mb4字符集,他是utf8的超集,有4個位元組,可以存下所有的中文。除非能明確不會有utf8不能儲存的字元並且為了節省空間的場景,不然一般預設使用utf8mb4(還有一種情況就是業務習慣使用) 第一個問題是為什麼會報錯? 因為utf8mb4_0900_ai_ci是mysql8.0才支援的排序規則,而業務的例項的5.6.24的。 MySQL中的字符集是如何設計的 mysql設定了7條規則用於確定字符集 (1)編譯MySQL 時,指定了一個MySQL預設的字符集,這個字符集是 latin1;
(2)安裝MySQL 時,可以在配置檔案 (my.ini) 中指定一個預設的的字符集,如果沒指定,這個值繼承自編譯時指定的; (3)啟動mysql 時,可以在命令列引數中指定一個預設的的字符集,如果沒指定,這個值繼承自配置檔案中的配置,此時 character_set_server 被設定為這個預設的字符集; (4)當建立一個新的資料庫時,除非明確指定,這個資料庫的字符集被預設設定為character_set_server; (5)當選定了一個數據庫時,character_set_database 被設定為這個資料庫預設的字符集; (6)在這個資料庫裡建立一張表時,表預設的字符集被設定為 character_set_database,也就是這個資料庫預設的字符集; (7)當在表內設定一欄時,除非明確指定,否則此欄預設的字符集就是表預設的字符集; 類似優先順序,7優先順序最高,1最低 問題2圖中引數分別代表什麼 一、character_set_client   主要用來設定客戶端使用的字符集。 二、character_set_connection   主要用來設定連線資料庫時的字符集,如果程式中沒有指明連線資料庫使用的字符集型別則按照這個字符集設定。 三、character_set_database   主要用來設定預設建立資料庫的編碼格式,如果在建立資料庫時沒有設定編碼格式,就按照這個格式設定。 四、character_set_filesystem   檔案系統的編碼格式,把作業系統上的檔名轉化成此字符集,即把 character_set_client轉換character_set_filesystem, 預設binary是不做任何轉換的。 五、character_set_results   資料庫給客戶端返回時使用的編碼格式,如果沒有指明,使用伺服器預設的編碼格式。 六、character_set_server   伺服器安裝時指定的預設編碼格式,這個變數建議由系統自己管理,不要人為定義。 七、character_set_system   資料庫系統使用的編碼格式,這個值一直是utf8,不需要設定,它是為儲存系統元資料的編碼格式。 八、character_sets_dir   這個變數是字符集安裝的目錄。 以上紅色條目無需在意 如何修改字符集 可以通過alter table xxx characterset xxxx 或者alter database xxx characterset xxxx,但是這樣修改字符集是不影響存量資料,只變更增量資料。如果想修改存量資料,可以採用按指定字符集匯出再匯入的方式 set names xxx做了什麼 set names xxx實際上相當於重新設定了 character_set_client,character_set_connection,character_set_results,每次連線資料庫都需要執行一遍,所以問題2中業務可用通過此方法解決亂碼問題。