MySQL字符集詳解


一、MySQL字符集編碼簡單介紹

  在使用MySQL時要注意6個需要編碼的地方:系統的編碼、客戶端、服務端、庫、表、列。字符集編碼不僅影響數據存儲,還影響client程序和數據庫之間的交互.在mysql中輸入命令show session variables like '%char%'能夠看到例如以下一些字符集(下面是以win10為例,生產中多數時linux,在linux里面除了latin1之外都是utf8的字符集):

    mysql> show variables like "%char%";
    +--------------------------+-------------------------------------------+
    | Variable_name | Value |
    +--------------------------+-------------------------------------------+
    | character_set_client | gbk |
    | character_set_connection | gbk |
    | character_set_database | latin1 |
    | character_set_filesystem | binary |
    | character_set_results | gbk |
    | character_set_server | latin1 |
    | character_set_system | utf8 |
    | character_sets_dir | F:\jj\mysql-5.6.42-winx64\share\charsets\ |
    +--------------------------+-------------------------------------------+

    8 rows in set (0.00 sec)

  mysql中的字符集都相應着一個默認的校對規則(COLLATION),當然一個字符集也可能相應多個校對規則,可是兩個不同的字符集不能相應同一個規則。使用默認的就可以了

 

  以下來看看上面命令列出的字符集相關變量的含義:

  • character_set_client:server解析客戶端sql語句的字符集.(The character set for statements that arrive from the client. The session value of this variable is set using the character set requested by the client when the client connects to the server).
  • character_set_connection:字符串字面值(literal strings)的字符集.
  • character_set_results:server返回給客戶端的查詢結果或者錯誤提示的字符集編碼.(The character set used for returning query results such as result sets or error messages to the client)
  • character_set_system:這是mysqlserver用來存儲元數據的編碼,通常就是utf8,不要去改動它.
  • character_sets_dir:這是mysql字符集編碼存儲文件夾.
  • character_set_filesystem:這是文件系統字符集編碼,主要用於解析用於文件名稱的字符串字面值,如LOAD DATA INFILE和SELECT ...INTO OUTFILE等語句以及LOAD_FILE()函數.在打開文件之前,文件名稱會從character_set_client轉換為character_set_filesystem指定的編碼.默認值為binary,也就是說不會進行轉換.比如我們設置的character_set_client=GBK,而character_set_filesystem為默認值的話,則采用SELECT...INTO OUTFILE "文件名稱",文件名稱為GBK編碼.反之,假設我們設置了character_set_filesystem=UTF8,則導出的文件名稱為UTF8編碼. 比如:linux系統的終端編碼是UTF8,系統默認語言和編碼為zh_CN.UTF8.我們有一個數據庫名為test,test中有個表名為t1,編碼為latin1,另外,我們在mysqlclient運行了SET NAMES GBK,假設我們不改動character_set_filesystem的值,運行SELECT * FROM t1 INTO OUTFILE '文件1', 能夠發現相應的文件夾以下生成了一個名為"文件1"的文件,那文件名稱編碼是什么呢?事實上這里有幾個地方須要注意,首先,我們的sql語句里面的"文件1"原生編碼就是終端編碼UTF8,也就是'\xe6\x96\x87\xe4\xbb\xb61',而導出數據的語句SELECT * FROM t1 INTO OUTFILE '文件1',依照前面的說法,由於character_set_filesystem為binary,因此'\xe6\x96\x87\xe4\xbb\xb61'不會轉換,這樣終於還是'\xe6\x96\x87\xe4\xbb\xb61',這樣在zh_CN.UTF8的系統中文件名稱不會亂碼.而假設我們設置了character_set_filesystem=UTF8,則原生的'\xe6\x96\x87\xe4\xbb\xb61'會先依照GBK解碼,然后用UTF8編碼,最后的結果是"\xe9\x8f\x82\xe5\x9b\xa6\xe6\xac\xa21",這樣文件名稱就會亂碼了.所以這個變量也最好不要改動,用默認值就OK.
  • character_set_server:服務器默認字符集編碼,假設創建數據庫的時候沒有指定編碼,則采用character_set_server指定編碼.
  • character_set_database:默認數據庫的字符集編碼.假設沒有默認數據庫,則該變量值與character_set_server同樣.事實上這個值代表的就是你當前數據庫的編碼而已,比方使用"use test",而test數據庫的編碼為latin1的話,這個值就是latin1.而你切換的時候"use test2",則character_set_database的值就是數據庫test2的編碼.

二、MySQL字符集編碼層次

  第一部分主要是歸納了MySQL文檔中關於字符集編碼的說明。這部分主要說明下MySQL中字符集編碼層次:服務端-->數據庫-->表-->字段。

  關於系統的編碼主要針對的是我們將來在存儲文件的時候,有可能會將文件直接存貯在mysql的服務器上,那么,我們在數據庫里面存的就是這些文件的路徑,實際文件是存在系統里面的,那么文件名稱就會受到你系統編碼的影響,比如我們mysql設置的utf8編碼的格式存儲的文件路徑,但是系統默認是gbk編碼的,那么文件在保存到系統里的時候,文件的名稱和你存在mysql里面的文件名稱就對應不上了,出現亂碼顯示的問題,所以也要注意系統的編碼。客戶端的編碼問題,我們在第一節的時候說了一下,大家應該比較了解啦。所以我們下面之說mysql內部設置的這些編碼問題。

  簡單來說,服務器編碼就是character_set_server來指定的.當我們創建數據庫的時候能夠指定編碼,假設沒有指定,采用的就是character_set_server指定的編碼.比如:我們使用"create database t1 character set gbk",這里我們指定了數據庫t1的編碼為gbk,所以不會采用character_set_server指定的編碼.而假設我們使用"create database t2",則通過"show create database t2"能夠看到t2的編碼為character_set_server定的編碼.

  同理,mysql表也能夠有自己獨立的編碼,在創建表的時候能夠指定,假設沒有指定,則默認采用數據庫的編碼.比方我們再之前的數據庫t1創建表t11,"create table t11(i int) character set utf8",則表t11的編碼為utf8,假設不指定編碼則編碼為數據庫t1的編碼gbk.

  此外,mysql表中的字段也能夠有自己的編碼,假設不指定字段編碼,則字段編碼與表的編碼一致.

 

三、MySQL連接字符集

  前面談到的編碼內容基本都不會產生亂碼問題,mysql中容易產生亂碼的地方在character_set_client, character_set_connection, character_set_results這三個變量的設定.能夠簡單的通過set names utf8或者charset utf8命令來一次設置這三個參數.

  從文檔中的解釋來看,mysql連接字符集轉換主要包含以下三個步驟:

  • 1.character_set_client是client發送過來的sql語句的編碼,由於服務端本身並不知道client的sql語句的編碼是什么,所以是以這個變量作為clientsql語句的初始編碼.而服務端接收到sql語句后,則會將sql語句轉換為character_set_connection指定的編碼(注意,對於字面值字符串,假設前面有introducer標記如latin1或utf8,則不會進行這一步轉換).轉換完畢,才會真正運行sql語句.
  • 2.進行內部操作前將sql語句中的數據從character_set_connection轉換為數據表中對應字段的編碼.
  • 3.將操作結果從內部字符集編碼轉換為character_set_results編碼.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM