字元集與排序規則概念 在資料庫當中都有字元集和排序規則的概念, 很多開發人員甚至包括有些DBA都會將這個混淆,當然這個情況也有一些情有可原的原因。一來兩者本來就是相輔相成,相互依賴關聯; 另外一方面, 有些資料庫並沒有清晰的區分開兩者。例如,SQL Server中字元集和排序規則就是合在一起的,創建... ...
字元集與排序規則概念
在資料庫當中都有字元集和排序規則的概念, 很多開發人員甚至包括有些DBA都會將這個混淆,當然這個情況也有一些情有可原的原因。一來兩者本來就是相輔相成,相互依賴關聯; 另外一方面, 有些資料庫並沒有清晰的區分開兩者。例如,SQL Server中字元集和排序規則就是合在一起的,創建一個新的資料庫,只有一個Collation給你選擇,並沒有字元集選項概念,實際上你在選擇一個Collatin時,就選定了資料庫的字元集和排序規則,例如Chinese_PRC_CI_AS。在MySQL中,字元集和排序規則是區分開來的,你需要單獨設置字元集和排序規則。當然MySQL字元集和排序規則也是相關聯的。除非特殊需求,只要設置其一即可。設置字元集,即設置了預設的排序規則。
我們先來搞清楚字元、字元集與字元編碼的概念。相信很多人都在這些概念上犯過迷糊。什麼是字元呢? 什麼是字元集呢,什麼有是字元編碼呢?
字元(Charcter)是文字與符號的總稱,包括文字、圖形符號、數學符號等。26個英文字母屬於字元,每個漢字也屬於一個字元。
字元集是一組抽象的字元(Charcter)組合的集合。舉一個例子,所有的漢字就算一個“字元集合”, 所有的英語字母也算一個“字元集合”。 註意,我這裡說它們是字元集合,而且還有雙引號。是因為字元集並不簡單的是字元的集合, 準確概述來說,字元集是一套符號和編碼的規則。 字元集需要以某種字元編碼方式來表示、存儲字元。我們知道,電腦內部,所有信息最終都是一個二進位值。每一個二進位位(bit)有0和1兩種狀態。而如果用不同的0和1組合表示不同的字元就是編碼。
關於字元編碼,我們知道字元最終是以二進位形式存儲在磁碟的,這也是為什麼要有字元編碼的原因,因為電腦最終都要以二進位形式存儲,那麼編碼規則就是用什麼樣的二進位來代表這個字元。例如,我們所熟知的ASCII碼表中,01000011這個二進位對應的十進位是67,它代表的就是英語字母C。準確概述來說,字元編碼方式是用一個或多個位元組的二進位形式表示字元集中的一個字元。每種字元集都有自己特有的編碼方式,因此同一個字元,在不同字元集的編碼方式下,可能會產生不同的二進位形式。
另外,字元集合只是指定了一個集合中有哪些字元,而字元編碼,是為這個集合中所有字元定義相關編號,而字元集(註意與字元集合的區別)是字元和集合與編碼規則的混合體,這也是有時候編碼方案代表字元集的原因。
說了這麼多,相信有些人不能區分UTF8 與 Unicode,例如我們連接MySQL的字元串,這裡面就會包含字元編碼與字元集。
<string value="jdbc:mysql://192.168.xxx.xxx/TEST?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull"/>
那麼Unicode與UTF-8 、UTF-16 、UTF-32是什麼關係?
Unicode(統一碼、萬國碼、單一碼)是一種字元集,Unicode是國際組織制定的可以容納世界上所有文字和符號的字元編碼方案。Unicode用數字0-0x10FFFF來映射這些字元,最多可以容納1114112個字元,或者說有1114112個碼位。UTF-8、UTF-16、UTF-32都是將數字轉換到程式數據的編碼方案。.在Unicode中:漢字“中”對應的數字是20013。我們可以用:UTF-8、UTF-16、UTF-32表示這個數字,將數字20013存儲在電腦中。UTF-8對應是:E4B8AD,UTF-16對應是:FEFF4E2D,UTF-32對應是:0000FEFF00004E2D。簡單來說,UTF-8、UTF-16、UTF-32是Unicode碼一種實現形式,都是屬於Unicode編碼。
在MySQL中,常見的幾個字元集有latin1、GBK、GB2312、BIG5、UTF8、UTF8MB4、UTF16、UTF32等。
而MySQl的排序規則(collation),一般指對字元集中字元串之間的比較、排序制定的規則, MySLQ排序規則特征:
o 兩個不同的字元集不能有相同的校對規則;
o 每個字元集有一個預設校對規則;
o 存在校對規則命名約定:以其相關的字元集名開始,中間包括一個語言名,並且以_ci(大小寫不敏感)、_cs(大小寫敏感)或_bin(二元)結束。
其實對於排序規則的細節問題,我們關註較少,反而對排序規則中是否涉及大小寫敏感關註較多。 例如,系統使用utf8字元集,若使用utf8_bin校對規則執行SQL查詢時區分大小寫,使用utf8_general_ci不區分大小寫(預設的utf8字元集對應的校對規則是utf8_general_ci)。
MySQL字元集的分類
MySQL資料庫的相關字元集設置相當靈活和複雜(靈活性太高,就會引起複雜性),要搞清、弄懂這些概念還真需要花一點時間。這個也是很多人遭遇中文亂碼的真正原因。具體來說,MySQL的字元集有分層的、靈活的特點。如果沒有指定欄位的字元集,那麼就預設使用當前表的字元集,如果沒有指定當前表的字元集,那麼就會預設使用當前資料庫的字元集.... 要瞭解不同字元集的分類,我們先從MySQL的系統變數(字元集相關的系統變數)開始
mysql> show variables like 'character_set%';
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | utf8 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)
character_set_client 客戶端數據使用的字元集
MySQL Client發送給mysqld的語句或數據使用字元集。
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. (Many clients support a --default-character-set option to enable this character set to be specified explicitly. See also Section 10.1.4, “Connection Character Sets and Collations”.) The global value of the variable is used to set the session value in cases when the client-requested value is unknown or not available, or the server is configured to ignore client requests:
The client is from a version of MySQL older than MySQL 4.1, and thus does not request a character set.
The client requests a character set not known to the server. For example, a Japanese-enabled client requests sjis when connecting to a server not configured with sjis support.
mysqld was started with the --skip-character-set-client-handshake option, which causes it to ignore client character set configuration. This reproduces MySQL 4.0 behavior and is useful should you wish to upgrade the server without upgrading all the clients.
ucs2, utf16, utf16le, and utf32 cannot be used as a client character set, which means that they also do not work for SET NAMES or SET CHARACTER SET.
character_set_connection 連接層字元集
其實很多人對這個字元集一臉懵逼,這個字元集與character_set_client有啥區別呢? 這個字元集用於沒有introducer修飾的字元串和數字到字元串的轉換。
由introducer修飾的文本字元串在請求過程中不經過多餘的轉碼,直接轉換為內部字元集處理。
The character set used for literals that do not have a character set introducer and for number-to-string conversion. For information about introducers, seeSection 10.1.3.8, “Character Set Introducers”.
character_set_database 資料庫字元集
MySQL可以給實例下不同資料庫單獨設置各自的字元集。這個跟SQL Server是類似的。