A.11.1. | MySQL 中有哪些 CJK 字元集可用? |
| CJK 字元集的清單可能會因您的 MySQL 版本而異。例如,MySQL 5.7.4 之前的版本不支援 gb18030 字元集。但是,由於適用語言的名稱會出現在 INFORMATION_SCHEMA.CHARACTER_SETS 表格中每個項目的 DESCRIPTION 欄中,因此您可以使用此查詢來取得所有非 Unicode CJK 字元集的最新清單 mysql> SELECT CHARACTER_SET_NAME, DESCRIPTION
FROM INFORMATION_SCHEMA.CHARACTER_SETS
WHERE DESCRIPTION LIKE '%Chin%'
OR DESCRIPTION LIKE '%Japanese%'
OR DESCRIPTION LIKE '%Korean%'
ORDER BY CHARACTER_SET_NAME;
+--------------------+---------------------------------+
| CHARACTER_SET_NAME | DESCRIPTION |
+--------------------+---------------------------------+
| big5 | Big5 Traditional Chinese |
| cp932 | SJIS for Windows Japanese |
| eucjpms | UJIS for Windows Japanese |
| euckr | EUC-KR Korean |
| gb18030 | China National Standard GB18030 |
| gb2312 | GB2312 Simplified Chinese |
| gbk | GBK Simplified Chinese |
| sjis | Shift-JIS Japanese |
| ujis | EUC-JP Japanese |
+--------------------+---------------------------------+
(如需更多資訊,請參閱第 28.3.4 節「INFORMATION_SCHEMA CHARACTER_SETS 表格」。) MySQL 支援三種 GB(Guojia Biaozhun,或國家標準,或簡體中文)字元集的變體,這些變體在中華人民共和國是官方的:gb2312 、gbk 和(自 MySQL 5.7.4 起)gb18030 。 有時候人們會嘗試將 gbk 字元插入 gb2312 中,而且大部分時候都可以運作,因為 gbk 是 gb2312 的超集。但是,最終他們會嘗試插入較為罕見的中文字元,而這並不可行。(例如,請參閱錯誤 #16072)。 在此,我們嘗試參考官方文件,來明確說明哪些字元在 gb2312 或 gbk 中是合法的。請在回報 gb2312 或 gbk 錯誤之前,先檢查這些參考資料
雖然可用的定序可能無法完全按照您的預期來排序字元,但也可以將 CJK 字元儲存在 Unicode 字元集中
用於 Unicode 字元集的定序決定了在該集中排序(也就是區分)字元的能力
基於 Unicode 定序演算法 (UCA) 4.0.0 的定序僅區分 BMP 字元。 基於 UCA 5.2.0 或 9.0.0 的定序區分 BMP 和補充字元。 非 UCA 定序可能無法區分所有 Unicode 字元。例如,utf8mb4 的預設定序是 utf8mb4_general_ci ,它僅區分 BMP 字元。
此外,區分字元與按照給定 CJK 語言的慣例來排序它們並不相同。目前,MySQL 只有一個 CJK 專用的 UCA 定序,即 gb18030_unicode_520_ci (這需要使用非 Unicode 的 gb18030 字元集)。 如需關於 Unicode 定序及其區分屬性的資訊,包括補充字元的定序屬性,請參閱第 12.10.1 節「Unicode 字元集」。 |
A.11.2. | 我已將 CJK 字元插入我的表格。為什麼 SELECT 會將它們顯示為「?」字元? |
| 這個問題通常是因為 MySQL 中的設定與應用程式或作業系統的設定不符。以下是一些修正這些類型問題的常見步驟
確定您正在使用的 MySQL 版本.
使用語句 SELECT VERSION(); 來確定這一點。
確定資料庫實際上正在使用所需的字元集.
人們通常認為用戶端字元集始終與伺服器字元集或用於顯示目的的字元集相同。然而,這兩個都是錯誤的假設。您可以檢查 SHOW CREATE TABLE tablename 的結果來確定,或者,更好的方法是使用此語句 SELECT character_set_name, collation_name
FROM information_schema.columns
WHERE table_schema = your_database_name
AND table_name = your_table_name
AND column_name = your_column_name;
確定未正確顯示之字元或字元的十六進位值.
您可以使用下列查詢來取得表格 table_name 中欄 column_name 的此資訊 SELECT HEX(column_name)
FROM table_name;
3F 是 ? 字元的編碼;這表示 ? 實際上是儲存在欄位中的字元。這最常發生於將特定字元從用戶端字元集轉換為目標字元集時發生問題。
請確保可以進行往返轉換。當您選取 literal (或 _introducer 十六進位值 ) 時,您是否會得到 literal 作為結果?
例如,日文片假名字元 Pe (ペ' ) 存在於所有 CJK 字元集中,並且具有碼位值 (十六進位編碼) 0x30da 。要測試此字元的往返轉換,請使用此查詢 SELECT 'ペ' AS `ペ`; /* or SELECT _ucs2 0x30da; */
如果結果不是 ペ ,則往返轉換失敗。 對於此類失敗的錯誤報告,我們可能會要求您使用 SELECT HEX('ペ'); 進行追蹤。然後我們可以確定用戶端編碼是否正確。
請確認問題不在瀏覽器或其他應用程式,而是在 MySQL 中.
使用 mysql 用戶端程式來完成此項任務。如果 mysql 正確顯示字元,但您的應用程式無法正確顯示,則您的問題可能是由於系統設定所造成。 要判斷您的設定,請使用 SHOW VARIABLES 陳述式,其輸出應類似於此處顯示的內容 mysql> SHOW VARIABLES LIKE 'char%';
+--------------------------+----------------------------------------+
| Variable_name | Value |
+--------------------------+----------------------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | latin1 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | /usr/local/mysql/share/mysql/charsets/ |
+--------------------------+----------------------------------------+
這些是面向國際用戶端的典型字元集設定 (請注意使用 utf8 Unicode),該用戶端連接到西方的伺服器 (latin1 是西歐字元集)。 雖然 Unicode (通常是 Unix 上的 utf8 變體和 Windows 上的 ucs2 變體) 優於 Latin,但它通常不是您的作業系統公用程式支援的最佳選擇。許多 Windows 使用者發現 Microsoft 字元集 (例如日文 Windows 的 cp932 ) 很適合。 如果您無法控制伺服器設定,並且不知道您的底層電腦使用哪種設定,請嘗試變更為您所在國家/地區的常用字元集 (euckr = 韓國;gb18030 、gb2312 或 gbk = 中華人民共和國;big5 = 台灣;sjis 、ujis 、cp932 或 eucjpms = 日本;ucs2 或 utf8 = 任何地方)。通常,只需要變更用戶端和連線以及結果設定即可。SET NAMES 陳述式會一次變更全部三個。例如 SET NAMES 'big5';
設定正確後,您可以透過編輯 my.cnf 或 my.ini 使其成為永久性設定。例如,您可以新增如下所示的行 [mysqld]
character-set-server=big5
[client]
default-character-set=big5
您的應用程式中使用的 API 設定也可能存在問題;如需更多資訊,請參閱為什麼我的 GUI 前端或瀏覽器無法正確顯示 CJK 字元...?。
|
A.11.3. | 使用 Big5 中文字元集時,我應該注意哪些問題? |
| MySQL 支援 Big5 字元集,這在香港和台灣 (中華民國) 很常見。MySQL big5 字元集實際上是 Microsoft 代碼頁 950,它與原始的 big5 字元集非常相似。 已提出新增 HKSCS 擴充功能的建議。需要此擴充功能的人可能會發現 Bug #13577 的建議修補程式很有趣。 |
A.11.4. | 為什麼日文字元集轉換會失敗? |
| MySQL 支援 sjis 、ujis 、cp932 和 eucjpms 字元集以及 Unicode。常見的需求是在字元集之間進行轉換。例如,可能會有一個 Unix 伺服器 (通常使用 sjis 或 ujis ) 和一個 Windows 用戶端 (通常使用 cp932 )。 在下列轉換表中,ucs2 欄代表來源,而 sjis 、cp932 、ujis 和 eucjpms 欄代表目標;也就是說,最後 4 欄提供當我們使用 CONVERT(ucs2) 或將包含值的 ucs2 欄指派給 sjis 、cp932 、ujis 或 eucjpms 欄時的十六進位結果。
現在考慮下表的部分內容。
這表示 MySQL 會將 非符號 (Unicode U+00AC ) 轉換為 sjis 碼位 0x81CA ,並轉換為 cp932 碼位 3F 。(3F 是問號 (「?」)。當無法執行轉換時,總是會使用此符號。) |
A.11.5. | 如果我想將 SJIS 81CA 轉換為 cp932 ,我該怎麼辦? |
| 我們的答案是:「?」。這有缺點,許多人會偏好「鬆散」轉換,以便使 sjis 中的 81CA (非符號) 變成 cp932 中的 81CA (全形非符號) 。 |
A.11.6. | MySQL 如何表示日圓 (¥ ) 符號? |
| 出現問題是因為某些版本的日文字元集 (sjis 和 euc ) 會將 5C 視為反斜線符號 (\ ,也稱為反斜線),而其他版本則將其視為日圓符號 (¥ )。 MySQL 僅遵循 JIS (日本工業標準) 標準描述的一個版本。在 MySQL 中,5C 永遠是反斜線符號 (\ )。 |
A.11.7. | 在 MySQL 中使用韓文字元集時,我應該注意哪些問題? |
| 理論上,雖然 euckr (Extended Unix Code Korea) 字元集有數個版本,但僅注意到一個問題。我們使用 EUC-KR 的「ASCII」變體,其中碼位 0x5c 是反斜線,即 \ ,而不是 EUC-KR 的「KS-Roman」變體,其中碼位 0x5c 是 韓元符號 (₩ )。這表示您無法將 Unicode U+20A9 轉換為 euckr mysql> SELECT
CONVERT('₩' USING euckr) AS euckr,
HEX(CONVERT('₩' USING euckr)) AS hexeuckr;
+-------+----------+
| euckr | hexeuckr |
+-------+----------+
| ? | 3F |
+-------+----------+
|
A.11.8. | 為什麼我會收到 字串值不正確 錯誤訊息? |
| 要了解問題,請建立一個包含一個 Unicode (ucs2 ) 欄和一個中文 (gb2312 ) 欄的資料表。 mysql> CREATE TABLE ch
(ucs2 CHAR(3) CHARACTER SET ucs2,
gb2312 CHAR(3) CHARACTER SET gb2312);
在非嚴格 SQL 模式下,嘗試將罕見字元 汌 放在這兩個欄中。 mysql> SET sql_mode = '';
mysql> INSERT INTO ch VALUES ('A汌B','A汌B');
Query OK, 1 row affected, 1 warning (0.00 sec)
INSERT 會產生警告。使用下列陳述式查看警告是什麼
mysql> SHOW WARNINGS\G
*************************** 1. row ***************************
Level: Warning
Code: 1366
Message: Incorrect string value: '\xE6\xB1\x8CB' for column 'gb2312' at row 1
因此,這只是關於 gb2312 欄的警告。 mysql> SELECT ucs2,HEX(ucs2),gb2312,HEX(gb2312) FROM ch;
+-------+--------------+--------+-------------+
| ucs2 | HEX(ucs2) | gb2312 | HEX(gb2312) |
+-------+--------------+--------+-------------+
| A汌B | 00416C4C0042 | A?B | 413F42 |
+-------+--------------+--------+-------------+
這裡需要解釋幾件事
如先前所述,汌 字元不在 gb2312 字元集中。 如果您使用的是舊版 MySQL,您可能會看到不同的訊息。 發生警告而不是錯誤,是因為 MySQL 未設定為使用嚴格 SQL 模式。在非嚴格模式下,MySQL 會盡力而為,以獲得最佳的匹配,而不是放棄。在嚴格 SQL 模式下,會將 字串值不正確 訊息當作錯誤而不是警告,並且 INSERT 會失敗。
|
A.11.9. | 為什麼我的 GUI 前端或瀏覽器在使用 Access、PHP 或其他 API 的應用程式中錯誤地顯示 CJK 字元? |
| 使用 mysql 用戶端直接連線到伺服器,並在那裡嘗試相同的查詢。如果 mysql 回應正確,問題可能在於您的應用程式介面需要初始化。使用 mysql,透過語句 SHOW VARIABLES LIKE 'char%'; 告訴您它使用的字元集。如果您使用 Access,您很可能使用 Connector/ODBC 連線。在這種情況下,您應該檢查 設定 Connector/ODBC。例如,如果您使用 big5 ,您應該輸入 SET NAMES 'big5' 。(在這種情況下,不需要 ; 字元。)如果您使用 ASP,您可能需要在程式碼中加入 SET NAMES 。以下是一個過去有效的範例 <%
Session.CodePage=0
Dim strConnection
Dim Conn
strConnection="driver={MySQL ODBC 3.51 Driver};server=server;uid=username;" \
& "pwd=password;database=database;stmt=SET NAMES 'big5';"
Set Conn = Server.CreateObject("ADODB.Connection")
Conn.Open strConnection
%>
同樣地,如果您使用 Connector/NET 時使用了 latin1 以外的任何字元集,您必須在連線字串中指定字元集。請參閱 Connector/NET 連線,以取得更多資訊。 如果您使用 PHP,請嘗試以下操作 <?php
$link = new mysqli($host, $usr, $pwd, $db);
if( mysqli_connect_errno() )
{
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
$link->query("SET NAMES 'utf8'");
?>
在這種情況下,我們使用 SET NAMES 來變更 character_set_client 、character_set_connection 和 character_set_results 。 PHP 應用程式中經常遇到的另一個問題與瀏覽器所做的假設有關。有時新增或變更 <meta> 標籤就足以解決問題:例如,為了確保使用者代理程式將頁面內容解譯為 UTF-8 ,請在 HTML 頁面的 <head> 區段中加入 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 。 如果您使用 Connector/J,請參閱 使用字元集和 Unicode。 |
A.11.10. | 我已升級到 MySQL 8.4。我如何還原到像 MySQL 4.0 那樣的字元集行為? |
| 在 MySQL 4.0 版中,伺服器和用戶端都有一個單一的「全域」字元集,而且要使用哪個字元集的決定是由伺服器管理員決定的。這在 MySQL 4.1 版開始發生了改變。現在發生的是「交握」,如 第 12.4 節「連線字元集與校對」中所述
這樣做的效果是,您無法透過使用 --character-set-server=utf8 啟動 mysqld 來控制用戶端字元集。但是,有些亞洲客戶偏好 MySQL 4.0 的行為。為了能夠保留此行為,我們加入了一個 mysqld 開關 --character-set-client-handshake ,可以使用 --skip-character-set-client-handshake 將其關閉。如果您使用 --skip-character-set-client-handshake 啟動 mysqld,則當用戶端連線時,它會將它想要使用的字元集名稱傳送到伺服器。但是,伺服器會忽略來自用戶端的此請求。 舉例來說,假設您最愛的伺服器字元集是 latin1 。進一步假設用戶端使用 utf8 ,因為這是用戶端作業系統支援的字元集。使用 latin1 作為其預設字元集來啟動伺服器 mysqld --character-set-server=latin1
然後使用預設字元集 utf8 來啟動用戶端 mysql --default-character-set=utf8
可以透過檢視 SHOW VARIABLES 的輸出,來查看產生的設定 mysql> SHOW VARIABLES LIKE 'char%';
+--------------------------+----------------------------------------+
| Variable_name | Value |
+--------------------------+----------------------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | latin1 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | /usr/local/mysql/share/mysql/charsets/ |
+--------------------------+----------------------------------------+
現在停止用戶端,並使用 mysqladmin 停止伺服器。然後再次啟動伺服器,但這次告訴它略過交握,如下所示 mysqld --character-set-server=utf8 --skip-character-set-client-handshake
再次使用預設字元集 utf8 啟動用戶端,然後顯示產生的設定 mysql> SHOW VARIABLES LIKE 'char%';
+--------------------------+----------------------------------------+
| Variable_name | Value |
+--------------------------+----------------------------------------+
| character_set_client | latin1 |
| character_set_connection | latin1 |
| character_set_database | latin1 |
| character_set_filesystem | binary |
| character_set_results | latin1 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | /usr/local/mysql/share/mysql/charsets/ |
+--------------------------+----------------------------------------+
正如您透過比較 SHOW VARIABLES 的不同結果所見,如果使用 --skip-character-set-client-handshake 選項,伺服器會忽略用戶端的初始設定。 |
A.11.11. | 為什麼使用 CJK 字元的某些 LIKE 和 FULLTEXT 搜尋會失敗? |
| 對於 LIKE 搜尋,二進位字串資料行類型(例如 BINARY 和 BLOB )存在一個非常簡單的問題:我們必須知道字元在哪裡結束。對於多位元組字元集,不同的字元可能具有不同的位元組長度。例如,在 utf8 中,A 需要一個位元組,但是 ペ 需要三個位元組,如下所示 +-------------------------+---------------------------+
| OCTET_LENGTH(_utf8 'A') | OCTET_LENGTH(_utf8 'ペ') |
+-------------------------+---------------------------+
| 1 | 3 |
+-------------------------+---------------------------+
如果我們不知道字串中的第一個字元在哪裡結束,我們就不知道第二個字元在哪裡開始,在這種情況下,即使是很簡單的搜尋(例如 LIKE '_A%' )也會失敗。解決方案是使用定義為具有正確 CJK 字元集的非二進位字串資料行類型。例如:mycol TEXT CHARACTER SET sjis 。或者,在比較之前轉換為 CJK 字元集。 這也是 MySQL 無法允許編碼不存在的字元的原因之一。如果它不嚴格拒絕錯誤的輸入,它就無法知道字元在哪裡結束。 對於 FULLTEXT 搜尋,我們必須知道單字在哪裡開始和結束。對於西方語言,這很少成為問題,因為大多數(如果不是全部)西方語言都使用容易識別的單字邊界:空格字元。但是,亞洲文字通常不是這種情況。我們可以採用任意的折衷方法,例如假設所有漢字都代表單字,或者(對於日語)依賴於文法結尾導致的片假名到平假名的變化。但是,唯一確定的解決方案需要一份全面的單字清單,這表示我們必須在伺服器中加入每個支援的亞洲語言的字典。這根本不可行。 |
A.11.12. | 我如何知道字元 X 在所有字元集中是否可用? |
| 大多數簡體中文和基本非半形日文假名都出現在所有 CJK 字元集中。下列預存程序接受 UCS-2 Unicode 字元,將其轉換為其他字元集,並以十六進位顯示結果。 DELIMITER //
CREATE PROCEDURE p_convert(ucs2_char CHAR(1) CHARACTER SET ucs2)
BEGIN
CREATE TABLE tj
(ucs2 CHAR(1) character set ucs2,
utf8 CHAR(1) character set utf8,
big5 CHAR(1) character set big5,
cp932 CHAR(1) character set cp932,
eucjpms CHAR(1) character set eucjpms,
euckr CHAR(1) character set euckr,
gb2312 CHAR(1) character set gb2312,
gbk CHAR(1) character set gbk,
sjis CHAR(1) character set sjis,
ujis CHAR(1) character set ujis);
INSERT INTO tj (ucs2) VALUES (ucs2_char);
UPDATE tj SET utf8=ucs2,
big5=ucs2,
cp932=ucs2,
eucjpms=ucs2,
euckr=ucs2,
gb2312=ucs2,
gbk=ucs2,
sjis=ucs2,
ujis=ucs2;
/* If there are conversion problems, UPDATE produces warnings. */
SELECT hex(ucs2) AS ucs2,
hex(utf8) AS utf8,
hex(big5) AS big5,
hex(cp932) AS cp932,
hex(eucjpms) AS eucjpms,
hex(euckr) AS euckr,
hex(gb2312) AS gb2312,
hex(gbk) AS gbk,
hex(sjis) AS sjis,
hex(ujis) AS ujis
FROM tj;
DROP TABLE tj;
END//
DELIMITER ;
輸入可以是任何單一 ucs2 字元,也可以是該字元的程式碼值(十六進位表示法)。例如,從 Unicode 的 ucs2 編碼和名稱清單 (http://www.unicode.org/Public/UNIDATA/UnicodeData.txt),我們知道片假名 Pe 出現在所有 CJK 字元集中,而且其程式碼值為 X'30DA' 。如果我們使用此值作為 p_convert() 的引數,結果如下所示 mysql> CALL p_convert(X'30DA');
+------+--------+------+-------+---------+-------+--------+------+------+------+
| ucs2 | utf8 | big5 | cp932 | eucjpms | euckr | gb2312 | gbk | sjis | ujis |
+------+--------+------+-------+---------+-------+--------+------+------+------+
| 30DA | E3839A | C772 | 8379 | A5DA | ABDA | A5DA | A5DA | 8379 | A5DA |
+------+--------+------+-------+---------+-------+--------+------+------+------+
由於沒有資料行值是 3F (也就是問號字元 ? ),我們知道每個轉換都成功了。 |
A.11.13. | 為什麼 CJK 字串在 Unicode 中排序不正確?(I) |
| MySQL 舊版中發生的 CJK 排序問題可以透過使用 utf8mb4 字元集和 utf8mb4_ja_0900_as_cs 校對,在 MySQL 8.0 中解決。 |
A.11.14. | 為什麼 CJK 字串在 Unicode 中排序不正確?(II) |
| MySQL 舊版中發生的 CJK 排序問題可以透過使用 utf8mb4 字元集和 utf8mb4_ja_0900_as_cs 校對,在 MySQL 8.0 中解決。 |
A.11.15. | 為什麼我的補充字元被 MySQL 拒絕? |
| 補充字元位於 Unicode 基本多文種平面/平面 0 之外。BMP 字元的程式碼點值介於 U+0000 和 U+FFFF 之間。補充字元的程式碼點值介於 U+10000 和 U+10FFFF 之間。 若要儲存補充字元,您必須使用允許它們的字元集
utf8 和 ucs2 字元集僅支援 BMP 字元。
utf8 字元集只允許最多佔用三個位元組的 UTF-8 字元。這導致了在錯誤 #12600 中找到的報告,我們拒絕此報告,並標示為「不是錯誤」。使用 utf8 時,當 MySQL 遇到它不理解的位元組時,必須截斷輸入字串。否則,不知道錯誤的多位元組字元有多長。
一種可能的解決方法是使用 ucs2 而非 utf8 ,在這種情況下,「錯誤」字元會變更為問號。但是,不會發生截斷。您也可以將資料類型變更為 BLOB 或 BINARY ,它們不會執行有效性檢查。 utf8mb4 、utf16 、utf16le 和 utf32 字元集支援 BMP 字元,以及 BMP 之外的補充字元。
|
A.11.16. | 「CJK」是否應該是「CJKV」? |
| 否。術語「CJKV」(中文、日文、韓文、越南文)指的是包含漢字(最初是中文)的越南字元集。MySQL 支援使用西文字元的現代越南語文字,但不支援使用漢字的舊越南語文字。 從 MySQL 5.6 開始,Unicode 字元集提供了越南語校對,如 第 12.10.1 節「Unicode 字元集」中所述。 |
A.11.17. | MySQL 是否允許在資料庫和資料表名稱中使用 CJK 字元? |
| 是。 |
A.11.18. | 我可以在哪裡找到 MySQL 手冊的中文、日文和韓文翻譯版本? |
| MySQL 5.6 手冊的日文翻譯版本可以從 https://mysqldev.dev.org.tw/doc/ 下載。 |
A.11.19. | 我可以在哪裡取得 MySQL 中 CJK 和相關問題的協助? |
| 可以使用下列資源
|