本文爲mariadb官方手冊:SETTING CHARACTER SETS AND COLLATIONS的譯文。mysql
原文:https://mariadb.com/kb/en/setting-character-sets-and-collations/
我提交到MariaDB官方手冊的譯文:https://mariadb.com/kb/zh-cn/setting-character-sets-and-collations/ sql
在MariaDB中,默認的字符集character set爲latin1,默認的排序規則爲latin1_swedish_ci(但不一樣的發行版可能會不一樣,例如Debian)。字符集和排序規則均可以從server端一直指定到字段級別,client鏈接到server時也能夠指定。當修改字符集但卻沒有指定排序規則時,將老是使用字符集的默認排序規則。數據庫
字符集和排序規則老是級聯向下的,因此當沒有爲字段指定排序規則時,將查找表的排序規則,一樣對於表來講會上查到數據庫,對數據庫來講會上查到server級。所以,可使用極細粒度的字符集和排序規則來控制控制你的數據。函數
每種字符集的默認排序規則可以使用SHOW COLLATION語句查看,例如查找latin2字符集的默認排序規則:ui
SHOW COLLATION LIKE 'latin2%';
+---------------------+---------+----+---------+----------+---------+
| Collation | Charset | Id | Default | Compiled | Sortlen |
+---------------------+---------+----+---------+----------+---------+
| latin2_czech_cs | latin2 | 2 | | Yes | 4 |
| latin2_general_ci | latin2 | 9 | Yes | Yes | 1 |
| latin2_hungarian_ci | latin2 | 21 | | Yes | 1 |
| latin2_croatian_ci | latin2 | 27 | | Yes | 1 |
| latin2_bin | latin2 | 77 | | Yes | 1 |
+---------------------+---------+----+---------+----------+---------+
能夠設置系統變量character_set_server來改變默認的server級的字符集。該變量可使用SET命令在啓動時或動態地設置:spa
SET character_set_server = 'latin2';
相似地,變量collation_server用於設置server級別的默認排序規則。code
SET collation_server = 'latin2_czech_cs';
CREATE DATABASE 和 ALTER DATABASE 語句中包含了可選的字符集、排序規則的設置子句。若是沒有設置字符集、排序規則,它們將使用server級別的默認值。orm
CREATE DATABASE czech_slovak_names CHARACTER SET = 'keybcs2' COLLATE = 'keybcs2_bin';
ALTER DATABASE czech_slovak_names COLLATE = 'keybcs2_general_ci';
使用下面的語句能夠查看數據庫所使用的字符集:server
SHOW CREATE DATABASE czech_slovak_names;
+--------------------+--------------------------------------------------------------------------------+
| Database | Create Database | +--------------------+--------------------------------------------------------------------------------+ | czech_slovak_names | CREATE DATABASE `czech_slovak_names` /*!40100 DEFAULT CHARACTER SET keybcs2 */ | +--------------------+--------------------------------------------------------------------------------+
或者,使用下面的語句能夠查看各數據庫採用的字符集和排序規則:排序
SELECT * FROM INFORMATION_SCHEMA.SCHEMATA;
+--------------+--------------------+----------------------------+------------------------+----------+
| CATALOG_NAME | SCHEMA_NAME | DEFAULT_CHARACTER_SET_NAME | DEFAULT_COLLATION_NAME | SQL_PATH |
+--------------+--------------------+----------------------------+------------------------+----------+
| def | czech_slovak_names | keybcs2 | keybcs2_general_ci | NULL |
| def | information_schema | utf8 | utf8_general_ci | NULL |
| def | mysql | latin1 | latin1_swedish_ci | NULL |
| def | performance_schema | utf8 | utf8_general_ci | NULL |
| def | test | latin1 | latin1_swedish_ci | NULL |
+--------------+--------------------+----------------------------+------------------------+----------+
能夠僅指定排序規則,因爲每種排序規則都對應於一種字符集,所以會同時設置排序規則所對應的字符集。
CREATE DATABASE danish_names COLLATE 'utf8_danish_ci';
SHOW CREATE DATABASE danish_names;
+--------------+----------------------------------------------------------------------------------------------+
| Database | Create Database | +--------------+----------------------------------------------------------------------------------------------+ | danish_names | CREATE DATABASE `danish_names` /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_danish_ci */ | +--------------+----------------------------------------------------------------------------------------------+
儘管能夠動態地設置系統變量character_set_database和collation_database,但它們用於肯定數據庫所使用的默認字符集和排序規則,應該儘可能僅在server端進行設置。
CREATE TABLE 和 ALTER TABLE 語句支持可選的字符集、排序規則設置子句,它們是MariaDB和MySQL對標準SQL語句的擴展。
CREATE TABLE english_names (id INT, name VARCHAR(40)) CHARACTER SET 'utf8' COLLATE 'utf8_icelandic_ci';
若是既沒有指定字符集也沒有指定排序規則,則採用數據庫的默認值。若是僅設置了字符集,將採用字符集的默認排序規則。若是僅設置了排序規則,則排序規則相關聯的字符集也會被設置。
ALTER TABLE table_name CONVERT TO CHARACTER SET charset_name [COLLATE collation_name];
若是沒有指定排序規則,將使用字符集默認的排序規則。
對於VARCHAR或TEXT類型的字段,爲了保證新字段足夠大以可以存儲原字段的大量字符,CONVERT TO CHARACTER SET可能會改變數據類型。
例如,某TEXT類型的字段存儲ascii字符時因爲每一個字符僅佔用一個字節,所以該字段能夠存儲65,535個字符。若是該字段轉換爲UTF8,因爲每一個字符須要3個字節,該字段的數據類型將被轉換爲MEDIUMTEXT類型以便可以存儲全部原字段的字符。
CONVERT TO CHARACTER SET binary將分別轉換CHAR、VARCHAR和TEXT字段爲BINARY、VARBINARY和BLOB,而且以後將再也不具備字符集屬性,或者能夠在之後使用CONVERT TO CHARACTER SET語句來改變該行爲。
爲了不CONVERT TO CHARACTER SET子句改變數據類型,能夠在單獨的字段上使用MODIFY。例如:
ALTER TABLE table_name MODIFY ascii_text_column TEXT CHARACTER SET utf8;
ALTER TABLE table_name MODIFY ascii_varchar_column VARCHAR(M) CHARACTER SET utf8;
一樣能夠爲字段類型爲CHAR、TEXT或VARCHAR的字段設置字符集和排序規則。可使用CREATE TABLE和ALTER TABLE語句進行設置——不像table級別的設置,column級別的設置是標準SQL所支持的。
CREATE TABLE european_names ( croatian_names VARCHAR(40) COLLATE 'cp1250_croatian_ci', greek_names VARCHAR(40) CHARACTER SET 'greek');
若是既沒有指定字符集也沒有指定排序規則,將使用表的默認值。若是僅設置了字符集,排序規則將使用字符集的默認排序規則,若是僅設置了排序規則,則其對應的字符集也會被設置。
當使用ALTER TABLE改變字段的字符集時,須要確保字符集能夠和已有數據兼容。MariaDB將盡量地一一映射轉換字符數據,但沒法轉換的數據可能會亂碼丟失。 可使用SHOW CREATE TABLE語句,或者查詢INFORMATION_SCHEMA數據庫來查看字段的字符集和排序規則所採用的值。
SHOW CREATE TABLE european_names\G *************************** 1. row *************************** Table: european_names Create Table: CREATE TABLE `european_names` ( `croatian_names` varchar(40) CHARACTER SET cp1250 COLLATE cp1250_croatian_ci DEFAULT NULL, `greek_names` varchar(40) CHARACTER SET greek DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_danish_ci SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME LIKE 'european%'\G *************************** 1. row *************************** TABLE_CATALOG: def TABLE_SCHEMA: danish_names TABLE_NAME: european_names COLUMN_NAME: croatian_names ORDINAL_POSITION: 1 COLUMN_DEFAULT: NULL IS_NULLABLE: YES DATA_TYPE: varchar CHARACTER_MAXIMUM_LENGTH: 40 CHARACTER_OCTET_LENGTH: 40 NUMERIC_PRECISION: NULL NUMERIC_SCALE: NULL DATETIME_PRECISION: NULL CHARACTER_SET_NAME: cp1250 COLLATION_NAME: cp1250_croatian_ci COLUMN_TYPE: varchar(40) COLUMN_KEY: EXTRA: PRIVILEGES: select,insert,update,references COLUMN_COMMENT: *************************** 2. row *************************** TABLE_CATALOG: def TABLE_SCHEMA: danish_names TABLE_NAME: european_names COLUMN_NAME: greek_names ORDINAL_POSITION: 2 COLUMN_DEFAULT: NULL IS_NULLABLE: YES DATA_TYPE: varchar CHARACTER_MAXIMUM_LENGTH: 40 CHARACTER_OCTET_LENGTH: 40 NUMERIC_PRECISION: NULL NUMERIC_SCALE: NULL DATETIME_PRECISION: NULL CHARACTER_SET_NAME: greek COLLATION_NAME: greek_general_ci COLUMN_TYPE: varchar(40) COLUMN_KEY: EXTRA: PRIVILEGES: select,insert,update,references COLUMN_COMMENT:
從MariaDB 5.1開始,系統變量character_set_filesystem可用來控制對給定字符串的文件名解析。它會影響的下面語句和函數:
默認狀況下,字符集和排序規則經過系統變量character_set_connection和collation_connection來決定使用的字面符號。可是能夠顯式地指定它們:
[_charset_name]'string' [COLLATE collation_name]
對於沒有字符集introducer的字符集來講,它的字符串符號由系統變量character_set_connection決定。
該查詢:
SELECT CHARSET('a'), @@character_set_connection;
老是會爲兩列返回相同的字符集名稱。
character_set_client和character_set_connection通常會被設置爲相同的值(例如在三次握手期間,或使用SET NAMES進行了設置)。但容許設置爲不一樣值。
設置@@character_set_client和@@character_set_connection爲不一樣的值時可能頗有用處:
示例 1:
假設咱們在utf8的數據庫中建立下面的表:
CREATE TABLE t1 (a VARCHAR(10)) CHARACTER SET utf8 COLLATE utf8_general_ci;
INSERT INTO t1 VALUES ('oe'),('ö');
如今使用"mysql.exe"鏈接,它會使用DOS的字符集(西歐的機器上是cp850),若是想要根據德國電話簿規則獲取等於"ö"的全部記錄。
使用下面的語句:
SET @@character_set_client=cp850, @@character_set_connection=utf8;
SELECT a FROM t1 WHERE a='ö' COLLATE utf8_german2_ci;
它將返回:
+------+
| a |
+------+
| oe |
| ö |
+------+
工做方式以下:
注意,若是重寫爲以下腳本:
SET NAMES cp850;
SELECT a FROM t1 WHERE a='ö' COLLATE utf8_german2_ci;
將報錯:
ERROR 1253 (42000): COLLATION 'utf8_german2_ci' is not valid for CHARACTER SET 'cp850'
由於:
示例 2:
繼續假設咱們的數據庫爲utf8,並使用西歐機器上的"mysql.exe"進行鏈接。
咱們這樣作:
SET @@character_set_client=cp850, @@character_set_connection=utf8;
CREATE TABLE t2 AS SELECT 'ö';
這將會建立一張包含VARCHAR(1) CHARACTER SET utf8字段類型的表。
注意,若是查詢重寫爲:
SET NAMES cp850;
CREATE TABLE t2 AS SELECT 'ö';
建立的表中的字段將爲VARCHAR(1) CHARACTER SET cp850類型,這可能不是咱們所指望的。
一樣, 可使用前綴N或n來轉換文本字符爲國際字符集(MariaDB中爲utf8)。
例如:
SELECT _latin2 'Müller';
+-----------+
| MĂźller |
+-----------+
| MĂźller |
+-----------+
SELECT CHARSET(N'a string');
+----------------------+
| CHARSET(N'a string') |
+----------------------+
| utf8 |
+----------------------+
SELECT 'Mueller' = 'Müller' COLLATE 'latin1_german2_ci';
+---------------------------------------------------+
| 'Mueller' = 'Müller' COLLATE 'latin1_german2_ci' |
+---------------------------------------------------+
| 1 |
+---------------------------------------------------+
當建立存儲過程或視圖時,其內出現的文本字符默認使用系統變量character_set_connection和collation_connection指定的字符集和排序規則。可使用SHOW CREATE語句獲取所使用的值。要改變已存在存儲過程、視圖中的文本字符的字符集,須要刪除存儲程序而後重建。
對於存儲過程的參數和返回值,能夠經過CHARACTER SET和COLLATE子句來指定其使用的字符集和排序規則。在MariaDB 5.5以前不支持指定排序規則。
下面的示例中展現了建立存儲程序時所使用的字符集和排序規則。
SET @@local.character_set_connection='latin1';
DELIMITER ||
CREATE PROCEDURE `test`.`x`() BEGIN SELECT CHARSET('x');
END;
||
Query OK, 0 rows affected (0.00 sec)
DELIMITER ;
SET @@local.character_set_connection='utf8';
CALL `test`.`x`();
+--------------+
| CHARSET('x') |
+--------------+
| latin1 |
+--------------+
下面的示例中展現瞭如何指定函數的參數和返回值的字符集和排序規則:
CREATE FUNCTION `test`.`y`(`str` TEXT CHARACTER SET utf8 COLLATE utf8_bin) RETURNS TEXT CHARACTER SET latin1 COLLATE latin1_bin BEGIN SET @param_coll = COLLATION(`str`);
RETURN `str`;
END;
-- 返回值的排序規則:
SELECT COLLATION(`test`.`y`('Hello, planet!'));
+-----------------------------------------+
| COLLATION(`test`.`y`('Hello, planet!')) |
+-----------------------------------------+
| latin1_bin |
+-----------------------------------------+
-- 參數的排序規則:
SELECT @param_coll;
+-------------+
| @param_coll |
+-------------+
| utf8_bin |
+-------------+
示例:更改默認的字符集爲UTF-8
要改變默認的字符集latin1爲UTF-8,須要在配置文件my.cnf中進行以下設置:
[client]
...
default-character-set=utf8 ... [mysql] ... default-character-set=utf8 ... [mysqld] ... collation-server = utf8_unicode_ci init-connect='SET NAMES utf8' character-set-server = utf8 ...
注意,選項default-character-set是一個客戶端選項,而非服務端選項。