说明:如果在创建数据库的时候指定了字符编码的话,那在该库下创建的新表会继承该库的字符编码。

一、字符编码作用介绍

在使用数据库服务时,有时在数据库表中输入中文信息条目时,默认经常会遇到字符乱码问题,输入中文信息为什么会出现乱码:

系统字符编码概念解释:

计算机,不能直接存储⽂字,存储的是编码。计算机只能处理⼆进制的数据。a -

对于其它数据,⽐如: 0-9、 a-z、 A-Z,这些字符,我们可以定义⼀套规则来表示。

假如: A-110表示, B-111表示等。

  • ASCII码:00000000 = 0-255 00000001 a 00000010 b

美国发布的,⽤1个字节(8位⼆进制)来表示⼀个字符,共可以表示2^8=256个字符。

美国的国家语⾔是英语,只要能表示0-9、 a-z、 A-Z、特殊符号。

  • ANSI编码:

每个国家为了显示本国的语⾔,都对ASCII码进⾏了扩展。

⽤2个字节(16位⼆进制)来表示⼀个汉字,共可以表示2^16= 65536个汉字。

中国的ANSI编码是GB2312编码(简体),对6763汉字进⾏编码,含600多特殊字符。另外还有GBK(简体)。

⽇本的ANSI编码是JIS编码。

台湾的ANSI编码是BIG5编码(繁体)

  • GBK:

对GB2312进⾏了扩展,⽤来显示罕⻅的、古汉语的汉字。现在已经收录了2.1万左右。并提供了1890个汉字码位。 K的含义就是“扩展”。

  • Unicode编码(统⼀编码): 4个字节 a - 4字节 4k

⽤4个字节(32位⼆进制)来表示⼀个字符,想法不错,但效率太低。例如,字⺟A⽤ASCII表示的话⼀个字节就够, 可⽤Unicode编码的话,得⽤4个字节表示,造成了空间的极⼤浪费。

```tiki wiki A的Unicode编码是:0000 0000 0000 00000000 0000 0100 0000

- UTF-8(Unicode Transform Format)编码:     11111100000     00000011111

根据字符的不同,选择其编码的⻓度。⽐如:⼀个字符A1个字节表示,⼀个汉字⽤2个字节表示。
毫⽆疑问,开发中,都⽤UTF-8编码吧,准没错。

中⽂能够使⽤的字符集两种:
第⼀种: UTF-8 UTF-8是国际通⽤字库,⾥⾯涵盖了所有地球上所有⼈类的语⾔⽂字,⽐如阿拉伯⽂、汉
语、⻦语……
第⼆种: GBK(对GB2312进⾏了扩展)。 gb2312 是国标,是中国的字库,⾥⾯仅涵盖了汉字和⼀些常⽤外
⽂,⽐如⽇⽂⽚假名,和常⻅的符号。
字库规模: UTF-8(字很全) > gb2312(只有汉字)

大部分情况下,作为中国网民用户在向网站服务端进行数据信息存储时,会经常使用到中文字符信息;

但是由于数据库服务系统默认的字符编码设置问题,会导致在识别存储的中文信息时,出现字符乱码问题;

因此,为了能更准确的识别数据库中的中文字符信息,需要对数据库服务配置文件中的字符编码设置进行调整。

# 二、配置修改数据库服务配置文件中的默认字符编码设置

1、查看获取当前数据库默认字符编码信息

(1)查看获取数据库服务可以使用的字符集,一般数据库服务中,常规使用的字符集编码为utf8utf8mb4

```sql
mysql > show charset;

Day003-数据库服务基础命令应用-图4

(2)查看获取数据库服务默认字符编码

mysql> show variables like "%character%";

Day003-数据库服务基础命令应用-图5

默认情况下,数据库存储数据与数据库服务端识别的字符编码均为:utf8mb4编码。

说明:数据库服务最新8.0版本的字符集信息为utf8mb4,早期数据库服务版本字符集编码为latin1;

特殊知识点说明:在数据库服务应用中 utf8和utf8mb4之间有什么区别?

序号 区别说明 解释说明
01 两种字符集的字符存储量不同
utf8 最多存储3字节长度字符 张-3字节
utf8mb4 最多存储4字节长度字符(表情字符emoji) 张-4字节

说明:企业生产环境中,建议客户端与服务端字符集要统一;

(3)模拟存储中文数据信息数据库中,查看中文字符的显示情况:

# 创建新的数据库信息
mysql > create database db01;

# 查看新的数据库编码
mysql > show create database db01;
+----------+--------------------------------------------------------------------------------------------------------------------------------+
| Database | Create Database                                                                                                                |
+----------+--------------------------------------------------------------------------------------------------------------------------------+
| db01     | CREATE DATABASE `db01` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */ |
+----------+--------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

# 创建新的数据库表信息
mysql> use db01;
mysql> create table a(name char(10));

# 向数据库表中插入数据
mysql> insert into a values("张三");

mysql> select * from a;
+--------+
| name   |
+--------+
| 张三   |
+--------+
1 row in set (0.00 sec)

说明:如果是字符集latin1,会出现乱码

2、编写修改数据库服务配置文件字符编码

Mysql8.0默认字符编码就是utf8mb4,不用调。主要调整的就是Mysql5.7和Mysql5.6版本

# 将数据库服务配置文件进行备份
[root@master ~]# cp /data/3306/data/my.cnf{,.bak}

# 编辑修改服务配置文件参数信息,设置服务端字符集编码为utf8mb4
[root@master ~]# vim /data/3306/data/my.cnf
[mysql]
socket=/tmp/mysql.sock
[mysqld]
character-set-server=utf8mb4
user=mysql
basedir=/usr/local/mysql
datadir=/data/3306/data
socket=/tmp/mysql.sock
innodb_fast_shutdown=0

#验证
[root@master ~]# systemctl restart mysqld
[root@master ~]# mysql
mysql> show variables like '%char%';
+--------------------------+----------------------------------------------------------------+
| Variable_name            | Value                                                          |
+--------------------------+----------------------------------------------------------------+
| character_set_client     | utf8mb4                                                        |
| character_set_connection | utf8mb4                                                        |
| character_set_database   | utf8mb4                                                        |
| character_set_filesystem | binary                                                         |
| character_set_results    | utf8mb4                                                        |
| character_set_server     | utf8mb4                                                        |
| character_set_system     | utf8                                                           |
| character_sets_dir       | /usr/local/mysql-5.7.30-linux-glibc2.12-x86_64/share/charsets/ |
+--------------------------+----------------------------------------------------------------+
8 rows in set (0.00 sec)

3、编写修改数据库客户配置文件字符编码

# 将数据库服务配置文件进行备份
[root@master ~]# cp /data/3306/data/my.cnf{,.bak}

# 编辑修改服务配置文件参数信息,设置客户端字符集编码为utf8mb4
[root@master ~]# vim /data/3306/data/my.cnf
[mysql]
default-character-set=utf8mb4
socket=/tmp/mysql.sock
[mysqld]
character-set-server=utf8mb4
user=mysql
basedir=/usr/local/mysql
datadir=/data/3306/data
socket=/tmp/mysql.sock
innodb_fast_shutdown=0

#验证
[root@master ~]# systemctl restart mysqld
[root@master ~]# mysql
mysql> show variables like 'character_set_client';
+----------------------+---------+
| Variable_name        | Value   |
+----------------------+---------+
| character_set_client | utf8mb4 |
+----------------------+---------+
1 row in set (0.00 sec)

4、数据库服务建库时单独设置字符集

# 创建数据库时单独设置字符集,默认后续库中创建的表也是这个字符集,存在库表的继承关系
mysql> create database db02 charset utf8mb4;

# 查看创建的数据库字符集信息
mysql> show create database db02;
+----------+------------------------------------------------------------------+
| Database | Create Database                                                  |
+----------+------------------------------------------------------------------+
| db02     | CREATE DATABASE `db02` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ |
+----------+------------------------------------------------------------------+
1 row in set (0.00 sec)

5、数据库服务建表时单独设置字符集

#创建数据库中表时单独设置字符集
mysql> create database db03;
mysql> use db03;
mysql> create table t1 (id int) charset gbk;

# 查看创建的数据表字符集信息
mysql> show create table t1;
+-------+---------------------------------------------------------------------------------+
| Table | Create Table                                                                    |
+-------+---------------------------------------------------------------------------------+
| t1    | CREATE TABLE `t1` (
  `id` int DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=gbk |
+-------+---------------------------------------------------------------------------------+
1 row in set (0.01 sec)

6、数据库服务字符编码信息调整方法:

假设数据库表原有字符集为gbk,并且已经存储数据了,需要将表和数据字符集进行调整转换utf8mb4

(1)方法一:不严谨的方法,只会影响之后存储的数据,不会修改之前存储的数据

#环境准备
mysql> create database db04 charset latin1;
mysql> create table db04.t1 (id int) charset latin1;

#环境验证
##查看数据库的字符集
mysql> show create database db04;
+----------+----------------------------------------------------------------------------------------------------+
| Database | Create Database                                                                                    |
+----------+----------------------------------------------------------------------------------------------------+
| db04     | CREATE DATABASE `db04` /*!40100 DEFAULT CHARACTER SET latin1 */ /*!80016 DEFAULT ENCRYPTION='N' */ |
+----------+----------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
##查看表的字符集
mysql> SHOW CREATE TABLE db04.t1;
+-------+------------------------------------------------------------------------------------+
| Table | Create Table                                                                       |
+-------+------------------------------------------------------------------------------------+
| t1    | CREATE TABLE `t1` (
  `id` int DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+-------+------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

#修改库的字符编码
mysql> alter DATABASE `db04` DEFAULT CHARACTER SET utf8mb4;

#修改表的字符编码
mysql > alter table db04.t1 DEFAULT charset=utf8mb4;

#验证库字符编码是否修改
mysql> show create database db04;
+----------+--------------------------------------------------------------------------------------------------------------------------------+
| Database | Create Database                                                                                                                |
+----------+--------------------------------------------------------------------------------------------------------------------------------+
| db04     | CREATE DATABASE `db04` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */ |
+----------+--------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

#验证表字符编码是否修改
mysql> show create table db04.t1;
+-------+----------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                   |
+-------+----------------------------------------------------------------------------------------------------------------+
| t1    | CREATE TABLE `t1` (
  `id` int DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+-------+----------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

(2)方法二:严谨的方法,可以影响之后存储的数据,也会修改之前存储的数据,字符集转换是可以的,但是必须保证修改后的字符集是修改前的严格超集(包含)

步骤一:锁表逻辑导出数据(例如:mysqldump
步骤二:重新创建数据空表(设置目标字符集)
步骤三:导入备份数据信息
-- 严谨的方法,可以影响之后存储的数据,也会修改之前存储的数据
-- 字符集转换是可以的,但是必须保证修改后的字符集是修改前的严格超集(包含)

数据库中字符设置参数信息说明:

序号 参数信息 解释说明
01 character_set_client 用来设置客户端使用的字符集
02 character_set_connection 用来设置连接数据库时的字符集
如果程序中没有指明连接数据库使用的字符集类型则按照这个字符集设置。
03 character_set_database 用来设置默认创建数据库的编码格式
如果在创建数据库时没有设置编码格式,就按照这个格式设置。
04 character_set_filesystem 文件系统的编码格式,把操作系统上的文件名转化成此字符集
即把 character_set_client转换character_set_filesystem, 默认binary是不做任何转换
05 character_set_results 数据库给客户端返回时使用的编码格式,如果没有指明,使用服务器默认的编码格式。
06 character_set_server 服务器安装时指定的默认编码格式,这个变量建议由系统自己管理,不要人为定义。
07 character_set_system 数据库系统使用的编码格式,这个值一直是utf8
不需要设置,它是为存储系统元数据的编码格式。
08 character_sets_dir 这个变量是字符集安装的目录。

根据客户端请求数据库服务端字符集转换流程,可以更好的理解以上字符编码配置参数:

(1) mysql Server收到请求时将请求数据从 character_set_client 转换为 character_set_connection;

(2) 进行内部操作前将请求数据从 character_set_connection 转换为内部操作字符集;

  • 使用每个数据字段的 CHARACTER SET 设定值;
  • 若上述值不存在,则使用对应数据表的字符集设定值;
  • 若上述值不存在,则使用对应数据库的字符集设定值;
  • 若上述值不存在,则使用 character_set_server 设定值;

(3) 最后将操作结果从内部操作字符集转换为 character_set_results

Day003-数据库服务基础命令应用-图6

三、字符编码校对规则

在进行字符编码设置时,还需要设置校对规则信息,校对规则是什么?

排序规则,就是指字符比较时按照字符编码还是直接用二进制数据比较,以及是否区分大小写。

主要可以根据校对规则定义或设置的不同:在查询数据信息时,影响数据信息的查询输出和排序效果;

其中utf8mb4字符集中,常用的排序规则有utf8mb4_unicode_ci、utf8mb4_general_ci、utf8mb4_bin:

排序规则前缀是字符集编码,中间是排序规则名称,后缀有特殊意义如下(常用的):

排序规则后缀 解释说明
_ci 不区分大小写,Case-insensitive的缩写
_cs 区分大小写,Case-sensitive的缩写
_ai 不区分重音,Accent-insensitive的缩写
_as 区分重音,Accent-sensitive的缩写
_bin 采用二进制方式存储数据信息(区分大小写)

utf8mb4_unicode_ci是基于标准Unicode来排序和比较,能够在各种语言之间精确排序。且在特殊情况下,Unicode排序规则为了能够处理特殊字符的情况,实现了略微复杂的排序算法。但是在绝大多数情况下不会发生此类复杂比较。

utf8mb4_general_ci没有实现Unicode排序规则,在遇到某些特殊字符情况下,排序结果可能不一致。但是,在绝大多数情况下,这些特殊字符的顺序并不需要那么精确。

utf8mb4_bin将字符串的每个字符用二进制数据编译存储,区分大小写,而且可以存二进制的内容。

综合来说,utf8mb4_unicode_ci比较准确,utf8mb4_general_ci速度较快。utf8mb4_unicode_ci对于特殊字符的处理,在中文、英文应用中不会使用到,除非你的应用有德语、法语、俄语等,则需要使用utf8mb4_unicode_ci,否则一般选用utf8mb4_general_ci就可以了。

# 查看数据库服务中可用的校对规则信息
mysql> show collation;

# 数据库设置字符编码校对规则
mysql> create database db05 charset utf8 collate utf8_general_mysql500_ci;

# 验证是否创建成功
mysql> show create database db05;
+----------+-----------------------------------------------------------------------------------------------------------------------------------+
| Database | Create Database                                                                                                                   |
+----------+-----------------------------------------------------------------------------------------------------------------------------------+
| db05     | CREATE DATABASE `db05` /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_mysql500_ci */ /*!80016 DEFAULT ENCRYPTION='N' */ |
+----------+-----------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

# 数据表设置字符编码校对规则
mysql> create table db05.t1 (id int) charset utf8 collate utf8_german2_ci;

# 验证表是否设置成功
mysql> show create table db05.t1;
+-------+-------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                |
+-------+-------------------------------------------------------------------------------------------------------------+
| t1    | CREATE TABLE `t1` (
  `id` int DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_german2_ci |
+-------+-------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

数据库校对规则设置应用实践:

# 创建三个数据表,并设置相同的字符集,以及不同的字符校对规则(mysql8环境)
mysql> create database db06 charset utf8 collate utf8_general_mysql500_ci;
mysql> create table db06.t1(info char(3)) charset utf8mb4 collate utf8mb4_0900_ai_ci;
mysql> create table db06.t2(info char(3)) charset utf8mb4 collate utf8mb4_0900_as_cs;
mysql> create table db06.t3(info char(3)) charset utf8mb4 collate utf8mb4_bin;

# 插入数据信息
mysql> insert into db06.t1 values('a'),('A'),('b'),('B'),('c'),('C');
mysql> insert into db06.t2 values('a'),('A'),('b'),('B'),('c'),('C');
mysql> insert into db06.t3 values('a'),('A'),('b'),('B'),('c'),('C');

# 查询数据信息, 结果_ci后缀发现不会区分大小写显示
mysql> select * from db06.t1 where info='a';
+------+
| info |
+------+
| a    |
| A    |
+------+
2 rows in set (0.00 sec)

# 查询数据信息, 结果_cs后缀发现会区分大小写显示
mysql> select * from db06.t2 where info='a';
+------+
| info |
+------+
| a    |
+------+
1 row in set (0.01 sec)

# 查询数据信息, 结果_bin后缀发现会区分大小写显示
mysql> select * from db06.t3 where info='a';
+------+
| info |
+------+
| a    |
+------+
1 row in set (0.00 sec)

# 针对info所在列进行排序,校对规则不同,查询的数据结果会有不同的排序效果,观察到_bin后缀会影响排序,优先排序大写字母,完了再排序小写字母
mysql> select * from db06.t1 order by info;
+------+
| info |
+------+
| a    |
| A    |
| b    |
| B    |
| c    |
| C    |
+------+
6 rows in set (0.00 sec)

mysql> select * from db06.t2 order by info;
+------+
| info |
+------+
| a    |
| A    |
| b    |
| B    |
| c    |
| C    |
+------+
6 rows in set (0.00 sec)

mysql> select * from db06.t3 order by info;
+------+
| info |
+------+
| A    |
| B    |
| C    |
| a    |
| b    |
| c    |
+------+
6 rows in set (0.00 sec)

#修改库的校对规则
mysql> alter database db06 charset utf8 collate utf8_bin;

#验证
mysql> show create database db06;
+----------+-------------------------------------------------------------------------------------------------------------------+
| Database | Create Database                                                                                                   |
+----------+-------------------------------------------------------------------------------------------------------------------+
| db06     | CREATE DATABASE `db06` /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_bin */ /*!80016 DEFAULT ENCRYPTION='N' */ |
+----------+-------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

#修改t1表的校对规则
mysql> alter table db06.t1 charset utf8mb4 collate utf8mb4_bin;

#验证
mysql> show create table db06.t1;
+-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                   |
+-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t1    | CREATE TABLE `t1` (
  `info` char(3) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin |
+-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)