MySQL 字符集与比较规则

摘要:
请参阅:MySQL的工作原理。儿童字符集#检查字符集显示[喜欢匹配模式]#utf8和utf8mb4有什么区别?验证规则的中间名表示主要应用比较规则的语言,例如utf8_ polish_ Ci在波兰语中表示规则的比较。

参考:《MySQL是怎样运行的》,小孩子

字符集

# 查看字符集

show (character set|charset) [like 匹配的模式];

# utf8(utf8mb3) 与 utf8mb4  有什么不同?

utf8(utf8mb3):用 1-3 字节表示一个字符 
utf8mb4:用 1-4 字节表示一个字符,支持 emoji 表情哦


# Maxlen 表示该字符集表示一个字符的最大长度(Byte字节数)
MariaDB [(none)]> show character set like "utf8%";
+---------+---------------+--------------------+--------+
| Charset | Description   | Default collation  | Maxlen |
+---------+---------------+--------------------+--------+
| utf8    | UTF-8 Unicode | utf8_general_ci    |      3 |
| utf8mb4 | UTF-8 Unicode | utf8mb4_general_ci |      4 |
+---------+---------------+--------------------+--------+
2 rows in set (0.00 sec)

# 比较重要的字符集 Character Set 及表达一个字符的最大长度 Maxlen
MariaDB [information_schema]> select * from CHARACTER_SETS where CHARACTER_SET_NAME regexp "utf8|latin1|ascii|gb";
+--------------------+----------------------+---------------------------+--------+
| CHARACTER_SET_NAME | DEFAULT_COLLATE_NAME | DESCRIPTION               | MAXLEN |
+--------------------+----------------------+---------------------------+--------+
| latin1             | latin1_swedish_ci    | cp1252 West European      |      1 |
| ascii              | ascii_general_ci     | US ASCII                  |      1 |
| gb2312             | gb2312_chinese_ci    | GB2312 Simplified Chinese |      2 |
| gbk                | gbk_chinese_ci       | GBK Simplified Chinese    |      2 |
| utf8               | utf8_general_ci      | UTF-8 Unicode             |      3 |
| utf8mb4            | utf8mb4_general_ci   | UTF-8 Unicode             |      4 |
+--------------------+----------------------+---------------------------+--------+
6 rows in set (0.00 sec)

比较规则

# 查询 Utf8 字符集下的校验规则
MariaDB [information_schema]> SHOW COLLATION LIKE 'utf8\_%';
+--------------------------+---------+-----+---------+----------+---------+
| Collation                | Charset | Id  | Default | Compiled | Sortlen |
+--------------------------+---------+-----+---------+----------+---------+
| utf8_general_ci          | utf8    |  33 | Yes     | Yes      |       1 |
| utf8_bin                 | utf8    |  83 |         | Yes      |       1 |
| utf8_unicode_ci          | utf8    | 192 |         | Yes      |       8 |
| utf8_icelandic_ci        | utf8    | 193 |         | Yes      |       8 |
| utf8_latvian_ci          | utf8    | 194 |         | Yes      |       8 |
| utf8_romanian_ci         | utf8    | 195 |         | Yes      |       8 |
| utf8_slovenian_ci        | utf8    | 196 |         | Yes      |       8 |
| utf8_polish_ci           | utf8    | 197 |         | Yes      |       8 |
| utf8_estonian_ci         | utf8    | 198 |         | Yes      |       8 |
| utf8_spanish_ci          | utf8    | 199 |         | Yes      |       8 |
| utf8_swedish_ci          | utf8    | 200 |         | Yes      |       8 |
| utf8_turkish_ci          | utf8    | 201 |         | Yes      |       8 |
| utf8_czech_ci            | utf8    | 202 |         | Yes      |       8 |
| utf8_danish_ci           | utf8    | 203 |         | Yes      |       8 |
| utf8_lithuanian_ci       | utf8    | 204 |         | Yes      |       8 |
| utf8_slovak_ci           | utf8    | 205 |         | Yes      |       8 |
| utf8_spanish2_ci         | utf8    | 206 |         | Yes      |       8 |
| utf8_roman_ci            | utf8    | 207 |         | Yes      |       8 |
| utf8_persian_ci          | utf8    | 208 |         | Yes      |       8 |
| utf8_esperanto_ci        | utf8    | 209 |         | Yes      |       8 |
| utf8_hungarian_ci        | utf8    | 210 |         | Yes      |       8 |
| utf8_sinhala_ci          | utf8    | 211 |         | Yes      |       8 |
| utf8_croatian_ci         | utf8    | 213 |         | Yes      |       8 |
| utf8_general_mysql500_ci | utf8    | 223 |         | Yes      |       1 |
+--------------------------+---------+-----+---------+----------+---------+
24 rows in set (0.00 sec)

校验规则前缀名表达含义:前缀名表示着所属字符集 。

校验规则中间名表达含义:中间名表示着该比较规则主要作用于哪种语言,比如utf8_polish_ci表示以波兰语的规则比较 。

校验规则后缀名表达含义:

后缀英文释义描述
_aiaccent insensitive不区分重音
_asaccent sensitive区分重音
_cicase insensitive不区分大小写
_cscase sensitive区分大小写
_binbinary以二进制方式比较

字符集 & 比较规则 的级别

MySQL有4个级别的字符集和比较规则,分别是:

  • 服务器级别
  • 数据库级别
  • 表级别
  • 列级别

服务器级别

# 查看服务器级别字符集 
MariaDB [(none)]> show variables like "character_set_server";
+----------------------+--------+
| Variable_name        | Value  |
+----------------------+--------+
| character_set_server | latin1 |
+----------------------+--------+
1 row in set (0.00 sec)
# 查看服务器级别字符校验规则
MariaDB [(none)]> show variables like "collation_server";
+------------------+-------------------+
| Variable_name    | Value             |
+------------------+-------------------+
| collation_server | latin1_swedish_ci |
+------------------+-------------------+
1 row in set (0.00 sec)
# 更改服务器级别字符集
MariaDB [(none)]> set character_set_server="utf8";
Query OK, 0 rows affected (0.00 sec)
# 更改服务器级别校验规则
MariaDB [(none)]> set collation_server="utf8_general_ci";
Query OK, 0 rows affected (0.00 sec)
# 验证结果(字符集)
MariaDB [(none)]> show variables like "character_set_server";
+----------------------+-------+
| Variable_name        | Value |
+----------------------+-------+
| character_set_server | utf8  |
+----------------------+-------+
1 row in set (0.00 sec)
# 验证结果(校验规则)
MariaDB [(none)]> show variables like "collation_server";
+------------------+-----------------+
| Variable_name    | Value           |
+------------------+-----------------+
| collation_server | utf8_general_ci |
+------------------+-----------------+
1 row in set (0.00 sec)

数据库级别

创建数据库时,若不指定数据库级别的字符集和校验规则,则默认使用以下字符集和校验规则:

# 无非还是环境变量啦,想修改 Set 下就好
MariaDB [(none)]> show variables like "character_set_database";
+------------------------+--------+
| Variable_name          | Value  |
+------------------------+--------+
| character_set_database | latin1 |
+------------------------+--------+
1 row in set (0.00 sec)

MariaDB [(none)]> show variables like "collation_database";
+--------------------+-------------------+
| Variable_name      | Value             |
+--------------------+-------------------+
| collation_database | latin1_swedish_ci |
+--------------------+-------------------+
1 row in set (0.00 sec)


# ============================== 关于 Set ================================= #
# 以下命令只能改变当前 Session 的环境变量,当前的 Session 即刻生效,其他 Session 不会生效
MariaDB [(none)]> set character_set_database="utf8";
# 以下命令可以改变全局 Session 的环境变量,但已经开启的 Session 不会生效(新开启的 Session 会生效)
MariaDB [(none)]> set global character_set_database="utf8";
# =================== 想修改某个变量时,两个命令全部执行一次即可 ========================= #
# =================== 以上变量在 MySQL 重启后失效  ============================ #
# =================== 修改配置文件后重启即可永久生效 ============================ #

如果不想受制于环境变量,那么就在创建数据库时指定下字符集与校验规则吧:

# 举个反例,utf8mb4_general_ci 无法适配 utf8 字符集(utf8 字符集中没有此校验规则)
MariaDB [(none)]> create database forethan character set utf8 collate utf8mb4_general_ci;
ERROR 1253 (42000): COLLATION 'utf8mb4_general_ci' is not valid for CHARACTER SET 'utf8'
# 指定字符集创建一个新的数据库 forethan
MariaDB [(none)]> create database forethan character set utf8mb4 collate utf8mb4_general_ci;
Query OK, 1 row affected (0.00 sec)
# 看看建库语句
MariaDB [(none)]> show create database forethan;
+----------+----------------------------------------------------------------------+
| Database | Create Database                                                      |
+----------+----------------------------------------------------------------------+
| forethan | CREATE DATABASE `forethan` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ |
+----------+----------------------------------------------------------------------+
1 row in set (0.00 sec)
# 指定字符集创建一个新的数据库 forkiki
MariaDB [(none)]> create database forkiki character set gb2312 collate gb2312_chinese_ci;
Query OK, 1 row affected (0.00 sec)
# 看看建库语句
MariaDB [(none)]> show create database forkiki;
+----------+--------------------------------------------------------------------+
| Database | Create Database                                                    |
+----------+--------------------------------------------------------------------+
| forkiki  | CREATE DATABASE `forkiki` /*!40100 DEFAULT CHARACTER SET gb2312 */ |
+----------+--------------------------------------------------------------------+
1 row in set (0.00 sec)

表级别

Create Table 表名 (列的信息)
    [[DEFAULT] CHARACTER SET 字符集名称]
    [COLLATE 比较规则名称];

Alter Table 表名
    [[DEFAULT] CHARACTER SET 字符集名称]
    [COLLATE 比较规则名称];
    
# Example:

mysql> CREATE TABLE t(
    ->     col VARCHAR(10)
    -> # 设置表级别的字符集和比较规则
    -> ) CHARACTER SET utf8 COLLATE utf8_general_ci;	
Query OK, 0 rows affected (0.03 sec)

如果建表时,不指定表的字符集和比较规则,则继承数据库级别的字符集和比较规则 。

列级别

同一个表中,不同列可以有不同的字符集和比较规则

Create Table 表名(
	列名 字符串类型 [CHARACTER SET 字符集名称] [COLLATE 比较规则名称],
    列名 ......
);

Alter Table 表名 Modify 列名 字符串类型  
	[CHARACTER SET 字符集名称] 
	[COLLATE 比较规则名称];
	
	
# Example:

mysql> ALTER TABLE t MODIFY col VARCHAR(10) CHARACTER SET gbk COLLATE gbk_chinese_ci;
Query OK, 0 rows affected (0.04 sec)
Records: 0  Duplicates: 0  Warnings: 0

每个级别中,仅修改字符集或者比较规则

由于字符集和比较规则是互相有联系的,如果我们只修改了字符集,比较规则也会跟着变化,如果只修改了比较规则,字符集也会跟着变化,具体规则如下:

  • 只修改字符集,则比较规则将变为修改后的字符集默认的比较规则。
  • 只修改比较规则,则字符集将变为修改后的比较规则对应的字符集。

MySQL 中的字符集的转换

那么,在 MySQL 客户端发起请求 -> MySQL 服务端 -> MySQL 客户端 这条流程中,字符集都经过了哪些转换?

如上所述,一次完整的转换过程中,会被 MySQL 三个系统变量所影响:

系统变量描述
character_set_client服务器解码请求时使用的字符集
character_set_connection服务器处理请求时会把请求字符串从character_set_client转为character_set_connection
character_set_results服务器向客户端返回数据时使用的字符集

一次请求被 MySQL 服务端处理

MySQL 字符集与比较规则第1张

服务器会默认认为客户端操作系统使用 character_set_client & character_set_results 字符集,如果不同:

  • 如果客户端操作系统字符集和 character_set_client 不一致,服务器可能无法理解我们发送的请求,更别谈处理这个请求了

  • 如果客户端操作系统字符集和 character_set_results 不一致,那么返回到客户端的界面的就会使乱码

图中的 character_set_connection 就没多重要,但是一定要注意,该字符集包含的字符范围一定涵盖请求中的字符,要不然会导致有的字符无法使用character_set_connection代表的字符集进行编码。比如你把character_set_client设置为utf8,把character_set_connection设置成ascii,那么此时你如果从客户端发送一个汉字到服务器,那么服务器无法使用ascii字符集来编码这个汉字,就会向用户发出一个警告 。

MySQL中从发送请求到返回结果过程里发生的各种字符集转换,但是为啥要转来转去的呢?不晕么?

所以我们通常都把 character_set_clientcharacter_set_connectioncharacter_set_results 这三个系统变量设置成和客户端使用的字符集一致的情况,这样减少了很多无谓的字符集转换。为了方便我们设置,MySQL提供了一条非常简便的语句:

SET NAMES 字符集名;

这一条语句产生的效果和我们执行这3条的效果是一样的:

SET character_set_client = 字符集名;
SET character_set_connection = 字符集名;
SET character_set_results = 字符集名;
小贴士:

如果你使用的是Windows系统,那应该设置成gbk。

另外,如果你想在启动客户端的时候就把character_set_clientcharacter_set_connectioncharacter_set_results这三个系统变量的值设置成一样的,那我们可以在启动客户端的时候指定一个叫default-character-set的启动选项,比如在配置文件里可以这么写:

[client]
default-character-set=utf8

比较规则的含义

比较规则是对于字符集中的字符比较大小的一种规则,又称为排序规则、校验规则 。

t的列col使用的字符集是gbk,使用的比较规则是gbk_chinese_ci,我们向里边插入几条记录:

-- 确认使用的比较规则是 gbk_chinese_ci
mysql> ALTER TABLE t MODIFY col VARCHAR(10) COLLATE gbk_chinese_ci;
Query OK, 0 rows affected (0.00 sec)
Records: 0  Duplicates: 0  Warnings: 0

-- 插入实验数据
mysql> INSERT INTO t(col) VALUES('a'), ('b'), ('A'), ('B');
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql>

我们查询的时候按照t列排序一下:

-- 默认排序结果
mysql> SELECT * FROM t ORDER BY col;
+------+
| col  |
+------+
| a    |
| A    |
| b    |
| B    |
+------+
4 rows in set (0.00 sec)

可以看到在默认的比较规则gbk_chinese_ci中是不区分大小写的,我们现在把列col的比较规则修改为gbk_bin

-- 更改比较规则为 gbk_bin
mysql> ALTER TABLE t MODIFY col VARCHAR(10) COLLATE gbk_bin;
Query OK, 4 rows affected (0.02 sec)
Records: 4  Duplicates: 0  Warnings: 0

由于gbk_bin是直接比较字符的编码,所以是区分大小写的,我们再看一下排序后的查询结果:

-- 默认排序结果
mysql> SELECT * FROM t ORDER BY col;
+------+
| s    |
+------+
| A    |
| B    |
| a    |
| b    |
+------+
4 rows in set (0.00 sec)

mysql>

ALTER 语句中的 CHANGE 与 MODIFY

-- CHANGE ~ 既可以更改列名,也可以更改列的类型
ALTER TABLE project_list
CHANGE COLUMN descriptionofproj proj_desc VARCHAR(100),
CHANGE COLUMN contractoronjob con_name VARCHAR(30);


-- MODIFY ~ 使用它可以只更改列的类型
ALTER TABLE project_list
MODIFY COLUMN proj_desc VACHAR(120);

总结:
①. — 既更改列名也更改类型,用 CHANGE

②. — 只修改类型,用 MODIFY

总结

①. — 字符集`指的是某个字符范围的编码规则。

②. — 比较规则是针对某个字符集中的字符比较大小的一种规则。

③. — 在MySQL中,一个字符集可以有若干种比较规则,其中有一个默认的比较规则,一个比较规则必须对应一个字符集。

④. — 查看MySQL中查看支持的字符集和比较规则的语句如下:

SHOW (CHARACTER SET|CHARSET) [LIKE 匹配的模式];
SHOW COLLATION [LIKE 匹配的模式];

⑤. — MySQL有四个级别的字符集和比较规则

  • 服务器级别

    character_set_server表示服务器级别的字符集,collation_server表示服务器级别的比较规则。

  • 数据库级别

    创建和修改数据库时可以指定字符集和比较规则:

    CREATE DATABASE 数据库名
        [[DEFAULT] CHARACTER SET 字符集名称]
        [[DEFAULT] COLLATE 比较规则名称];
      
    ALTER DATABASE 数据库名
        [[DEFAULT] CHARACTER SET 字符集名称]
        [[DEFAULT] COLLATE 比较规则名称];
    

    character_set_database表示当前数据库的字符集,collation_database表示当前默认数据库的比较规则,这两个系统变量是只读的,不能修改。如果没有指定当前默认数据库,则变量与相应的服务器级系统变量具有相同的值。

  • 表级别

    创建和修改表的时候指定表的字符集和比较规则:

    CREATE TABLE 表名 (列的信息)
        [[DEFAULT] CHARACTER SET 字符集名称]
        [COLLATE 比较规则名称]];
      
    ALTER TABLE 表名
        [[DEFAULT] CHARACTER SET 字符集名称]
        [COLLATE 比较规则名称];
    
  • 列级别

    创建和修改列定义的时候可以指定该列的字符集和比较规则:

    CREATE TABLE 表名(
        列名 字符串类型 [CHARACTER SET 字符集名称] [COLLATE 比较规则名称],
        其他列...
    );
      
    ALTER TABLE 表名 MODIFY 列名 字符串类型 [CHARACTER SET 字符集名称] [COLLATE 比较规则名称];
    
  1. 从发送请求到接收结果过程中发生的字符集转换:

    • 客户端使用操作系统的字符集编码请求字符串,向服务器发送的是经过编码的一个字节串。
    • 服务器将客户端发送来的字节串采用character_set_client代表的字符集进行解码,将解码后的字符串再按照character_set_connection代表的字符集进行编码。
    • 如果character_set_connection代表的字符集和具体操作的列使用的字符集一致,则直接进行相应操作,否则的话需要将请求中的字符串从character_set_connection代表的字符集转换为具体操作的列使用的字符集之后再进行操作。
    • 将从某个列获取到的字节串从该列使用的字符集转换为character_set_results代表的字符集后发送到客户端。
    • 客户端使用操作系统的字符集解析收到的结果集字节串。

    在这个过程中各个系统变量的含义如下:

    系统变量描述
    character_set_client服务器解码请求时使用的字符集
    character_set_connection服务器处理请求时会把请求字符串从character_set_client转为character_set_connection
    character_set_results服务器向客户端返回数据时使用的字符集

    一般情况下要使用保持这三个变量的值和客户端使用的字符集相同。

  2. 比较规则的作用通常体现比较字符串大小的表达式以及对某个字符串列进行排序中。

免责声明:文章转载自《MySQL 字符集与比较规则》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇logback使用配置详解(原创)CheckTool:CRC校验、累加和校验、异或和校验专业校验工具V1.1下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

[MySQL] mysql地理位置服务geometry字段类型

这个字段类型是mysql5.7新增的功能,主要就是解决坐标存储和距离计算的常见问题 创建表:CREATE TABLE `service` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`name` varchar(128) NOT NULL DEFAULT '',`content` varchar(128) NOT NU...

MySQL8.0新特性

MySQL8.0新特性本次的版本更新,在功能上主要有以下6点: 账户与安全 优化器索引 通用表表达式 窗口函数 InnoDB 增强 JSON 增强 一、账户与安全 1.用户的创建与授权   在MySQL5.7的版本:   > grant all privileges on *.* to '用户名'@'主机' identified by '密码...

Mysql 批处理多条sql语句

package cn.itcast.demo; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.Statement; import org.junit.Test; import cn.it...

kali系统网站部署笔记

网站放在 其他位置----计算机------var-----www----html 首先启动nginx service nginx start   然后访问127.0.0.1 就会看到Apache正在工作 启动mysql数据库 service mysql start 接着用 mysql -u root -p 连接mysql 用户名:root 密码:1234...

VMware虚拟机里centos7下安装mysql5.6并授权远程连接Navicat

这节来安装Mysql5.6,并远程授权连接本地windows的Navicat,可以根据以下步骤安装。此文章为自己收藏,必要时拿出来直接用的,有需要的友友可以查看查看的。文章图片有借助于网络的。 1.新开的云服务器,需要检测系统是否自带安装mysql # yum list installed | grep mysql 2.如果发现有系统自带mysql,果断这...

jira中使用eazyBI

参考:https://docs.eazybi.com/eazybijira/set-up-and-administer/set-up-and-administer-for-jira-server/installation-and-setup 安装前的清单 Jira内存设置 在安装eazyBI之前,请检查您当前的Jira内存设置。如果您的Jira服务器没有足...