「連線」是當用戶端程式連線到伺服器時所建立的,以便開始與伺服器互動的階段。用戶端透過階段連線傳送 SQL 陳述式,例如查詢。伺服器透過連線將回應(例如結果集或錯誤訊息)傳送回用戶端。
有數個字元集與校對系統變數與用戶端與伺服器的互動相關。其中一些已在先前的章節中提及
character_set_server
和collation_server
系統變數表示伺服器字元集與校對。請參閱第 12.3.2 節「伺服器字元集與校對」。character_set_database
和collation_database
系統變數表示預設資料庫的字元集與校對。請參閱第 12.3.3 節「資料庫字元集與校對」。
其他字元集和校對系統變數涉及處理用戶端和伺服器之間連線的流量。每個用戶端都有工作階段特定的連線相關字元集和校對系統變數。這些工作階段系統變數值在連線時初始化,但可以在工作階段內變更。
有關用戶端連線字元集與校對處理的幾個問題可以用系統變數來解答
陳述式離開用戶端時的字元集為何?
伺服器採用
character_set_client
系統變數作為用戶端傳送陳述式的字元集。注意某些字元集不能用作用戶端字元集。請參閱不允許的用戶端字元集。
伺服器在收到陳述式後應將陳述式轉換為哪種字元集?
為了確定這一點,伺服器會使用
character_set_connection
和collation_connection
系統變數伺服器會將用戶端傳送的陳述式從
character_set_client
轉換為character_set_connection
。例外情況:對於具有引入器(例如_utf8mb4
或_latin2
)的字串常值,引入器會決定字元集。請參閱第 12.3.8 節「字元集引入器」。collation_connection
對於字串常值的比較很重要。對於字串與資料行值的比較,collation_connection
並不重要,因為資料行有自己的校對,而校對的優先順序較高(請參閱第 12.8.4 節「運算式中的校對強制性」)。
伺服器在將查詢結果傳送回用戶端之前,應將查詢結果轉換為哪種字元集?
character_set_results
系統變數表示伺服器將查詢結果傳回用戶端時使用的字元集。這包括結果資料(例如資料行值)、結果中繼資料(例如資料行名稱)和錯誤訊息。若要告訴伺服器不要對結果集或錯誤訊息執行任何轉換,請將
character_set_results
設定為NULL
或binary
SET character_set_results = NULL; SET character_set_results = binary;
如需有關字元集和錯誤訊息的詳細資訊,請參閱第 12.6 節「錯誤訊息字元集」。
若要查看適用於目前工作階段的字元集和校對系統變數的值,請使用以下陳述式
SELECT * FROM performance_schema.session_variables
WHERE VARIABLE_NAME IN (
'character_set_client', 'character_set_connection',
'character_set_results', 'collation_connection'
) ORDER BY VARIABLE_NAME;
以下較簡單的陳述式也會顯示連線變數,但也會包含其他相關變數。它們可以用來查看所有字元集和校對系統變數
SHOW SESSION VARIABLES LIKE 'character\_set\_%';
SHOW SESSION VARIABLES LIKE 'collation\_%';
用戶端可以微調這些變數的設定,或依賴預設值(在這種情況下,您可以跳過本節的其餘部分)。如果您不使用預設值,您必須針對每個與伺服器的連線變更字元設定。
character_set_client
系統變數不能設定為某些字元集
ucs2
utf16
utf16le
utf32
嘗試使用任何這些字元集作為用戶端字元集會產生錯誤
mysql> SET character_set_client = 'ucs2';
ERROR 1231 (42000): Variable 'character_set_client'
can't be set to the value of 'ucs2'
如果任何這些字元集在下列情境中使用,也會發生相同的錯誤,這些情境都會導致嘗試將 character_set_client
設定為指定的字元集。
MySQL 用戶端程式(例如 mysql 和 mysqladmin)使用的
--default-character-set=
命令選項。charset_name
當用戶端連線到伺服器時,它會指示要用於與伺服器通訊的字元集。(實際上,用戶端會指示該字元集的預設排序規則,伺服器可以從中判斷字元集。)伺服器會使用此資訊將 character_set_client
、character_set_results
、character_set_connection
系統變數設定為該字元集,並將 collation_connection
設定為該字元集的預設排序規則。實際上,伺服器會執行與 SET NAMES
操作等效的操作。
如果伺服器不支援要求的字元集或排序規則,它會改用伺服器字元集和排序規則來設定連線。有關此回退行為的更多詳細資訊,請參閱 連線字元集錯誤處理。
mysql、mysqladmin、mysqlcheck、mysqlimport 和 mysqlshow 用戶端程式會按如下方式判斷要使用的預設字元集:
在沒有其他資訊的情況下,每個用戶端都會使用編譯時預設字元集,通常是
utf8mb4
。每個用戶端都可以根據作業系統設定自動偵測要使用的字元集,例如 Unix 系統上的
LANG
或LC_ALL
地區環境變數的值,或 Windows 系統上的程式碼頁設定。對於可從作業系統取得地區設定的系統,用戶端會使用它來設定預設字元集,而不是使用編譯時預設字元集。例如,將LANG
設定為ru_RU.KOI8-R
會導致使用koi8r
字元集。因此,使用者可以在其環境中設定地區設定,以供 MySQL 用戶端使用。如果沒有完全符合的字元集,作業系統字元集會對應到最接近的 MySQL 字元集。如果用戶端不支援相符的字元集,它會使用編譯時預設字元集。例如,
utf8
和utf-8
對應到utf8mb4
,而ucs2
不支援作為連線字元集,因此它會對應到編譯時預設字元集。C 應用程式可以在連線到伺服器之前,透過如下方式叫用
mysql_options()
,使用基於作業系統設定的字元集自動偵測:mysql_options(mysql, MYSQL_SET_CHARSET_NAME, MYSQL_AUTODETECT_CHARSET_NAME);
每個用戶端都支援
--default-character-set
選項,讓使用者可以明確指定字元集,以覆寫用戶端以其他方式判定的任何預設值。注意某些字元集不能用作用戶端字元集。嘗試將它們與
--default-character-set
一起使用會產生錯誤。請參閱 不允許的用戶端字元集。
使用 mysql 用戶端時,若要使用與預設值不同的字元集,您可以在每次連線到伺服器時明確執行 SET NAMES
陳述式(請參閱 用戶端程式連線字元集設定)。若要更輕鬆地達成相同的結果,請在選項檔案中指定字元集。例如,下列選項檔案設定會在每次您叫用 mysql 時,將三個與連線相關的字元集系統變數變更為 koi8r
:
[mysql]
default-character-set=koi8r
如果您在使用啟用自動重新連線(不建議使用)的 mysql 用戶端,最好使用 charset
命令,而不是 SET NAMES
。例如:
mysql> charset koi8r
Charset changed
charset
命令會發出 SET NAMES
陳述式,也會變更 mysql 在連線中斷後重新連線時使用的預設字元集。
在設定用戶端程式時,您也必須考量它們執行的環境。請參閱 第 12.5 節,「設定應用程式字元集和排序規則」。
連線建立後,用戶端可以變更目前工作階段的字元集和排序規則系統變數。這些變數可以使用 SET
陳述式個別變更,但另外兩個更方便的陳述式會影響一組與連線相關的字元集系統變數:
SET NAMES '
charset_name
' [COLLATE 'collation_name
']SET NAMES
表示用戶端用於將 SQL 陳述式傳送到伺服器的字元集。因此,SET NAMES 'cp1251'
會告知伺服器,「來自此用戶端的未來傳入訊息採用cp1251
字元集。」它也指定伺服器應使用哪個字元集將結果傳回給用戶端。(例如,如果您使用產生結果集的SELECT
陳述式,它會指示要用於資料行值的字元集。)SET NAMES '
陳述式等同於以下三個陳述式:charset_name
'SET character_set_client = charset_name; SET character_set_results = charset_name; SET character_set_connection = charset_name;
將
character_set_connection
設定為charset_name
也會隱含地將collation_connection
設定為charset_name
的預設排序規則。不需要明確設定該排序規則。若要指定要用於collation_connection
的特定排序規則,請新增COLLATE
子句:SET NAMES 'charset_name' COLLATE 'collation_name'
SET CHARACTER SET '
'charset_name
'SET CHARACTER SET
類似於SET NAMES
,但會將character_set_connection
和collation_connection
設定為character_set_database
和collation_database
(如先前所述,它們表示預設資料庫的字元集和排序規則)。SET CHARACTER SET
陳述式等同於以下三個陳述式:charset_name
SET character_set_client = charset_name; SET character_set_results = charset_name; SET collation_connection = @@collation_database;
設定
collation_connection
也會隱含地將character_set_connection
設定為與排序規則相關聯的字元集(等同於執行SET character_set_connection = @@character_set_database
)。不需要明確設定character_set_connection
。
某些字元集不能用作用戶端字元集。嘗試將它們與 SET NAMES
或 SET CHARACTER SET
一起使用會產生錯誤。請參閱 不允許的用戶端字元集。
範例:假設 column1
定義為 CHAR(5) CHARACTER SET latin2
。如果您沒有說 SET NAMES
或 SET CHARACTER SET
,則對於 SELECT column1 FROM t
,伺服器會使用用戶端在連線時指定的字元集傳回 column1
的所有值。另一方面,如果您在發出 SELECT
陳述式之前說 SET NAMES 'latin1'
或 SET CHARACTER SET 'latin1'
,伺服器會在將結果傳回之前,將 latin2
值轉換為 latin1
。對於不在兩個字元集中的字元,轉換可能會遺失資訊。
嘗試使用不適當的連線字元集或排序規則可能會產生錯誤,或導致伺服器回退到其預設字元集和給定連線的排序規則。本節說明在設定連線字元集時可能發生的問題。這些問題可能會在建立連線時或在已建立的連線中變更字元集時發生。
連線時錯誤處理
某些字元集不能用作用戶端字元集;請參閱 不允許的用戶端字元集。如果您指定有效但不允許作為用戶端字元集的字元集,伺服器會傳回錯誤:
$> mysql --default-character-set=ucs2
ERROR 1231 (42000): Variable 'character_set_client' can't be set to
the value of 'ucs2'
如果您指定的字元集是客戶端無法辨識的,則會產生錯誤。
$> mysql --default-character-set=bogus
mysql: Character set 'bogus' is not a compiled character set and is
not specified in the '/usr/local/mysql/share/charsets/Index.xml' file
ERROR 2019 (HY000): Can't initialize character set bogus
(path: /usr/local/mysql/share/charsets/)
如果您指定的字元集是客戶端可以辨識但伺服器無法辨識的,則伺服器會回退到其預設字元集和校對規則。假設伺服器配置為使用 latin1
和 latin1_swedish_ci
作為其預設值,且無法辨識 gb18030
作為有效的字元集。指定 --default-character-set=gb18030
的客戶端能夠連線到伺服器,但最終的字元集並非客戶端所期望的。
mysql> SHOW SESSION VARIABLES LIKE 'character\_set\_%';
+--------------------------+--------+
| Variable_name | Value |
+--------------------------+--------+
| character_set_client | latin1 |
| character_set_connection | latin1 |
...
| character_set_results | latin1 |
...
+--------------------------+--------+
mysql> SHOW SESSION VARIABLES LIKE 'collation_connection';
+----------------------+-------------------+
| Variable_name | Value |
+----------------------+-------------------+
| collation_connection | latin1_swedish_ci |
+----------------------+-------------------+
您可以看到連線系統變數已設定為反映 latin1
和 latin1_swedish_ci
的字元集和校對規則。發生這種情況是因為伺服器無法滿足客戶端字元集請求,並回退到其預設值。
在這種情況下,客戶端無法使用其想要的字元集,因為伺服器不支援。客戶端必須願意使用不同的字元集,或連線到支援所需字元集的不同伺服器。
當客戶端告知伺服器使用伺服器可以辨識的字元集,但客戶端預設的校對規則在伺服器端未知時,也會發生相同的問題。
執行階段錯誤處理
在已建立的連線中,客戶端可以使用 SET NAMES
或 SET CHARACTER SET
來請求變更連線字元集和校對規則。
某些字元集不能用作用戶端字元集;請參閱 不允許的用戶端字元集。如果您指定有效但不允許作為用戶端字元集的字元集,伺服器會傳回錯誤:
mysql> SET NAMES 'ucs2';
ERROR 1231 (42000): Variable 'character_set_client' can't be set to
the value of 'ucs2'
如果伺服器無法辨識字元集(或校對規則),則會產生錯誤。
mysql> SET NAMES 'bogus';
ERROR 1115 (42000): Unknown character set: 'bogus'
mysql> SET NAMES 'utf8mb4' COLLATE 'bogus';
ERROR 1273 (HY000): Unknown collation: 'bogus'
想要驗證其請求的字元集是否被伺服器接受的客戶端,可以在連線後執行以下語句,並檢查結果是否為預期的字元集。
SELECT @@character_set_client;