MySQL入门篇-MySQL字符集小结

news2024/12/27 12:13:41

备注:测试数据库版本为MySQL 8.0

这个blog我们来聊聊MySQL的字符集

前言:

字符集和排序规则

说实话我对这两个概念比较模糊,其实可以简单的理解:

字符集(character set):定义了字符以及字符的编码。
排序规则(collation):定义了字符的比较规则。

一个字符集对应至少一种排序规则(一般是1对多)
两个不同的字符集不能有相同的排序规则
每个字符集都有默认的排序规则

MySQL字符集相关参数

character_set_client      客户端来源数据使用的字符集,默认值:utf8mb4
character_set_connection  连接层字符集,默认值:utf8mb4
character_set_database    当前选中数据库的默认字符集,默认值:utf8mb4
character_set_results     查询结果字符集,默认值:utf8mb4
character_set_server      默认的内部操作字符集,默认值:utf8mb4
character_set_system      系统元数据(字段名等)字符集,默认值:utf8

这些参数真的多,不过还好MySQL 8.0开始,这些都是默认utf8mb4了(character_set_system除外)。

MySQL支持的字符集、排序规则:

-- MySQl支持的字符集
SHOW CHARACTER SET;
-- MySQL utf8mb4支持的排序规则:
SHOW COLLATION WHERE Charset = 'utf8mb4';

常用的字符集

utf8和utf8mb4

MySQL8.0开始,默认字符集修改为了utf8mb4。

MySQL在5.5.3之后增加了utf8mb4的编码,mb4即4-Byte UTF-8 Unicode Encoding,专门用来兼容四字节的unicode。utf8mb4为utf8的超集并兼容utf8,比utf8能表示更多的字符。

如果需要存储4 字节的字符,utf8字符集就会出现问题,例如emoji表情,所以建议选择utf8mb4而非utf8。
当然utf8替换为utf8mb4占的空间更多,如果utf8绝对够用,也可以依旧使用utf8

gbk/gb2312/gb18030

GB2312 :中国国家标准简体中文字符集,共收录 6763 个汉字,其中一级汉字 3755 个,二级汉字 3008 个;同时收录了包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的 682 个字符。

GBK :共收入21886个汉字和图形符号,GBK 向下与 GB 2312 完全兼容,向上支持 ISO 10646 国际标准,在前者向后者过渡过程中起到的承上启下的作用。

GB18030 :共收录汉字70244个,GB18030 与 GB 312 和 GBK 兼容

大多数情况下,GBK就够用了,如果生僻字比较多,可以改为GB18030

关于utf8和gbk字符集如何选择:
UTF-8:一个汉字 = 3个字节,英文是1个字节
GBK: 一个汉字 = 2个字节,英文是1个字节

测试记录:

-- 测试语句
create table t_utf8(en varchar(100),cn varchar(100)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;

insert into t_utf8 values ('a','张');
insert into t_utf8 values ('ab','张三');


create table t_gbk(en varchar(100),cn varchar(100)) DEFAULT CHARACTER SET gbk COLLATE gbk_chinese_ci;

insert into t_gbk values ('a','张');
insert into t_gbk values ('ab','张三');


select en,cn,char_length(en),char_length(cn),length(en),length(cn) from t_utf8;

select en,cn,char_length(en),char_length(cn),length(en),length(cn) from t_gbk;

上面的sql语句对应下面的结果 

 

latin

光latin字符集就有latin1、latin2、latin5、latin7四种,当然这4种字符集在中国应用很少,我在这里也就不一一讲解了。

MySQL一直到8.0版本才将字符集由latin1改为utf8mb4。
之前版本如果创建数据库和表的时候,不指定字符集,默认都是latin1字符集。
latin1存中文很容易出现乱码问题,给系统带来灾难性的问题,如果是MySQL 8.0之前版本,创建数据库和表,一定要指定字符集。
测试记录:

-- 创建一个latin字符集的表
create table t_latin(en varchar(100),cn varchar(100)) DEFAULT CHARACTER SET latin1 COLLATE latin1_general_ci;
-- insert的时候直接报错
insert into t_latin values ('a','程');
insert into t_latin values ('ab','张三');

-- set names latin1  此时可以将中文数据录入表
set names latin1;
insert into t_latin values ('a','张');
insert into t_latin values ('ab','张三');

-- 查询也没有问题,正常显示
select * from t_latin;

-- 退出重登陆后,发现中文乱码了
exit;

mysql -uroot -p
use test;
select * from t_latin;

 

 

解决latin1字符集显示显示乱码的两种方法

#方法一
select en,cn from t_latin;
select en,convert(unhex(hex(convert(cn using latin1))) using utf8) as cn from t_latin;

#方法二
set names latin;
set names latin1;
select en,cn from t_latin;

常用MySQL的排序规则介绍 

utf8_general_ci 不区分大小写,这个你在注册用户名和邮箱的时候就要使用。
utf8_general_cs 区分大小写,如果用户名和邮箱用这个 就会造成不良后果
utf8_bin:字符串每个字符串用二进制数据编译存储。 区分大小写,而且可以存二进制的内容

utf8_general_ci校对速度快,但准确度稍差。
utf8_unicode_ci准确度高,但校对速度稍慢。

show collation where charset = 'utf8';
show collation where charset = 'gbk';

如果字符集选择utf8,则排序规则选择默认的utf8_general_ci
如果字符集选择utf8mb4,则排序规则选择默认的utf8mb4_0900_ai_ci
如果字符集选择gbk,则排序规则选择默认的gbk_chinese_ci

排序规则大小写敏感测试:

create table t_utf8mb4(en1 varchar(100),en2 varchar(100)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;

alter table t_utf8mb4 modify column en2 varchar(100) charset utf8mb4 collate utf8mb4_0900_as_cs ;

insert into t_utf8mb4 values ('a','a');
insert into t_utf8mb4 values ('A','A');
insert into t_utf8mb4 values ('a','A');
insert into t_utf8mb4 values ('A','a');

select * from t_utf8mb4 where en1='a';
select * from t_utf8mb4 where en1='A';

select * from t_utf8mb4 where en2='a';
select * from t_utf8mb4 where en2='A';

 测试结果:

mysql>
mysql> create table t_utf8mb4(en1 varchar(100),en2 varchar(100)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
Query OK, 0 rows affected (0.03 sec)

mysql> alter table t_utf8mb4 modify column en2 varchar(100) charset utf8mb4 collate utf8mb4_0900_as_cs ;
Query OK, 0 rows affected (0.07 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql>
mysql>
mysql> insert into t_utf8mb4 values ('a','a');
Query OK, 1 row affected (0.00 sec)

mysql> insert into t_utf8mb4 values ('A','A');
Query OK, 1 row affected (0.01 sec)

mysql> insert into t_utf8mb4 values ('a','A');
Query OK, 1 row affected (0.00 sec)

mysql> insert into t_utf8mb4 values ('A','a');
Query OK, 1 row affected (0.01 sec)

mysql>
mysql>
mysql> select * from t_utf8mb4;
+------+------+
| en1  | en2  |
+------+------+
| a    | a    |
| A    | A    |
| a    | A    |
| A    | a    |
+------+------+
4 rows in set (0.00 sec)

mysql>
-- 查询不区分大小写的排序规则列,果然全部输出
mysql> select * from t_utf8mb4 where en1='a';
+------+------+
| en1  | en2  |
+------+------+
| a    | a    |
| A    | A    |
| a    | A    |
| A    | a    |
+------+------+
4 rows in set (0.00 sec)

mysql> select * from t_utf8mb4 where en1='A';
+------+------+
| en1  | en2  |
+------+------+
| a    | a    |
| A    | A    |
| a    | A    |
| A    | a    |
+------+------+
4 rows in set (0.00 sec)
-- 查询区分大小写的排序规则列,值输出全部是小写或全部是大写的
mysql> select * from t_utf8mb4 where en2='a';
+------+------+
| en1  | en2  |
+------+------+
| a    | a    |
| A    | a    |
+------+------+
2 rows in set (0.00 sec)

mysql> select * from t_utf8mb4 where en2='A';
+------+------+
| en1  | en2  |
+------+------+
| A    | A    |
| a    | A    |
+------+------+
2 rows in set (0.00 sec)

MySQL字符集相关参数

字符集参数介绍

character_set_client      客户端来源数据使用的字符集,默认值:utf8mb4
character_set_connection  连接层字符集,默认值:utf8mb4
character_set_database    当前选中数据库的默认字符集,默认值:utf8mb4
character_set_results     查询结果字符集,默认值:utf8mb4
character_set_server      默认的内部操作字符集,默认值:utf8mb4
character_set_system      系统元数据(字段名等)字符集,默认值:utf8

也许大家会有疑问,弄一个字符集不好吗,为什么有这6个字符集
我这边来讲讲这6个字符集的使用场景
因为服务器端和客户端,字符集会存在一定的差异。

服务器端总是假设客户端是按照 character_set_client设置的字符来传输数据和SQL语句的。
当服务器收到客户端的SQL语句时,它先将其转换为字符集character_set_connection。它还是用这个设置来决定如何将数据转换成字符串。
当服务器端返回数据或错误信息给客户端时,它会将其转换成character_set_result。

这样就保证了,服务器端和客户端在中转数据的时候,不会出现乱码。

至于character_set_server和character_set_database这两个,一个是系统默认的字符集,一个是创建数据库默认的字符集。

字符集参数修改

备注:character_set_system参数是只读参数,不能修改,其余参数可以通过set命令进行修改
上述5个参数需要保持一致,这样才能避免出现乱码,如果需要修改,可以参考如下:

测试 

mysql> set character_set_client = utf8;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> set character_set_connection = utf8;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql>
mysql> set character_set_database = utf8;
Query OK, 0 rows affected, 2 warnings (0.00 sec)

mysql>
mysql> set character_set_results = utf8;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> set character_set_server = utf8;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql>
mysql>
mysql> show variables like 'character_set%';
+--------------------------+----------------------------------------------+
| Variable_name            | Value                                        |
+--------------------------+----------------------------------------------+
| character_set_client     | utf8                                         |
| character_set_connection | utf8                                         |
| character_set_database   | utf8                                         |
| character_set_filesystem | binary                                       |
| character_set_results    | utf8                                         |
| character_set_server     | utf8                                         |
| character_set_system     | utf8                                         |
| character_sets_dir       | E:\mysql\mysql-8.0.19-winx64\share\charsets\ |
+--------------------------+----------------------------------------------+
8 rows in set, 1 warning (0.00 sec)

mysql>
-- 修改
mysql> set character_set_system = utf8;
ERROR 1238 (HY000): Variable 'character_set_system' is a read only variable

数据库、表、列的字符集

创建数据库时,如不指定字符集,将根据服务器上的character_set_server设置来设定该数据库的默认字符集。
创建表时,如不指定字符集,将根据数据库的字符集设置指定这个表的字符集。
创建列时,如不指定字符集,将根据表的设置指定列的字符集。

我们来演练一个 数据库、表、列的字符集不相同的例子。

-- 数据库字符集是 latin1
mysql> create database test1 charset latin1;
Query OK, 1 row affected (0.03 sec)

mysql> use test1;
Database changed
-- 表的字符集是 utf8mb4  而列的字符集有 utf8也有gbk
mysql> create table t1(id int,name1 varchar(100) charset gbk,name2 varchar(100) charset utf8) default charset = utf8mb4;
Query OK, 0 rows affected, 1 warning (0.06 sec)

mysql> insert into t1 values(1,'张三','张三');
Query OK, 1 row affected (0.01 sec)

mysql> select * from t1;
+------+--------+--------+
| id   | name1  | name2  |
+------+--------+--------+
|    1 | 张三   | 张三   |
+------+--------+--------+
1 row in set (0.00 sec)

这样看,数据库、表、列可以有不同的字符集和排序规则。
那么我们如何选择数据库、表、列的字符集和排序规则呢?

最好是先为服务器(数据库)选择一个合理的字符集,然后表和列都遵循这个字符集。
当有特殊需求的时候,可以显式的指定表或列的字符集,让表和列选择自己合适的字符集。

字符集和排序规则如何影响查询

order by collate时 可能导致无法使用索引进行排序
测试数据:

create table t1(name1 varchar(100) charset utf8mb4 ,name2 varchar(100) charset utf8 collate utf8_bin,name3 varchar(100) charset gbk);
insert into t1 values('张三','张三','张三');
insert into t1 values('李四','李四','李四');
-- 创建索引
create index i_t1_02 on t1(name2);  
explain select name2 from t1 order by name2;
explain select name2 from t1 order by name2 collate utf8_general_ci;

执行记录:

mysql> create table t1(name1 varchar(100) charset utf8mb4 ,name2 varchar(100) charset utf8 collate utf8_bin,name3 varchar(100) charset gbk);
Query OK, 0 rows affected, 2 warnings (0.03 sec)

mysql> insert into t1 values('张三','张三','张三');
Query OK, 1 row affected (0.01 sec)

mysql> insert into t1 values('李四','李四','李四');
Query OK, 1 row affected (0.01 sec)

mysql> select * from t1;
+--------+--------+--------+
| name1  | name2  | name3  |
+--------+--------+--------+
| 张三   | 张三   | 张三   |
| 李四   | 李四   | 李四   |
+--------+--------+--------+
2 rows in set (0.00 sec)

mysql> create index i_t1_02 on t1(name2);
Query OK, 0 rows affected (0.03 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> explain select name2 from t1 order by name2;
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | t1    | NULL       | index | NULL          | i_t1_02 | 303     | NULL |    2 |   100.00 | Using index |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

mysql>
mysql> explain select name2 from t1 order by name2 collate utf8_general_ci;
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-----------------------------+
| id | select_type | table | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra                       |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-----------------------------+
|  1 | SIMPLE      | t1    | NULL       | index | NULL          | i_t1_02 | 303     | NULL |    2 |   100.00 | Using index; Using filesort |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-----------------------------+
1 row in set, 1 warning (0.00 sec)

mysql>

可以看到 order by name2 collate utf8_general_ci 由于排序规则并不是创建时指定的utf8_bin,最后使用了文件排序 Using filesort

参考文章

MySQL字符集小结_只是甲的博客-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/197069.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Django】ORM增删改查、F对象和Q对象、聚合操作和原生数据库操作

1、ORM的增删改查均需要通过管理器对象进行。 2、可使用python3 manage.py shell 进入脚本页方便操作。 3、可修改输出格式 一、ORM查询操作 1、查询方法 (1)all()方法 用法:MyModel.objects.all()作用:查询所有数据&#xff0c…

微信小程序——自定义组件(纯数据字段),组件的生命周期,组件所在页面的生命周期,插槽,父子组件之间的通信,事件绑定,属性绑定,behavior

一.纯数据字段1.什么是纯数据字段概念:纯数据字段指的是那些不用于界面渲染的data字段。应用场景:例如有些情况下,某些 data 中的字段既不会展示在界面上,也不会传递给其他组件,仅仅在当前组件内部使用。带有这种特性的…

《Keras深度学习:入门、实战与进阶》之回归问题实例:波士顿房价预测

本文摘自《Keras深度学习:入门、实战与进阶》。 本节将要预测20世纪70年代中期波士顿郊区房屋价格的中位数。这个数据是1978年统计收集的,数据集中的每一行数据都是对波士顿周边或城镇房价的描述,包含以下14个特征和506条数据。  CRIM&am…

verilog图像算法实现和仿真(代码与实践)

【声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 这里的代码指的是verilog代码,而不是之前的python代码。因为verilog处理的是数据,所以之前我们也谈到过,如果需要用verilog处理图像数据,需要先用python把图像变成文本文件,等到…

菜鸟的进阶--手写一个微型Spring

前言想干嘛深入了解spring原理,特别是IOC容器是如何实现的?AOP是如何实现的?手写一个spring迷你版框架,实现容器和AOP机制。我为什么想这么做spring是整个java体系中最重要的框架,它整合第三方技术,将所有的…

交联剂134272-64-3,Maleimide-NH2 HCl,2-马来酰亚胺乙胺盐酸盐

【中文名称】N-(2-氨乙基)马来酰亚胺盐酸盐,2-马来酰亚胺乙胺盐酸盐【英文名称】 MAL-NH2 HCl,Maleimide-NH2 HCl,MAL NH2 HCl,Maleimide-amine HCl,MAL-amine HCl,N-(2-AMinoethyl)MaleiMide Hydrochlorid…

5年老测试员,面试被刷,别人说他不懂自动化测试.....

圈内认识的朋友最近跳槽了,之前在一家小公司干了5年测试,本来以为很容易跳一个高待遇的工作,结果却比想象的难,因为他不会自动化测试… 最近也看了很多人的简历,写的都是3年工作经验,但面试中&#xff0c…

对数据库几个范式的理解

数据库关系理论 这部分主要是几个概念很抽象,大家开始学可能学不明白。最近在准备复试,复习了一下相关的内容,顺便做一下总结。 先说几个名词: 候选码:能够唯一确定一个元组的属性集合称为候选码。注意是集合&#…

每日学术速递2.3

CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 Subjects: cs.Cv、cs.LG 1.Compositional Prompt Tuning with Motion Cues for Open-vocabulary Video Relation Detection(ICLR 2023) 标题:通过基于错误的隐性神经表征的上下文修剪实现高…

Java基础学习笔记(十五)—— 集合(3)

集合1 HashMap 类1.1 HashMap 类概述1.2 HashMap 案例2 TreeMap 类2.1 TreeMap 类概述2.2 TreeMap 案例3 Properties集合3.1 Properties集合概述3.2 Properties基本使用3.3 Properties特有方法3.4 Properties和IO流相结合的方法4 可变参数与不可变集合4.1 可变参数4.2 不可变集…

2023.1.26

0、任务 今明两天任务,回答以下问题: 1、网络传输延迟有哪些?如何区分传输延迟和排队延迟? 2、如何理解路由器存储转发的过程? 3、拥塞是什么,为什么会发生拥塞,发生拥塞的表现是什么&#xff…

网络资源下载方式:http/https、ftp/sftp、BT种子、磁力下载、ed2k下载等的区别

文章目录参考资料序言中心化下载http/https下载ftp/sftp下载http与ftp下载方式的不同中心化下载的缺点中心化下载BT种子下载磁力下载ed2k下载推荐的下载器IDM下载器安装步骤IDM如何下载种子文件参考资料 一文读懂Bt种子、磁力链接、直链、p2p这些下载的区别 常说的BT下载、磁力…

【数据结构基础】图 - 基础和Overview

图(Graph)是由顶点和连接顶点的边构成的离散结构。在计算机科学中,图是最灵活的数据结构之一,很多问题都可以使用图模型进行建模求解。例如: 生态环境中不同物种的相互竞争、人与人之间的社交与关系网络、化学上用图区分结构不同但分子式相同的同分异构体…

情人节该送女友什么?分享四款适合送女生的数码好物

情人节快到了,对于有伴侣的人来说,这是一个浪漫的日子。在这个浪漫的日子,一些生活仪式感是必不可少的。最近看到不少人问,适合女生的数码好物有哪些?下面,我来给大家推荐几款适合送女生的数码好物&#xf…

动态规划DP与记忆化搜索DFS 题单刷题(c++实现+AC代码)

文章目录数字三角形滑雪挖地雷最大食物链计数采药疯狂的采药5倍经验值过河卒洛谷动态规划入门题单: 提单传送门 数字三角形 观察下面的数字金字塔。写一个程序来查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以走到左下方的点也…

“深度学习”学习日记。卷积神经网络--卷积层

2023.2.3 CNN中出现一些新的概念:填充、步幅 等,此外各层中传递的数据是有形状的,与之前的全连接层神经网络完全不同; 一、全连接层存在的问题: 全连接层神经网络使用了Affine层,在相邻的神经元全部连接…

php7.3.4 pdo方式连接sqlserver 设置方法

我这边用的php是7.3.4版本的,大家设置的时候看一下。一、首先要开启php的sqlsrv扩展1.下载SQLSRV58.EXE,我的php版本是7.3.4https://docs.microsoft.com/en-us/sql/connect/php/release-notes-php-sql-driver?viewsql-server-2017#previous-releases拷贝到浏览器打…

内网渗透(二)之基础知识-工作组介绍

系列文章 内网渗透(一)之基础知识-内网渗透介绍和概述 注:阅读本编文章前,请先阅读系列文章,以免造成看不懂的情况!! 工作组介绍 1、工作组的介绍 在一个大型单位里,可能有成百上千台计算机互相连接组成局域网,它…

Rancher 部署 MongoDB

文章目录前置部署创建 Headless开始部署测试前置 背景:在 K8S 集群用 bitnami 部署 MongoDB 有一定的学习成本,有兴趣可以参考 k8s 部署 mongodb 三种模式,且部署后发现 MongoDB 会随着时间推移占用越来越多的内存,暂没找到原有&…

计算机如何在本地硬盘安装WinPE系统

环境: 联想E14 Win 10专业版 U盘魔术师V6 30G硬盘分区 双硬盘:128G固+1T机 DiskGenius UltraISO 问题描述: 如何在本地硬盘安装WinPE系统 解决方案: 一、使用软件制作硬盘PE系统 1.机械磁盘先分区分一个30G分区 …