MySQL中字符集與排序規(guī)則的實(shí)現(xiàn)
在MySQL中,當(dāng)使用字符串類型時,有兩方面的知識我們需要特別關(guān)注一下:字符集和排序規(guī)則。如果使用不當(dāng),則可能會導(dǎo)致性能問題或在插入數(shù)據(jù)時出現(xiàn)一些異常情況。
字符集定義了對應(yīng)列允許使用的字符,而排序規(guī)則是用于比較這些字符的基礎(chǔ)規(guī)則。通常,每個類型的字符集都會有多種排序規(guī)則,但一個排序規(guī)則只能屬于一個字符集。
這篇文章,我們就圍繞MySQL中字符集以及排序規(guī)則展開,詳細(xì)聊聊相關(guān)的技術(shù)點(diǎn)。
MySQL中的字符集
MySQL支持廣泛的字符集,包括GB2312、GBK、BIG5等本地字符集,以及多種Unicode字符集,如utf8mb3 (MySQL中舊版的utf8)、utf8mb4、ucs2、utf16和utf32。utf8mb4是推薦使用的字符集,因?yàn)樗芡暾С炙蠻nicode字符,包括表情符號和不常用的漢字。
可以使用下面的命令在information_schema數(shù)據(jù)庫中查看所有字符集:
mysql> SELECT * FROM information_schema.character_sets ORDER BY character_set_name; +--------------------+----------------------+---------------------------------+--------+ | CHARACTER_SET_NAME | DEFAULT_COLLATE_NAME | DESCRIPTION | MAXLEN | +--------------------+----------------------+---------------------------------+--------+ | armscii8 | armscii8_general_ci | ARMSCII-8 Armenian | 1 | | ascii | ascii_general_ci | US ASCII | 1 | | big5 | big5_chinese_ci | Big5 Traditional Chinese | 2 | | binary | binary | Binary pseudo charset | 1 | …… …… …… | utf16 | utf16_general_ci | UTF-16 Unicode | 4 | | utf16le | utf16le_general_ci | UTF-16LE Unicode | 4 | | utf32 | utf32_general_ci | UTF-32 Unicode | 4 | | utf8 | utf8_general_ci | UTF-8 Unicode | 3 | | utf8mb4 | utf8mb4_0900_ai_ci | UTF-8 Unicode | 4 | +--------------------+----------------------+---------------------------------+--------+
通過上述命令可以列出當(dāng)前MySQL支持的所有字符集,以及它們的默認(rèn)排序規(guī)則。每種字符集都有一個默認(rèn)排序規(guī)則。
在上述命令展示的列表底部,有兩個字符集被描述為UTF-8 Unicode。utf8字符集的MAXLEN為3,而utf8mb4的MAXLEN為4。這里指的是每個字符允許的最大字節(jié)長度。
特別需要留意的是,**根據(jù)UTF-8標(biāo)準(zhǔn),每個字符允許使用最多4個字節(jié),這意味著MySQL的utf8字符集實(shí)際上并不是真正的UTF-8,因?yàn)樗恢С置孔址疃?個字節(jié)。從MySQL 8開始,utf8mb4成為默認(rèn)字符集,也是最常使用的字符集。**而utf8被保留用于向下兼容,應(yīng)該不再使用。
如何定義字符集
定義列的字符集有幾種方式。如果你沒有在表或列級別指定字符集,服務(wù)器默認(rèn)的utf8mb4字符集將被應(yīng)用(除非你明確聲明了一個不同的服務(wù)器或數(shù)據(jù)庫默認(rèn)設(shè)置)。
我們可以通過創(chuàng)建一個沒有字符集信息的表并讀取其定義來驗(yàn)證這一點(diǎn):
CREATE TABLE no_charset ( my_column VARCHAR(255) ); SHOW CREATE TABLE no_charset;
生成的CREATE TABLE語句顯示了默認(rèn)的字符集和排序規(guī)則已經(jīng)被應(yīng)用:
CREATE TABLE `no_charset` ( `my_column` varchar(255) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
在表級別定義
你可以顯式地在表級別設(shè)置字符集,通過使用CHARSET=[字符集]語法。例如,這里我們創(chuàng)建一個所有字符列都使用latin1字符集的表:
CREATE TABLE no_charset ( `my_column` VARCHAR(255) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
在列級別定義
你也可以在列級別設(shè)置字符集。這是最具體的設(shè)置,會覆蓋任何表級別的設(shè)置:
CREATE TABLE `mixed_collations` ( `explicitly_set` VARCHAR(255) CHARACTER SET latin1, `implicitly_set` VARCHAR(255) );
通過運(yùn)行SHOW CREATE TABLE mixed_collations可以看到表的默認(rèn)字符集是utf8mb4,但是顯式設(shè)置的列使用了latin1字符集:
CREATE TABLE `mixed_collations` ( `explicitly_set` VARCHAR(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci DEFAULT NULL, `implicitly_set` VARCHAR(255) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
列級別的聲明將覆蓋表級別的聲明,表級別的聲明將覆蓋數(shù)據(jù)庫默認(rèn),數(shù)據(jù)庫默認(rèn)的字符集覆蓋服務(wù)器默認(rèn)。
MySQL中的排序規(guī)則
字符集定義了可以存儲在列中的合法字符,而排序規(guī)則則是確定如何進(jìn)行字符串比較的規(guī)則。如果你在排序或比較字符串,MySQL就會使用排序規(guī)則來決定順序以及判斷字符串是否相同。
可以通過查詢information_schema表來顯示所有排序規(guī)則。下面的查詢僅顯示與utf8mb4字符集相關(guān)的排序規(guī)則:
mysql> SELECT
-> *
-> FROM
-> information_schema.collations
-> WHERE
-> character_set_name = 'utf8mb4'
-> ORDER BY
-> collation_name;
+----------------------------+--------------------+-----+------------+-------------+---------+---------------+
| COLLATION_NAME | CHARACTER_SET_NAME | ID | IS_DEFAULT | IS_COMPILED | SORTLEN | PAD_ATTRIBUTE |
+----------------------------+--------------------+-----+------------+-------------+---------+---------------+
| utf8mb4_0900_ai_ci | utf8mb4 | 255 | Yes | Yes | 0 | NO PAD |
| utf8mb4_0900_as_ci | utf8mb4 | 305 | | Yes | 0 | NO PAD |
| utf8mb4_0900_as_cs | utf8mb4 | 278 | | Yes | 0 | NO PAD |
| utf8mb4_0900_bin | utf8mb4 | 309 | | Yes | 1 | NO PAD |
| utf8mb4_bin | utf8mb4 | 46 | | Yes | 1 | PAD SPACE |
……
……
……
該查詢將顯示所有排序規(guī)則、相關(guān)字符集名稱、是否為默認(rèn)值以及其他信息。例如,utf8mb4_0900_ai_ci是utf8mb4字符集的默認(rèn)排序規(guī)則。
排序規(guī)則的命名規(guī)則
排序規(guī)則的命名通常前綴為字符集名稱,后綴由排序規(guī)則的屬性組合而成。
以下是一些主要后綴及其含義:
| 后綴 | 含義 |
|---|---|
| _ai | 不區(qū)分重音符 |
| _as | 區(qū)分重音符 |
| _ci | 不區(qū)分大小寫 |
| _cs | 區(qū)分大小寫 |
| _ks | 區(qū)分假名 |
| _bin | 二進(jìn)制比較 |
例如,默認(rèn)排序規(guī)則utf8mb4_0900_ai_ci可以拆解:
utf8mb4:屬于utf8mb4字符集;0900:使用UCA 9.0.0的權(quán)重鍵;_ai:不區(qū)分重音符;_ci:不區(qū)分大小寫。
那么,字符串比較是否區(qū)分大小寫?答案是:“視具體排序規(guī)則而定!”
驗(yàn)證排序規(guī)則
我們可以使用COLLATE關(guān)鍵字顯式設(shè)置字符串的排序規(guī)則:
mysql> SELECT "MySQL" COLLATE utf8mb4_0900_ai_ci = "mysql" COLLATE utf8mb4_0900_ai_ci; +-------------------------------------------------------------------------+ | "MySQL" COLLATE utf8mb4_0900_ai_ci = "mysql" COLLATE utf8mb4_0900_ai_ci | +-------------------------------------------------------------------------+ | 1 | +-------------------------------------------------------------------------+
此查詢返回結(jié)果值為1,表示MySQL認(rèn)為這兩個字符串相等。如果改用區(qū)分大小寫的排序規(guī)則,我們會得到不同的結(jié)果:
mysql> SELECT "MySQL" COLLATE utf8mb4_0900_as_cs = "mysql" COLLATE utf8mb4_0900_as_cs; +-------------------------------------------------------------------------+ | "MySQL" COLLATE utf8mb4_0900_as_cs = "mysql" COLLATE utf8mb4_0900_as_cs | +-------------------------------------------------------------------------+ | 0 | +-------------------------------------------------------------------------+
此查詢返回結(jié)果值為0,表明MySQL認(rèn)為這兩個字符串不同,因?yàn)樗鼈兇笮懖煌?/p>
類似邏輯也適用于重音符。例如,在使用不區(qū)分重音符的排序規(guī)則時,resume與résumé會被認(rèn)為是相同的。
如何定義排序規(guī)則
與字符集類似,排序規(guī)則可以在表級別或列級別設(shè)置。如果未顯式定義排序規(guī)則,MySQL會使用字符集的默認(rèn)排序規(guī)則。
表級別定義
可以在CREATE TABLE語句中使用COLLATE子句定義表的排序規(guī)則。例如,以下創(chuàng)建了一個所有字符列都使用utf8mb4_bin排序規(guī)則的表:
CREATE TABLE table_with_collation ( my_column VARCHAR(255) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
列級別定義
也可以在列定義中設(shè)置排序規(guī)則。例如:
CREATE TABLE table_with_collation ( `explicitly_set` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci, `implicitly_set` varchar(255) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
此外,也可以通過ALTER TABLE語句修改現(xiàn)有表列的排序規(guī)則:
ALTER TABLE table_with_collation
CHANGE `explicitly_set` `explicitly_set` varchar(255)
CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
小結(jié)
理解字符集和排序規(guī)則是處理MySQL字符串?dāng)?shù)據(jù)的基礎(chǔ)。字符集定義了列中存儲的合法字符,排序規(guī)則決定了字符串比較的方式。
- 字符集可以在列級別、表級別定義,或者繼承自數(shù)據(jù)庫或服務(wù)器默認(rèn)值。最具體的層級(列 > 表 > 數(shù)據(jù)庫 > 服務(wù)器)將會被采用。
- 排序規(guī)則可以在列級別、表級別定義,或者繼承自字符集默認(rèn)。仍然是最具體的層級優(yōu)先。
列的字符集和排序規(guī)則會影響數(shù)據(jù)存儲方式以及數(shù)據(jù)的比較和排序行為。在設(shè)計(jì)數(shù)據(jù)庫時需注意這些設(shè)置,以確保行為正確并優(yōu)化性能。
如果不確定應(yīng)使用哪個字符集或排序規(guī)則,MySQL默認(rèn)的utf8mb4字符集及其默認(rèn)排序規(guī)則utf8mb4_0900_ai_ci通常是一個不錯的選擇。它們支持所有Unicode字符并提供大小寫不敏感和重音符不敏感的比較功能。
到此這篇關(guān)于MySQL中字符集與排序規(guī)則的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)MySQL 字符集與排序規(guī)則內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
(MariaDB)MySQL數(shù)據(jù)類型和存儲機(jī)制全面講解
下面小編就為大家分享一篇(MariaDB)MySQL數(shù)據(jù)類型和存儲機(jī)制全面講解,具有很的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-01-01
MySQL8.x連接5.x 服務(wù)器認(rèn)證問題解決
MySQL 8.0與5.x認(rèn)證插件不兼容,需在客戶端指定使用mysql_native_password,下面就來介紹一下如何解決,感興趣的可以了解一下2025-08-08
一臺linux主機(jī)啟動多個MySQL數(shù)據(jù)庫的方法
這篇文章主要介紹了一臺linux主機(jī)啟動多個MySQL數(shù)據(jù)庫的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
解決phpstudy無法啟動MySQL服務(wù)的三種方法小結(jié)
本文主要介紹了光速解決phpstudy無法啟動MySQL服務(wù)的三種方法小結(jié),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-09-09
詳解騰訊云CentOS7.0使用yum安裝mysql及使用遇到的問題
本篇文章主要介紹了騰訊云CentOS7.0使用yum安裝mysql,詳細(xì)的介紹了使用yum安裝mysql及使用遇到的問題,有興趣的可以了解一下。2017-01-01
連接遠(yuǎn)程mysql數(shù)據(jù)庫失敗常見原因及解決方案
這篇文章主要介紹了連接遠(yuǎn)程mysql數(shù)據(jù)庫失敗常見原因及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-07-07
mysql將數(shù)據(jù)庫中所有表結(jié)構(gòu)和數(shù)據(jù)導(dǎo)入到另一個庫的方法(親測有效)
這篇文章主要給大家介紹了關(guān)于mysql將數(shù)據(jù)庫中所有表結(jié)構(gòu)和數(shù)據(jù)導(dǎo)入到另一個庫的方法,文中通過代碼介紹的非常詳細(xì),親測有效,對同樣遇到這個需求的朋友具有一定的參考借鑒價值,需要的朋友可以參考下2024-01-01

