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 hexadecimal-value ) 時,您是否會得到 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 欄代表目的地;也就是說,當我們使用 CONVERT(ucs2) 或將包含值的 ucs2 欄指派給 sjis 、cp932 、ujis 或 eucjpms 欄時,最後 4 個欄會提供十六進位結果。
現在請考慮表格的以下部分。
這表示 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 (延伸 Unix 程式碼韓國) 字元集有多個版本,但只注意到一個問題。我們使用 EUC-KR 的「ASCII」變體,其中程式碼點 0x5c 是反斜線,也就是 \ ,而不是 EUC-KR 的「KS-Roman」變體,其中程式碼點 0x5c 是 WON SIGN (₩ )。這表示您無法將 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 9.0。我如何還原為像 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 8.0 開始,可以使用 utf8mb4 字元集和 utf8mb4_ja_0900_as_cs 校對來解決舊版 MySQL 中發生的 CJK 排序問題。 |
A.11.14。 | 為什麼 CJK 字串在 Unicode 中排序不正確? (II) |
| 從 MySQL 8.0 開始,可以使用 utf8mb4 字元集和 utf8mb4_ja_0900_as_cs 校對來解決舊版 MySQL 中發生的 CJK 排序問題。 |
A.11.15。 | 為什麼我的補充字元被 MySQL 拒絕? |
| 補充字元位於 Unicode 基本多語文平面/平面 0 之外。BMP 字元的程式碼點值介於 U+0000 和 U+FFFF 之間。補充字元的程式碼點值介於 U+10000 和 U+10FFFF 之間。 若要儲存補充字元,您必須使用允許它們的字元集
utf8 和 ucs2 字元集僅支援 BMP 字元。
utf8 字元集僅允許占用最多三個位元組的 UTF-8 字元。這導致了諸如 Bug #12600 中發現的報告,我們拒絕了該報告,認為「不是錯誤」。使用 utf8 ,MySQL 遇到它不理解的位元組時,必須截斷輸入字串。否則,就不知道錯誤的多位元組字元有多長。
一個可能的解決方法是使用 ucs2 而不是 utf8 ,在這種情況下,「錯誤」的字元會被更改為問號。但是,不會發生截斷。您也可以將資料類型更改為 BLOB 或 BINARY ,它們不會執行任何有效性檢查。 utf8mb4 、utf16 、utf16le 和 utf32 字元集支援 BMP 字元,以及 BMP 之外的補充字元。
|
A.11.16. | 應該使用 「CJKV」而不是 「CJK」嗎? |
| 不應該。「「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 和相關問題的幫助? |
| 以下資源可用:
|