查看完整版本: MySQL 字元集支援【翻譯】

Linux0911 2006-1-22 05:46 AM

MySQL 字元集支援【翻譯】

[url]http://www.enhand.net/blog.php?id=82[/url]

MySQL 4.1 版本改進了對字元集處理的支援。這裡描述的特性是 MySQL 4.1.1 裡已經
實現的。( MySQL 4.1.0 裡有一些,不過不包含這裡的全部特性,並且有的實現也是不同的)

本章討論下面的主題:

·什麼是字元集和 collations?
·The multiple-level default system
·MySQL 4.1 裡新的語法
·Affected functions and operations
·Unicode 支援
·每種特殊字元集和 collation 的含義

現在在 MyISAM, MEMORY (HEAP), 和 (從 MySQL 4.1.2 開始) InnoDB 等存儲引擎裡包含
字元集支援. ISAM 存儲引擎不包含字元集支援; 也沒有計劃加入, 因為 ISAM 已經被
淘汰了


10.1 字元集和 Collations 的一般介紹

一個 character set (字元集) 是一組符號和編碼,而一個 collation 是在一個字元集裡
比較字元的一套規則,讓我們通過一個虛構的字元集例子來說明區別。

假設我們有個四個字母的字母表:`A', `B', `a', `b'.我們給每個字母一個編號:
`A' = 0, `B' = 1, `a' = 2, `b' = 3. 字母`A' 是一個符號,而數字 0 是 `A' 的
encoding(編碼),而這四個字母和他們的編碼合起來就是一個字元集 ( character set )。

現在,假設我們要比較兩個字元串的值,`A' 和`B',最簡單的方法是看編碼,`A' 是 0
而 `B'是 1. 因為 0 比 1 小,我們就說`A' 比 `B' 小。現在,我們就算已經對我們的字元
集使用了一個 collation,collation 是一組規則 ( 在這個例子裡只有一條規則):
"比較編碼".我們把所有可能的 collation 中最簡單的這種叫做 binary collation

但是如果我們想讓大寫字母和小寫字母一樣怎麼辦?那麼我們就得有兩條規則:
(1)把小寫字母`a' 和 `b' 看作跟 `A' 和 `B'相等;
(2)然後比較編碼。
我們稱這是一個 case-insensitive collation(不區分大小寫的 collation).
這比 binary collation 稍微複雜了一點。

在實際生活中,大多數字元集都包含很多字元:不是僅僅`A'和`B' 而是整個字母表,
有時是多個字母表或者東方書寫系統裡幾千的字元,和很多專有符號和標點符。
並且在實際生活中,大多數的 collations 有很多規則:除了不區分大小寫外還有不區分
重音(重音``accent'' 是像在德語裡字元附加的重音符那樣的)和多字元映射。

MySQL 4.1 可以為你做以下事:

·使用各種字元集存儲字元串
·使用各種 collation 比較字元串。
·在同一台伺服器上或者同一個資料庫甚至同一個表中使用不同的字元集和 collation 混合
·允許在任何級別上指明字元集和 collation

在這些方面,MySQL 4.1 不只遠遠比 MySQL 4.0 複雜,也比其他 DBMS 先進很多。不過要想
有效的使用這些新特性,你需要學習哪些字元集和 collation 是可用的,怎樣把他們改成
默認,還有各種字元串運算符如何操作他們。


10.2 MySQL 裡的字元集和 Collations

MySQL 伺服器可支援多個字元集。要列出可用的字元集,使用 SHOW CHARACTER SET 語句:

mysql> SHOW CHARACTER SET;
+----------+-----------------------------+---------------------+
| Charset | Description | Default collation |
+----------+-----------------------------+---------------------+
| big5 | Big5 Traditional Chinese | big5_chinese_ci |
| dec8 | DEC West European | dec8_swedish_ci |
| cp850 | DOS West European | cp850_general_ci |
| hp8 | HP West European | hp8_english_ci |
| koi8r | KOI8-R Relcom Russian | koi8r_general_ci |
| latin1 | ISO 8859-1 West European | latin1_swedish_ci |
| latin2 | ISO 8859-2 Central European | latin2_general_ci |
...

輸出實際上包含另一列,這裡為了讓例子在頁面上顯示更合適,沒顯示出來

任一給出的字元集至少包含一個 collation. 它可能包含多個 collations.

要列出一個字元集的 collations , 使用 SHOW COLLATION 語句. 例如, 要看 latin1
(``ISO-8859-1 West European'') 的 collations, 使用這個語句來找到哪些名字以 latin1
開頭的 collation

mysql> SHOW COLLATION LIKE 'latin1%';
+-------------------+---------+----+---------+----------+---------+
| Collation | Charset | Id | Default | Compiled | Sortlen |
+-------------------+---------+----+---------+----------+---------+
| latin1_german1_ci | latin1 | 5 | | | 0 |
| latin1_swedish_ci | latin1 | 8 | Yes | Yes | 1 |
| latin1_danish_ci | latin1 | 15 | | | 0 |
| latin1_german2_ci | latin1 | 31 | | Yes | 2 |
| latin1_bin | latin1 | 47 | | Yes | 1 |
| latin1_general_ci | latin1 | 48 | | | 0 |
| latin1_general_cs | latin1 | 49 | | | 0 |
| latin1_spanish_ci | latin1 | 94 | | | 0 |
+-------------------+---------+----+---------+----------+---------+

latin1 collations 有下列含義:

Collation 含義
latin1_bin Binary according to latin1 encoding
latin1_danish_ci Danish/Norwegian
latin1_general_ci Multilingual
latin1_general_cs Multilingual, case sensitive
latin1_german1_ci German DIN-1
latin1_german2_ci German DIN-2
latin1_spanish_ci Modern Spanish
latin1_swedish_ci Swedish/Finnish

Collations 有這些一般特性:

·兩個不同字元集沒法擁有同一個collation.
·每個字元集有一個預設 collation. 例如, latin1 的預設 collation 是
latin1_swedish_ci.
·collation 的命名有個約定: 他們由所關聯的字元集的名字打頭,他們通常包含一個
語言名, 並以 _ci (case insensitive 大小寫不敏感),
或者 _cs (case sensitive 大小寫敏感), 或者 _bin ( binary 二進制).


10.3 決定預設字元集和 Collation

有四個級別上的預設字元集和 collation 設置: 伺服器,資料庫,表和連接。下面的描述
可能看起來複雜,不過實踐中得出多級預設設置可以帶來自然而然的結果。


10.3.1 伺服器級字元集和 Collation

MySQL 伺服器有一個伺服器級別的字元集和 collation, 不能為空。

MySQL 這樣決定伺服器級的字元集和 collation
·當伺服器開始按照有效選項設置
·運行期間按照變量

在伺服器級別,決定是很簡單的,依靠你執行 mysqld 時使用的選項來決定伺服器字元集
和 collation。你可以使用--default-character-set 來指定字元集,並且和這個一起
還可以為 collation 加上--default-collation 。如果你不指定字元集,就相當於說
--default-character-set=latin1。如果你只指定了字元集 ( 例如, latin1 ) 但是沒有指定
collation,就相當於
--default-charset=latin1 --default-collation=latin1_swedish_ci
因為 latin1_swedish_ci 是 latin1 字元集的預設 collation, 因此下面三個命令都具有
同樣效果:

shell> mysqld
shell> mysqld --default-character-set=latin1
shell> mysqld --default-character-set=latin1 \
--default-collation=latin1_swedish_ci

有個改變這個設置的方法是重新編譯,如果你想編譯源碼來改變預設的伺服器字元集和
collation,在 configure 使加上參數--with-charset 和 --with-collation ,例如:

shell> ./configure --with-charset=latin1

或者:

shell> ./configure --with-charset=latin1 \

mysqld 和 configure 都會核實字元集/collation 的結合是否有效,如果無效,這兩個
程序都會報錯並中止。

現行伺服器字元集和 collation 是和 character_set_server 和 collation_server
這兩個系統變量的值一樣,這些變量可以在運行時更改


10.3.2 資料庫字元集和 Collation

每個資料庫都有一個資料庫字元集和資料庫 collation, 並且不能為空,CREATE DATABASE
和 ALTER DATABASE 語句有專門指明資料庫字元集和 collation 的可選子句:

CREATE DATABASE db_name
[[DEFAULT] CHARACTER SET charset_name]
[[DEFAULT] COLLATE collation_name]

ALTER DATABASE db_name
[[DEFAULT] CHARACTER SET charset_name]
[[DEFAULT] COLLATE collation_name]

例子:

CREATE DATABASE db_name
DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci;

MySQL 可以這樣選擇資料庫字元集和資料庫 collation:

·如果 CHARACTER SET X 和 COLLATE Y 被指定了, 那麼字元集是 X collation 是 Y.
·如果 CHARACTER SET X 被指定,但是沒有指定 COLLATE, 那麼字元集是 X collation
是預設collation.
·否則, 就用伺服器字元集和伺服器 collation.

MySQL 的 CREATE DATABASE ... DEFAULT CHARACTER SET ... 語法類似於標準 SQL
的 CREATE SCHEMA ... CHARACTER SET ... 語法. 因為這樣, 就可能在同一個MySQL
伺服器上創建具有不同字元集和 collation 的資料庫。

如果在建表的語句裡沒有指定表的字元集和 collation,那麼資料庫字元集和 collation
就作為表的字元集和 collation 的預設值. 它們沒有別的作用。

預設資料庫的字元集和 collation 是和 character_set_database 以及
collation_database 這兩個系統變量的值一樣。 當預設資料庫更改時服務程序會設置
這些變量的值。如果沒有預設資料庫, 變量的值會和配套的伺服器級系統變量
character_set_server 以及 collation_server 的值一致.


10.3.3 表字元集和 Collation

每個表有一個表字元集以及一個表 collation,不能為空。CREATE TABLE 和 ALTER TABLE
語句有可選子句指定表字元集和 collation。

CREATE TABLE tbl_name (column_list)
[DEFAULT CHARACTER SET charset_name [COLLATE collation_name]]

ALTER TABLE tbl_name
[DEFAULT CHARACTER SET charset_name] [COLLATE collation_name]

例子:

CREATE TABLE t1 ( ... )
DEFAULT CHARACTER SET latin1 COLLATE latin1_danish_ci;

MySQL 通過下面的方法選擇表字元集和 collation:

·如果 CHARACTER SET X 和 COLLATE Y 都被指定了, 那麼字元集就是 X collation 是Y
·如果只指定了CHARACTER SET X 而沒有指定 COLLATE, 那麼字元集為 X 並配預設的
collation.
·否則就使用資料庫字元集和 collation.

表字元集和 collation 用來在沒有指定個別列字元集和列 collation 的時候做為它們
的預設值。表字元集和 collation 是 MySQL 的擴展; 在標準 SQL 裡沒有這種東西

10.3.4 列字元集和 Collation

每個``character'' 列 ( 是指列屬性為 CHAR, VARCHAR, 或 TEXT的 ) 都有一個列字元集
和一個列 collation,不能為空。列定義語句有可選子句指定列字元集和 collation:

col_name {CHAR | VARCHAR | TEXT} (col_length)
[CHARACTER SET charset_name [COLLATE collation_name]]

Example:

CREATE TABLE Table1
(
column1 VARCHAR(5) CHARACTER SET latin1 COLLATE latin1_german1_ci
);

MySQL 這樣選擇列字元集和 collation:

·如果 CHARACTER SET X 和 COLLATE Y 都被指定了, 那麼字元集就是 X collation 就是 Y.
·如果指定了 CHARACTER SET X 但沒有指定 COLLATE, 那麼字元集是 X 並配預設的collation.
·否則,就用表字元集和 collation.
CHARACTER SET 和 COLLATE 子句是標準SQL.

10.3.5 字元集和 Collation 分配的例子

下面的例子顯示了 MySQL 怎樣決定預設的字元集和 collation 的值:

例子1:表+列定義

CREATE TABLE t1
(
c1 CHAR(10) CHARACTER SET latin1 COLLATE latin1_german1_ci
) DEFAULT CHARACTER SET latin2 COLLATE latin2_bin;

這裡我們有一個用 latin1 的字元集和 latin1_german1_ci collation 的列。
定義非常明顯,所以很簡單。注意把一個 latin1 的列存到一個 latin2 的表裡不會有問題

例子2:表+列定義

CREATE TABLE t1
(
c1 CHAR(10) CHARACTER SET latin1
) DEFAULT CHARACTER SET latin1 COLLATE latin1_danish_ci;

這次我們有一列是 latin1 字元集加預設的 collation。現在,雖然它看上去很自然,
但是預設的 collation 卻不是從表級繼承而來。事實上,因為 latin1 的預設 collation
始終是 latin1_swedish_ci,所以 c1 列的 collation 是 latin1_swedish_ci (而不是
latin1_danish_ci).

例子3:表+列定義

CREATE TABLE t1
(
c1 CHAR(10)
) DEFAULT CHARACTER SET latin1 COLLATE latin1_danish_ci;

我們有一個預設字元集和預設 collation 的列。在這個環境下,MySQL 向上到表級決定
列字元集和collation。所以,c1 的列字元集是 latin1,它的 collation 是
latin1_danish_ci

例子4:資料庫+表+列定義

CREATE DATABASE d1
DEFAULT CHARACTER SET latin2 COLLATE latin2_czech_ci;
USE d1;
CREATE TABLE t1
(
c1 CHAR(10)
);

我們創建了一個沒有指定列字元集和 collation 的列。我們也沒有指定表級字元集和
collation。在這個條件下,MySQL 向上到資料庫級決定。(資料庫的設置變為表的設置,
之後成為列的設置),所以 c1 的列字元集是 latin2,collation 是 latin2_czech_ci


10.3.6 連接的字元集和Collations

一些字元集和 collation 和用戶對伺服器的作用結合。有些在前面已經提及了:

·伺服器的字元集和 collation 和 character_set_server 及 collation_server 變量
的值一樣
·預設資料庫的字元集和 collation 和 character_set_database 及 collation_database
變量的值一樣.

附加的字元集和 collation 變量被引入用來處理伺服器和客戶端之間連接得通訊。每個
客戶端都有連接相關的字元集和 collation 變量。

想想「連接」是什麼:是你連到伺服器時作的事情。客戶端通過這條連接發送 SQL 語句,
比如查詢,伺服器則通過這條連接給客戶端送回回應,比如查詢結果結果集合,這導致
了客戶端處理字元集和 collation 的一些問題,它們每個都可以按照系統變量來回答:

·當查詢離開客戶端的時候應該是什麼字元集的?伺服器用character_set_client
這個變量來作為客戶端發送查詢所用的字元集
·伺服器端在接收到了查詢以後應該把它翻譯到社麼字元集裡?對於這個,服務程序
用的是 character_set_connection 和 collation_connection 這兩個變量。
它把客戶端送來的查詢從 character_set_client 轉換成 character_set_connection
(除了 latin1 或者 utf8 的字元串)。collation_connection 對於比較字元串非常
重要,對於列值比較字元串是沒有關係的,因為列擁有高優先級
·當服務程序要送回結果集合或者錯誤訊息給客戶端時應該用什麼字元集?
character_set_results 變量指示了這個值,這包括了列值,或者列名等結果數據。

你可以調整這些變量的值,或者就使用預設的(那樣就可以省略這節了)

有兩個語句影響連接字元集設置:
SET NAMES 'charset_name'
SET CHARACTER SET charset_name

SET NAMES 指出客戶端送出的 SQL 語句裡是什麼。因此,SET NAMES 'cp1251' 就告訴服務
程序「下面將要從這個客戶端送來的訊息將是使用 'cp1251' 這個字元集。這也指定了
服務程序送回的結果所用的字元集,(例如如果你用了一個 SELECT 語句它會指出列值
擁有的字元集)

SET NAMES 'x' 語句相當於下面三個語句:

mysql> SET character_set_client = x;
mysql> SET character_set_results = x;
mysql> SET character_set_connection = x;

把character_set_connection 設置成 x 也會把 collation_connection 設置成預設
collation x

SET CHARACTER SET 是類似的,不過是把連接字元集和 collation 設置成那些預設資料庫。
SET CHARACTER SET x 語句相當於這三個語句:

mysql> SET character_set_client = x;
mysql> SET character_set_results = x;
mysql> SET collation_connection = @@collation_database;

當一個客戶連接,它向服務程序發送它想使用的字元集的名字,服務程序把
character_set_client, character_set_results, 和 character_set_connection
這些變量設置成那個字元集(事實上,服務程序使用字元集執行了 SET NAMES 操作)

如果你不想用預設字元集,使用 Mysql 客戶端程序不需要每次啟動時執行 SET NAMES 。
你可以在 mysql 執行語句行加上--default-character-set 這個選項,或者在你的選項
文件裡加上。比如,下面的選項文件設置使你每次執行 mysql 程序時把預設字元集變量
改成 koi8r:

[mysql]
default-character-set=koi8r

例如:假設 column1 定義是 CHAR(5) CHARACTER SET latin2。如果你不用 SET NAMES
或者 SET CHARACTER SET,那麼對於你的 SELECT column1 FROM t 請求,服務程序
會把 column1 的所有值用連接建立時客戶端指定的字元集來回送。另一方面,如果你
用了 SET NAMES 'latin1' or SET CHARACTER SET latin1 ,那麼在送回結果之前,
服務程序會把 latin2 的值轉成 latin1,如果裡面有兩種字元集裡都沒有的字元,
轉化會有損耗。

如果你不希望服務程序作任何轉換,就把 character_set_results 設置成 NULL

mysql> SET character_set_results = NULL;


10.3.7. 字元串文字字元集和 collation

每個字元串文字都有自己的字元集和 collation,不能為空

一個字元串文字可能有一個可選字元集 introducer 和 COLLATION 子句:

[_charset_name]'string' [COLLATE collation_name]

例如:

SELECT 'string';
SELECT _latin1'string';
SELECT _latin1'string' COLLATE latin1_danish_ci;

對於簡單語句 SELECT 'string',字元串的字元集和 collation 是由兩個系統變量
character_set_connection 和 collation_connection 定義的。

_charset_name 表達式正式情況下被叫做 introducer .它告訴分析器「下面的字元串
是使用 X 字元集的。」因為這在以前造成很多人的困擾,我們強調一下 introducer
並不作任何轉換,嚴格來講並不改變字元串的值,只是一個符號。introducer 在
標準 16 進制文字前和數字 16 進制記法前都是合法的(x'literal' 和 0xnnnn),
在?前面也是合法的(當在程序設計語言接口裡使用預備語句時作參數替換)

例如:

SELECT _latin1 x'AABBCC';
SELECT _latin1 0xAABBCC;
SELECT _latin1 ?;

MySQL 這樣決定一個文字的字元集和 collation:

·如果 _X 和 COLLATE Y 都被指定了,那麼字元集就是 X collation 是 Y
·如果 指定了 _X 而沒有指定 COLLATE ,那麼字元集是 X collation 是 X 的預設
collation
·否則,由系統變量 character_set_connection 和 collation_connection 決定字元集
和collation

例如:
·一個字元集是 latin1 而 collation 是 latin1_german1_ci 的字元串:

SELECT _latin1'Muller' COLLATE latin1_german1_ci;

·一個字元集是 latin1 以及其配套預設 collation 的(latin1_swedish_ci)字元串:

SELECT _latin1'Muller';

·一個連接預設字元集和 collation 的字元串:

SELECT 'Muller';

字元集 introducer 和 COLLATE 子句是符合標準 SQL 規則的工具



10.3.8. 在 SQL 語句裡使用 COLLATE

通過 COLLATE 子句,你可以在比較時覆蓋替換掉任何預設 collation, COLLATE 可以用
在 SQL 語句的很多部分裡,這裡是一些例子:

·在 ORDER BY 裡:

SELECT k
FROM t1
ORDER BY k COLLATE latin1_german2_ci;

·在 AS 裡:

SELECT k COLLATE latin1_german2_ci AS k1
FROM t1
ORDER BY k1;

·在 GROUP BY 裡 :

SELECT k
FROM t1
GROUP BY k COLLATE latin1_german2_ci;

·在集合函數裡:

SELECT MAX(k COLLATE latin1_german2_ci)
FROM t1;

·在 DISTINCT 裡

SELECT DISTINCT k COLLATE latin1_german2_ci
FROM t1;

·在 WHERE 裡:

SELECT *
FROM t1
WHERE _latin1 'Muller' COLLATE latin1_german2_ci = k;

·在 HAVING 裡:

SELECT k
FROM t1
GROUP BY k
HAVING k = _latin1 'Muller' COLLATE latin1_german2_ci;


User Comments
Posted by [name withheld] on January 14 2005 2:33pm

在不同的列/表裡:

SELECT t1.k FROM t1 WHERE NOT EXISTS
( SELECT * FROM t2 WHERE t1.k=t2.k COLLATE latin1_german2_ci);

在 collation 之間比較列的時候能夠避免出錯訊息。


10.3.9. COLLATE 子句優先級

COLLATE子句具有高優先級(比||高),所以下面兩個表達式是相同的:

x || y COLLATE z
x || (y COLLATE z)


10.3.10. BINARY 運算

BINARY 運算是 COLLATE 子句的速記法,BINARY 'x' 和 'x' COLLATE y 是相同的,
y 是字元集 'x' 的二元collation 的名字。每個字元集都有二元 collation。例如,
latin1 字元集的 collation 是 latin1_bin,所以如果列 a 是 latin1 字元集,下面
兩個語句有同樣效果:

SELECT * FROM t1 ORDER BY BINARY a;
SELECT * FROM t1 ORDER BY a COLLATE latin1_bin;


10.3.11. 一些決定 collation 比較棘手的情況

在絕大多數查詢裡,MySQL 用什麼 collation 來進行比較操作都是很顯而易見的,例如,
在下面的情況裡,很顯然 collation 應該是「列 x 的列 collation」:

SELECT x FROM T ORDER BY x;
SELECT x FROM T WHERE x = x;
SELECT DISTINCT x FROM T;

但是,當捲入了多操作數時,就很難搞了,例如:

SELECT x FROM T WHERE x = 'Y';

這個查詢應該使用列 x 的 collation 呢,還是使用字元串'Y' 的?

標準 SQL 使用被叫做``coercibility'' 的規則來解決這個問題。本質就是:因為
x 和 'Y' 都有 collation , 優先使用誰的 collation 呢?這很複雜,不過下面的規則能
應付大多數情況:

·一個 COLLATE 子句的 coercibility 是 0 ( 也就是根本不 coercible)

·兩個具有不同 collation 的字元串連結的 coercibility 是 1

·一個列的 collation 的 coercibility 是 2

·一個文字型的 collation 的 coercibility 是 3。

那些規則這樣解決含混:

·使用具有最低 coercibility 值的 collation

·如果兩邊具有相同的 coercibility, 如果兩個 collation 不同那就是錯誤。

例如:

column1 = 'A' 使用 column1 的 collation
column1 = 'A' COLLATE x 使用 'A' 的collation
column1 COLLATE x = 'A' COLLATE y Error

COERCIBILITY() 函數可以用來判斷一個字元串表達式的 coercibility:

mysql> SELECT COERCIBILITY('A' COLLATE latin1_swedish_ci);
-> 0
mysql> SELECT COERCIBILITY('A');
-> 3




User Comments
Posted by Thierry Danard on November 5 2004 10:34pm

對於資料庫引擎來說顯而易見的排序並不是總那麼顯而易見(version 4.1).

一個沒有帶類似於"select concat(mycolumn, '%') from mytable "這樣的排序指令
的查詢在"mycolumn" 和"%"的字元集不相同的情況下不會工作。

在我這裡,整個資料庫使用 UTF-8, 預設情況下, '%' 假設是 latin1,
causing an error to be triggered。



10.3.12. Collations Must Be for the Right Character Set

記得說過每個字元集都有一個或者多個 collation,每個 collation 只和一個字元集關聯。
因此,下面的語句會導致錯誤,因為 latin2_bin 這個 collation 和 latin1 這個字元集
不配套。

mysql> SELECT _latin1 'x' COLLATE latin2_bin;
ERROR 1251: COLLATION 'latin2_bin' is not valid
for CHARACTER SET 'latin1'

在某些情況下,在 MySQL 4.1 前工作的表達式會在 MySQL 4.1 以後的版本失敗,
如果你在帳號裡沒有字元集和 collation 的話。例如,在 MySQL 4.1 前,這個語句
會這樣工作:

mysql> SELECT SUBSTRING_INDEX(USER(),'@',1);
+-------------------------------+
| SUBSTRING_INDEX(USER(),'@',1) |
+-------------------------------+
| root |
+-------------------------------+

升級到 MySQL 4.1 以後,語句失效:

mysql> SELECT SUBSTRING_INDEX(USER(),'@',1);
ERROR 1267 (HY000): Illegal mix of collations
(utf8_general_ci,IMPLICIT) and (latin1_swedish_ci,COERCIBLE)
for operation 'substr_index'

發生這個的原因是 username 使用 utf8 存儲(參看 10.6 節),因此, USER() 函數
和文字型字元串'@'具有不同的字元集(當然也是不同 collation):

mysql> SELECT COLLATION(USER()), COLLATION('@');
+-------------------+-------------------+
| COLLATION(USER()) | COLLATION('@') |
+-------------------+-------------------+
| utf8_general_ci | latin1_swedish_ci |
+-------------------+-------------------+

解決的一個方法是告訴 MySQL 把文字型字元串翻譯成 utf8:

mysql> SELECT SUBSTRING_INDEX(USER(),_utf8'@',1);
+------------------------------------+
| SUBSTRING_INDEX(USER(),_utf8'@',1) |
+------------------------------------+
| root |
+------------------------------------+

另一個方法是把連接的字元集和 collation 改成 utf8,你可以使用 SET NAMES 'utf8'
或者直接設置兩個系統變量 character_set_connection 和 collation_connection
的值來達到這個目的。


10.3.13. Collation 的效果的一個例子

假設表 T 裡的列 X 具有這些 latin1 的列值:

Muffler
Muller
MX Systems
MySQL

並且假設這些列值可以用下列語句找回:

SELECT X FROM T ORDER BY X COLLATE collation_name;

在這張表中列出了不同 collation 的結果值的結果排序

latin1_swedish_ci latin1_german1_ci latin1_german2_ci
Muffler Muffler Muller
MX Systems Muller Muffler
Muller MX Systems MX Systems
MySQL MySQL MySQL

這張表顯示了如果我們在一個 ORDER BY 子句裡使用不同 collation 會有什麼樣的效果
的例子,導致這種不同排序結果的字元是上面有兩個點的 U,在德語裡叫做 U-曲音,
不過我們叫做 U-分音符

·第一列顯示了使用瑞典/芬蘭 collation 規則的 SELECT 的結果,U-分音符
通過 Y 歸類

·第二列顯示了使用德語 DIN-1 規則的 SELECT 語句的結果,U-分音符通過 U 歸類

·第三列顯示了使用德語 DIN-2 規則的 SELECT 語句的結果,U-分音符通過 UE 歸類

三種不同的 collation ,三種不同的結果,這是 MySQL 在這裡的處理。通過使用合適的
collation,你可以選擇你想要的排序次序。
頁: [1]
查看完整版本: MySQL 字元集支援【翻譯】