翻譯:MariaDB字符集和排序規則


本文為mariadb官方手冊:SETTING CHARACTER SETS AND COLLATIONS的譯文。

原文:https://mariadb.com/kb/en/setting-character-sets-and-collations/
我提交到MariaDB官方手冊的譯文:https://mariadb.com/kb/zh-cn/setting-character-sets-and-collations/

在MariaDB中,默認的字符集character set為latin1,默認的排序規則為latin1_swedish_ci(但不同的發行版可能會不同,例如Debian)。字符集和排序規則都可以從server端一直指定到字段級別,client連接到server時也可以指定。當修改字符集但卻沒有指定排序規則時,將總是使用字符集的默認排序規則。

字符集和排序規則總是級聯向下的,所以當沒有為字段指定排序規則時,將查找表的排序規則,同樣對於表來說會上查到數據庫,對數據庫來說會上查到server級。因此,可以使用極細粒度的字符集和排序規則來控制控制你的數據。

每種字符集的默認排序規則可使用SHOW COLLATION語句查看,例如查找latin2字符集的默認排序規則:

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 |
+---------------------+---------+----+---------+----------+---------+

Server級別

可以設置系統變量character_set_server來改變默認的server級的字符集。該變量可以使用SET命令在啟動時或動態地設置:

SET character_set_server = 'latin2';

類似地,變量collation_server用於設置server級別的默認排序規則。

SET collation_server = 'latin2_czech_cs';

Database級別

CREATE DATABASE 和 ALTER DATABASE 語句中包含了可選的字符集、排序規則的設置子句。如果沒有設置字符集、排序規則,它們將使用server級別的默認值。

CREATE DATABASE czech_slovak_names CHARACTER SET = 'keybcs2' COLLATE = 'keybcs2_bin';
ALTER DATABASE czech_slovak_names COLLATE = 'keybcs2_general_ci';

使用下面的語句可以查看數據庫所使用的字符集:

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端進行設置。

Table級別

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;

Column級別

同樣可以為字段類型為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可用來控制對給定字符串的文件名解析。它會影響的下面語句和函數:

  • SELECT INTO DUMPFILE
  • SELECT INTO OUTFILE
  • LOAD DATA INFILE
  • LOAD XML
  • LOAD_FILE()

字面符號(譯者注:可理解為常量、普通字符串或文本字符)

默認情況下,字符集和排序規則通過系統變量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   |
| ö    |
+------+

工作方式如下:

  1. 客戶端使用cp850發送查詢語句。
  2. 服務端解析查詢語句時,將把'ö'從@@character_set_client (cp850)轉換為@@character_set_connection (utf8)的文本字符。
  3. 服務端對該文本字符應用排序規則"utf8_germal2_ci"。
  4. 服務端使用utf8_german2_ci進行字符比較。

注意,如果重寫為如下腳本:

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的文本字符,而是轉換為cp850的文本字符。
  • 在第3步中,服務端無法對cp850的字符串應用排序規則utf8_german2_ci。

示例 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或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是一個客戶端選項,而非服務端選項。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM