目錄
一、字符集概念
1、字符(Character)
2、字符編碼
3、字符集(Character set)
二、字符集原理
1、ASCII字符集
2、GB2312
3、GBK
4、GB18030
5、BIG5
6、Unicode 編碼
三、字符序
四、MySQL字符集 & 字符序
1、mysql 字符集
2、mysql 字符序
3、字符集與字符序的關(guān)系
五、MySQL 數(shù)據(jù)存儲字符集 | 數(shù)據(jù)庫內(nèi)部操作字符集
1. 字符集層級關(guān)系
2、如何設(shè)置字符集
2.1 服務(wù)器字符集設(shè)置
2.2 數(shù)據(jù)庫字符集設(shè)置
2.3?數(shù)據(jù)表字符集設(shè)置
2.4?字段字符集設(shè)置
3、多級的字符集 & 多種字符集的作用
六、MySQL 客戶端與服務(wù)端交互字符集 | 數(shù)據(jù)庫外部字符集
1、客戶端與服務(wù)端的交互
2、如何設(shè)置字符集
? ? 我們在使用 MySQL 的過程中,經(jīng)常會碰到諸如亂碼之類的問題。字符編碼與字符集密切相關(guān),MySQL 支持種類繁多的字符集類型,這些字符集到底如何影響 MySQL 數(shù)據(jù)存儲與數(shù)據(jù)傳輸?shù)哪??我們該如何選擇正確的字符集:character_set_client、character_set_connection 和 character_set_results?那就通過這篇文章來幫你捋清個中細(xì)節(jié)和解除困擾吧!
本文依賴以下環(huán)境:
操作系統(tǒng):MAC OS 10.11.6
MySQL:Server version: 5.6.21 MySQL Community Server (GPL)
一、字符集概念
1、字符(Character)
字符是各種文字和符號的總稱,包括各國家文字、標(biāo)點符號、圖形符號、數(shù)字、??(emoji表情)等屬于字符的范疇。
2、字符編碼
計算機(jī)是通過 BIT 來存儲數(shù)據(jù)的,將人類可識別的字符轉(zhuǎn)換成計算機(jī)能夠存儲的形式,這個過程就是字符編碼。
3、字符集(Character set)
字符集是多個字符的集合,包含一組字符以及對應(yīng)的編碼方式。字符集種類較多,每個字符集包含的字符個數(shù)和編碼方式不同,常見字符集名稱:ASCII 字符集、GB2312 字符集、BIG5 字符集、 GB18030 字符集、Unicode 字符集等。
二、字符集原理
1、ASCII字符集
我們熟知的 ASCII 字符集是一種現(xiàn)代美國英語適用的字符集。包括的字符有數(shù)字、大小寫字母、分號、換行之類的符號,編碼方式是用一個 7bit 表示一個字符,例如A的編碼是 65,b 的編碼是 98。
ASCII(American Standard Code for Information Interchange,美國標(biāo)準(zhǔn)信息交換代碼)是基于拉丁字母的一套電腦編碼系統(tǒng),主要用于顯示現(xiàn)代英語和其他西歐語言,主要編碼表如下圖所示。
2、GB2312
GB2312 字符集是一種對漢字比較友好的字符集,共收錄 6700 多個漢字,基本涵蓋了絕大部分常用漢字。不過,GB2312 字符集不支持絕大部分的生僻字和繁體字。對于英語字符,GB2312 編碼和 ASCII 碼是相同的,1 字節(jié)編碼即可。對于非英字符,需要 2 字節(jié)編碼。
3、GBK
GBK 字符集可以看作是 GB2312 字符集的擴(kuò)展,兼容 GB2312 字符集,共收錄了 20000 多個漢字。GBK 中 K 是漢語拼音 Kuo Zhan(擴(kuò)展)中的 “Kuo” 的首字母。
4、GB18030
GB18030 完全兼容 GB2312 和 GBK 字符集,納入中國國內(nèi)少數(shù)民族的文字,且收錄了日韓漢字,是目前為止最全面的漢字字符集,共收錄漢字 70000 多個。
5、BIG5
BIG5 主要針對的是繁體中文,收錄了 13000 多個漢字。
6、Unicode 編碼
ASCII 只對英文符號和英文字母做了編碼,GB2312對英文符號,英文字母,漢字做了編碼。每個國家為了更加適合本國語言,都有一套自己的字符集。不同的字符集可以表示的字符范圍以及編碼規(guī)則存在差異。同一個編碼,對于不同的字符集來說就可能代表不同的字符:
這就導(dǎo)致了一個非常嚴(yán)重的問題:使用錯誤的編碼方式查看一個包含字符的文件就會產(chǎn)生亂碼現(xiàn)象。就比如說你使用 UTF-8 編碼方式打開 GB2312 編碼格式的文件就會出現(xiàn)亂碼。示例:“?!边@個漢字 GB2312 編碼后的十六進(jìn)制數(shù)值為 “C5A3”,而 “C5A3” 用 UTF-8 解碼之后得到的卻是 “?”。
為了解決不同語言編碼之間不兼容的問題,Unicode 出現(xiàn)了。Unicode 字符集致力于為全世界每一個語言的每一個字符都有統(tǒng)一且唯一的編碼,Unicode 字符序號的范圍是 0x000000 到0x10FFFF,可以容納 110 多萬個字符。UTF8、UTF16、UTF32 是 Unicode 編碼的不同實現(xiàn)方式:
- UTF-8 使用 1 到 4 個字節(jié)為每個字符編碼, UTF-16 使用 2 或 4 個字節(jié)為每個字符編碼,UTF-32 固定位 4 個字節(jié)為每個字符編碼。
- UTF-8 可以根據(jù)不同的符號自動選擇編碼的長短,像英文字符只需要 1 個字節(jié)就夠了,這一點 ASCII 字符集一樣 。因此,對于英語字符,UTF-8 編碼和 ASCII 碼是相同的。
- UTF-32 的規(guī)則最簡單,不過缺陷也比較明顯,對于英文字母這類字符消耗的空間是 UTF-8 的 4 倍之多。
?
三、字符序
一個字符集中有多個字符,那么如何對其中的字符進(jìn)行排序呢?這就是字符序。簡單來說,字符序就是字符排序的規(guī)則集合。
一個字符集中有多個字符,那么如何對其中的字符進(jìn)行排序呢?這就是字符序。比如一個字符集有下面幾個字符以及字符編碼:
我們可以直接按照 A > B > a > b 的規(guī)則來進(jìn)行排序,這就是這個簡單字符集的一個字符序。如果想讓小寫字母放在前面,比如 a > b > A > B,這又是一種字符序。如果還想加上大小寫無關(guān)或大小寫相關(guān),這就產(chǎn)生了不同的字符序。
四、MySQL字符集 & 字符序
接下來我們來看看 MySQL 的字符集與字符序。MySQL 目前支持多種字符集,支持在不同的字符集之間轉(zhuǎn)換(便于移植和支持多語言)。
1、mysql 字符集
通過命令: mysql -u[username]?-p[password]? 連接上MySQL后,用下面命令查詢MySQL 支持的字符集:
SHOW CHARACTER SET;
結(jié)果:
指定條件查詢:?
SHOW CHARACTER SET LIKE 'utf%';
結(jié)果:
字段含義:
- Charset: 字符集的名稱;
- Description:字符集的簡單描述;
- Default collation:該字符集的默認(rèn)字符序;
- Maxlen:該字符集中字符最大存儲長度。
2、mysql 字符序
每個字符集都對應(yīng)一個或多個字符序,可以通過下面的語句查看所有的字符序:
SHOW COLLATION;
結(jié)果(部分展示):
?指定條件查詢:
SHOW COLLATION WHERE Charset = 'utf8mb4';
結(jié)果:
字段含義:?
- Collation:字符序名稱;
- Charset:該字符序關(guān)聯(lián)的字符集;
- Id:字符序ID;
- Default:該字符序是否是所關(guān)聯(lián)的字符集的默認(rèn)字符序。比armscii8_general_ci就是armscii8的默認(rèn)字符序,而armscii8_bin就不是;
- Compiled:字符集是否已編譯到服務(wù)器中;
- Sortlen:這與對以字符集表示的字符串進(jìn)行排序所需的內(nèi)存量有關(guān);
- Pad_attribute:這表明了字符序在比較字符串時對末尾padding的處理。NO PAD表明在比較字符串時,末尾的padding也會考慮進(jìn)去,否則不考慮。
每個字符序都是以該字符序所關(guān)聯(lián)的字符集為前綴的,同時還有一些有規(guī)律的后綴:
- bin:二進(jìn)制;
- ci:大小寫不敏感;
- cs:大小寫敏感;
- ai:口音(Accent)不敏感;
- as:口音敏感;
- ks:假名(Kanatype)敏感。
同時有的字符序是面向某種語言的,也會在字符序名字中有所體現(xiàn),比如big5_chinese_ci。
?
3、字符集與字符序的關(guān)系
字符集與字符序的關(guān)系可以上面的圖來表示:
- 每個字符集都有一個或多個字符序;
- 每個字符集都有一個默認(rèn)的字符序;
- 每個字符序都關(guān)聯(lián)一個且只有一個字符集;
- 兩個不同的字符集沒有相同的字符序。
五、MySQL 數(shù)據(jù)存儲字符集 | 數(shù)據(jù)庫內(nèi)部操作字符集
1. 字符集層級關(guān)系
MySQL 是按層級來設(shè)定字符集與字符序的,MySQL 可以設(shè)置:服務(wù)器級字符集、數(shù)據(jù)庫級字符集、數(shù)據(jù)表級字符集、表列級別字符集。實際上,最終使用字符集的地方是存儲字符的列,它決定了數(shù)據(jù)庫中存儲的數(shù)據(jù)采用哪個字符集的編碼和字符序。
結(jié)構(gòu)圖:
?層級圖:
如上圖所示:
上一層級如果沒有指定字符集與字符序,就采用下一層級的字符集與字符序。也就是說:新建數(shù)據(jù)庫時沒有指定字符集,就默認(rèn)設(shè)置為服務(wù)器的字符集;如果新建數(shù)據(jù)表時沒有指定字符集,就默認(rèn)設(shè)置為數(shù)據(jù)庫的字符集;如果向數(shù)據(jù)表添加新列時沒有指定列的字符集,那么這些列就默認(rèn)設(shè)置為數(shù)據(jù)表的字符集。與字符集相同,如果不特別指定,字符序也采取了默認(rèn)值繼承的方式。
另一方面,直接改變這四個層次的編碼并不會改變它們各自所有下層對象的當(dāng)前編碼。比如修改 Server 級,那么所有已經(jīng)存在的數(shù)據(jù)庫、數(shù)據(jù)表、表、列的字符集都不會發(fā)生改變。同樣,修改某個字段的字符集,該字段下每一條現(xiàn)有記錄的字符仍然按原來的編碼存儲。
2、如何設(shè)置字符集
我們先來看下,MySQL 剛安裝完,MySQL 字符集的的初始字符集和字符序是什么?
查看字符集變量:
SHOW VARIABLES LIKE 'character_set\_%';
查看字符序變量:
SHOW VARIABLES LIKE '%collation%';
查詢結(jié)果:
character_set_server:服務(wù)器的字符集是 latin1
collation_server: 服務(wù)器的字符序是 latin1_swedish_ci
character_set_database:數(shù)據(jù)庫的字符集是 latin1
collation_database:數(shù)據(jù)庫的字符序是 latin1_swedish_ci
從上圖可以看出,MySQL 服務(wù)器安裝后已經(jīng)初始化了服務(wù)器和數(shù)據(jù)庫的默認(rèn)字符集和字符序,那么,默認(rèn)的配置從何而來呢?
- 編譯MySQL 時,指定了一個默認(rèn)的字符集,這個字符集是 latin1,MySQL 8.0 以后默認(rèn)值應(yīng)是 utf8mb4;
- 安裝MySQL 時,可以在配置文件 (myconf | my.ini) 中指定一個默認(rèn)的的字符集,如果沒指定,這個值繼承自編譯時指定的;
- 啟動mysqld 時,可以在命令行參數(shù)中指定一個默認(rèn)的的字符集,如果沒指定,這個值繼承自配置文件中的配置,此時 character_set_server 被設(shè)定為這個默認(rèn)的字符集。
另外,我們在創(chuàng)建數(shù)據(jù)庫、表、添加字段時,都可以默認(rèn)采用上一級的字符集和字符序,也可以在創(chuàng)建時自行指定。
2.1 服務(wù)器字符集設(shè)置
通過 character_set_server 變量的設(shè)定字符集的幾個方式:
方式 1:在 my.cnf | my.ini 中配置
[mysqld]
character-set-server=utf8
方式 2:啟動時配置參數(shù)
mysqld --charater-set-server=utf8
方式 3:編譯時指定
[root@database-one ~]# cmake . -DDEFAULT_CHARSET=utf8
2.2 數(shù)據(jù)庫字符集設(shè)置
// -- 示例: 創(chuàng)建數(shù)據(jù)庫
create database if not exists dbtest character set utf8;
// -- 示例:修改數(shù)據(jù)庫
ALTER DATABASE dbtest CHARACTER SET 'utf8';
2.3?數(shù)據(jù)表字符集設(shè)置
// -- 創(chuàng)建表時:DEFAULT CHARSET=utf8mb4 設(shè)置字符集
CREATE TABLE `t_employee` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '員工ID',
`code` varchar(10) NOT NULL COMMENT '員工編碼',
`name` varchar(10) NOT NULL COMMENT '員工姓名',
`age` int(10) unsigned DEFAULT NULL COMMENT '年齡',
`sex` int(10) unsigned DEFAULT NULL COMMENT '性別',
`cert_type` int(10) unsigned DEFAULT NULL COMMENT '證件類型',
`cert_no` varchar(20) DEFAULT NULL COMMENT '證件號',
`birthday` date DEFAULT NULL COMMENT '生日',
`income_date` date DEFAULT NULL COMMENT '入職日期',
PRIMARY KEY (`id`),
UNIQUE KEY `code` (`code`),
UNIQUE KEY `cert_type` (`cert_type`,`cert_no`)
) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=utf8mb4 COMMENT='員工表';
// -- 修改表的字符集
ALTER TABLE `dbtest`.`t_employee` CHARACTER SET = utf8mb4;
2.4?字段字符集設(shè)置
// -- 創(chuàng)建表時:CHARACTER SET utf8mb4指定字段字符集
CREATE TABLE `t_employee` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '員工ID',
`code` varchar(10) NOT NULL COMMENT '員工編碼',
`name` varchar(10) NOT NULL COMMENT '員工姓名',
`age` int(10) unsigned DEFAULT NULL COMMENT '年齡',
`sex` int(10) unsigned DEFAULT NULL COMMENT '性別',
`cert_type` int(10) unsigned DEFAULT NULL COMMENT '證件類型',
`cert_no` varchar(20) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '證件號',
`birthday` date DEFAULT NULL COMMENT '生日',
`income_date` date DEFAULT NULL COMMENT '入職日期',
PRIMARY KEY (`id`),
UNIQUE KEY `code` (`code`),
UNIQUE KEY `cert_type` (`cert_type`,`cert_no`)
) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=utf8 COMMENT='員工表';
// -- 修改字段的字符集:CHARACTER SET utf8mb4
ALTER TABLE `dbtest`.`t_employee`
MODIFY COLUMN `cert_no` varchar(20) CHARACTER SET utf8mb4 NULL DEFAULT NULL COMMENT '證件號' AFTER `cert_type`;
3、多級的字符集 & 多種字符集的作用
多級繼承的字符集與字符序:可以方便快捷的設(shè)置下一層級的字符集和字符序,比如一個數(shù)據(jù)庫下面有很多張表,只需要將數(shù)據(jù)庫的字符集設(shè)置為 UTF8,所有表創(chuàng)建時就指定了默認(rèn)的字符集。
MySQL 早期只支持有限數(shù)量字符集,后來不斷的擴(kuò)展,例如從早期的 latin 1 到?UTF8(閹割版本的utf8,?MySQL 較早的版本為了節(jié)省存儲空間,只三個字節(jié))完全夠用了,后面出現(xiàn)了 EMOJI?表情符號、復(fù)雜的漢字、繁體字等需要 4 個字節(jié)存儲,就不能滿足要求了,于是有 mysql 的 utf8mb4 字符集。
MySQL 支持在同一個服務(wù)器的數(shù)據(jù)庫設(shè)置不同的字符集,同一個數(shù)據(jù)庫下的不同表也可以設(shè)定不同的字符集,同一個表的不同字段也可以設(shè)定不同的字符集,都是為了方便業(yè)務(wù)的移植和擴(kuò)展。(例如以前一個業(yè)務(wù)只覆蓋了歐洲英文國家,采用 ladin 1字符集就足夠了,但是后來有擴(kuò)展到中國,于是需要將字符集擴(kuò)展到 UTF8;之前全部字段(nickname)采用UTF8字符集,但是發(fā)現(xiàn)有些用戶的昵稱?EMOJI 表情符號,導(dǎo)致注冊失敗,于是將?nickname 字段的字符集修改為 utf8mb4)。
六、MySQL 客戶端與服務(wù)端交互字符集 | 數(shù)據(jù)庫外部字符集
1、客戶端與服務(wù)端的交互
上面 4 種級別的字符集都是用于數(shù)據(jù)保存的,屬于「數(shù)據(jù)庫內(nèi)部操作字符集」。另外,客戶端和服務(wù)器之間的交互也受到其它「數(shù)據(jù)庫外部字符集」的影響。
MySQL 采用?C/S 架構(gòu),所以它有服務(wù)端和客戶端(如:MySQL自帶的客戶端、Navicat for MySQL等), 如果兩端分布在不同的的主機(jī)上,那么兩端通常需要通過 TCP/IP 獲其他協(xié)議建立連接,然后實現(xiàn)通信或數(shù)據(jù)傳輸。跟 HTTP 協(xié)議有點異曲同工,HTTP 發(fā)起請求時會在 Header 里附上客戶端“信息體”采用的字符集,MySQL 兩端也需要提前溝通好通信采用的字符集,否則服務(wù)器端不知道客戶端要的是什么,客戶端也不知道服務(wù)端給的是什么,也就是雞同鴨講,亂碼就會出現(xiàn)了。
MySQL提供了 character_set_client、character_set_connection 和 character_set_results 三個變量來輔助客戶端與服務(wù)端的通信。
-
character_set_client:服務(wù)器會將請求(如:一條 SQL 查詢語句)的字節(jié)序列當(dāng)作采用?
character_set_client?
字符集進(jìn)行編碼的字節(jié)序列。 - character_set_connection:連接數(shù)據(jù)庫時的字符集。
- character_set_results:數(shù)據(jù)庫給客戶端返回時使用的字符集。
每次客戶端在連接服務(wù)器時,都會將客戶端「默認(rèn)的字符集」
與用戶名、密碼等信息一起發(fā)給服務(wù)器,服務(wù)器根據(jù)發(fā)過來的信息,統(tǒng)一把這三個系統(tǒng)變量設(shè)定好。
客戶端「默認(rèn)的字符集」
與客戶端所在的操作系統(tǒng)環(huán)境變量有關(guān),如果在 Unix 或 Linux 上,你設(shè)置了?LANG
?或?LC_ALL
?這樣的環(huán)境變量,那么 MySQL 的客戶端程序會默認(rèn)檢查應(yīng)該使用哪一個字符集。例如:如果將?LC_ALL
?設(shè)置為?en_US.UTF-8
?,那么?mysql
?客戶端將默認(rèn)使用?UTF8 字符集
?。
用 local 命令查看系統(tǒng)環(huán)境的字符集:UTF8
shitao-2:~ shitao$ locale
LANG="zh_CN.UTF-8"
LC_COLLATE="zh_CN.UTF-8"
LC_CTYPE="zh_CN.UTF-8"
LC_MESSAGES="zh_CN.UTF-8"
LC_MONETARY="zh_CN.UTF-8"
LC_NUMERIC="zh_CN.UTF-8"
LC_TIME="zh_CN.UTF-8"
LC_ALL=
基于筆者的操作系統(tǒng)環(huán)境,現(xiàn)在我們通過命令來查看這三個變量的賦值:
SHOW VARIABLES LIKE 'character_set\_%';
結(jié)果如下:
可以看到這三個變量都被設(shè)置成了 UTF8?字符集?,F(xiàn)在我們來看下客戶端發(fā)起的一次請求,這三個變量是如何起作用的。
流程圖:
(1)mysql Server 收到請求時將請求數(shù)據(jù)從 character_set_client 字符集轉(zhuǎn)換為?character_set_connection 字符集;
(2)進(jìn)行內(nèi)部操作前將請求數(shù)據(jù)從 character_set_connection 字符集轉(zhuǎn)換為內(nèi)部操作字符集,步驟如下
? A. 使用每個數(shù)據(jù)字段的字符集設(shè)定值;
? B. 若上述值不存在,則使用對應(yīng)數(shù)據(jù)表的字符集設(shè)定值;
? C. 若上述值不存在,則使用對應(yīng)數(shù)據(jù)庫的字符集設(shè)定值;
? D. 若上述值不存在,則使用 character_set_server 設(shè)定值。
(3)最后將操作結(jié)果從內(nèi)部操作字符集轉(zhuǎn)換為 character_set_results 字符集。
為什么不直接將?character_set_client?
字符集轉(zhuǎn)為內(nèi)部操作字符集?,中間 character_set_connection 轉(zhuǎn)換步驟的是否是多余的呢?其作用機(jī)制可以參考:Mysql中character_set_client、connection和results
為了加深理解,我們做兩個小測試:
測試一:在數(shù)據(jù)集庫里新建表 tb_example, 表和字段的字符集都默認(rèn)是 utf8, 插入數(shù)據(jù)如下:
?輸入一條查詢語句:?
select id from tb_example where name = "牛";
正常返回查詢結(jié)果:
+------+
| id ? |
+------+
| 1001 |
+------+
現(xiàn)在我們在客戶端執(zhí)行下列語句:
set character_set_client=gbk;
然后再次執(zhí)行上面相同的查詢語句,卻返回為空
mysql> select id from example where name = "牛";
Empty set (0.03 sec)
分析:因為服務(wù)端?character_set_client 被設(shè)置為 GBK 后,服務(wù)器會將請求的字節(jié)序列(UTF8)當(dāng)作用?GBK?編碼的字節(jié)序列。 例如:“牛”的 UTF8編碼是 E7899B,這個編碼在GBK里對應(yīng)的就是其他字符了,所以導(dǎo)致查詢的結(jié)果為空。
測試二:現(xiàn)在恢復(fù)到測試一之前的情況,輸入下面的語句
set character_set_resuluts=gbk;
執(zhí)行下面的查詢語句:
select * from example where name = "牛";
返回結(jié)果:
+------+------+
| id ? | name |
+------+------+
| 1001 | ?? ? |
+------+------+
分析:可以看到存入數(shù)據(jù)庫里的字符“?!保║TF8編碼),卻按照 character_set_resuluts 指定的字符集(GBK編碼)返回給客戶端,字符的內(nèi)容就錯亂了。
另外,這三個變量其實是有作用域的(global | session),每一次創(chuàng)建新的連接,就為這三個變量創(chuàng)建了一個會話作用域 session ,剛才針對 character_set_client 和?character_set_resulut 的設(shè)置都這是針對當(dāng)前 session 起作用的。關(guān)閉后或重新打開新的連接,這三個變量都會恢復(fù)到最初的設(shè)置。
讓我們通過命令查看全局變量,與之前查詢命令相比,添加了?global 修飾符:
SHOW global VARIABLES LIKE 'character_set\_%';
結(jié)果:
可以觀察到,這三個字符集全局變量(global)與 會話變量(session),并不相同,那么這全局變量有什么作用呢?可以參考 <mysql 8.0 版本>:MySQL 官網(wǎng)的解釋
如上圖所示:以?character_set_client 為例,服務(wù)端是根據(jù)客戶端的請求來設(shè)定該值的(如:前面所說客戶端默認(rèn)字符集 + 后面將會提到的其他三種設(shè)置方式),如果服務(wù)端沒有辦法獲取到客戶端的請求字符集,或者客戶端設(shè)置的字符集服務(wù)端不支持,那么將采用全局變量里這三個變量的值,在 mysql 8.0 版本,這三個值的默認(rèn)值為? utf8mb4,? 在筆者這里查詢到這三個全局變量字符集是?Ladin 1,也可以推斷上圖的 default_value 應(yīng)該是 Ladin 1。
2、如何設(shè)置字符集
如果你不想采用系統(tǒng)環(huán)境變量的默認(rèn)字符集,也可以采用其他方式來進(jìn)行設(shè)置:
方式 1:在 MySQL 配置文件 my.cnf | my.ini 中設(shè)置
如果客戶端程序支持?--default-character-set
?選項,你可以使用該選項。你可以將下列選項加入配置文件中,這樣在每次建立和服務(wù)端的連接后,就會進(jìn)行默認(rèn)的字符集設(shè)置:
[client]
default-character-set=utf8
方式 2:在建立連接后,在客戶端輸入下列語句
SET NAMES utf8;
方式 3:部分編程語言的驅(qū)動提供了接口來實現(xiàn)類似的功能
對于 Java,你可以通過為連接數(shù)據(jù)庫的 URL 指定?characterEncoding
?屬性來進(jìn)行客戶端所使用字符集的指定,例如:
jdbc:mysql://localhost:3306/mydatabase?useUnicode=true&characterEncoding=utf8
以上三種方式等效于在客戶端與服務(wù)器連接后,同時執(zhí)行以下三條命令,將三個變量統(tǒng)一設(shè)置為相同的字符集:
SET character_set_client=utf8;
SET?character_set_connection=utf8;
SET?character_set_results=utf8;
備注:這里的?character_set_client 有一定的迷惑性,其實它是客戶端與服務(wù)端建立連接時候,雙方約定的結(jié)果,也就是說,服務(wù)端會按 character_set_client 設(shè)置的字符集來接收客戶端發(fā)來的 SQL 語句,但是并不能保證客戶端一定就會按約定的字符集發(fā)送信息。
就像我們上面的「測試一」,在建立連接后,手動將 character_set_client 的字符集由 UTF8?改成了 GBK 字符集, 客戶端仍然按 UTF8 字符集發(fā)送消息,就會造成對接時字符集錯亂,導(dǎo)致查詢結(jié)果為空。
同理,在「測試二」手動修改了?character_set_results 的值也造成了接受返回數(shù)據(jù)顯示為亂碼。所以我們采取上面 3 種方式來配置字符集變量的時候,一定要確保客戶端環(huán)境實際采用的字符集與?character_set_client 和?character_set_results 完全一致。
參考:
MySQL配置文件my.ini詳解
你真的搞懂MySQL的字符集了嗎?
MySQL字符集的不同級別和效果
深入理解MySQL字符集及校對規(guī)則(一)
MySQL的字符編碼體系(一)——數(shù)據(jù)存儲編碼
MySQL-解析客戶端SQL執(zhí)行字符集參數(shù)設(shè)置文章來源:http://www.zghlxwxcb.cn/news/detail-758200.html
MySQL中的字符集與字符序文章來源地址http://www.zghlxwxcb.cn/news/detail-758200.html
到了這里,關(guān)于MySQL 字符集概念與原理及如何配置字符集 - 超詳細(xì)圖文詳解的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!