MySQL数据库学习之跟着掘金手册学-个人笔记与总结[2]-字符集和比较规则

一、对上一章的复习摘要

关于InnoDB:
具有外键支持功能的事务存储引擎。
引入了行级锁定和外键约束。
以下场景使用InnoDB是最理想的选择:
(1)更新密集的表。
(2)支持事务。
(3)自动灾难恢复。
(4)外键约束
(5)支持自动增加列AUTO_INCREMENT属性。(MySQL8.0以后才有。)
——需要事务支持,并且有较高并发读取频率时,InnoDB是不错的选择。

二、把我能想到的写下来:

从字符串映射到二进制码的过程叫编码,反之,从二进制码映射到字符串的过程叫解码。
字符集是指一定范围的字符映射成二进制码构成的集合。
(人们抽象出一个字符集的概念来描述某个字符范围的编码规则。)

字符串的比较规则:比如不区分大小写的/区分大小写的。比如:默认的是不区分大小写的:
在这里插入图片描述

alter table showCompare modify characters char(1)
 collate gbk_bin;

gbk_bin是区分大小写的:
在这里插入图片描述
因为编码集与比较规则是相关的,所以改变编码集时,比较规则也会改变;改变比较规则时,编码集也会改变。

各种编码规则:
ASCII:可以表示128个符号,英文字母、标点符号。最多1个字节即可。

(改:包括空格、标点符号、数字、大小写字母、不可见字符。)

?ISSO? 也叫latain1,可以表示汉字。256个字符,1个字节。如果是ASCII中的字符,1个字节,否则,2个字节。

(改:ISO 8859-1 是在ASCII基础上扩充了128个西欧-德/法常用的字符。最多1字节。)

GB2312。最多3个字节。

(改:汉字、拉丁字母、希腊字母、日本片假名、俄语西里尔字母,兼容ASCII,如果在ASCII中,1字节;如果不在ASCII中,2字节,采用变长编码方式。 )

GBK是在GB2312的基础上发展来的,可以兼容GB2312。1~4个字节。

(改:GBK最多2字节。)

utf8是Unicode的一种编码方式。
MySQL的utf8其实是简化了的utf8,是utfmb32,1~3个字节。
utfmb64是1~4字节,这个才是正宗的utf8。
(补:utf8变长,兼容ASCII,1~4字节 。)
(改:MySQL中的utf8指的是utf8mb3 .1~3字节。
utf8mb4才是正宗的utf8 1~4字节。

编码有4个级别:服务器 数据库 表 列。

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

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

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

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

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

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

ALTER TABLE 表名 MODIFY 列名 字符串类型 
[CHARACTER SET 字符集名称] [COLLATE 比较规则名称];

如果不指定数据库的字符编码,就会默认和服务器的一致;如果不指定表的,就默认和数据库的一致…
比如之前建表时:
在这里插入图片描述
就是指定表的编码方式。

有3个重要的系统变量:
character_set_client:是服务器解析指令时的编码方式;

(服务器解码)

character_set_connection:是服务器???

(改:服务器处理请求时会把请求字符串从character_set_client转为character_set_connection)

character_set_results:是服务器向客户端返回结果时用的编码方式。
我们执行SQL语句时,过程是这样的,操作系统这边会有编码方式(Windows默认的是GB2312) 然后发送给服务器,服务器解析后,返回结果,并给操作系统。

查看这三个系统变量:
在这里插入图片描述
在Windows系统中,这三个系统变量默认值都是gbk。

查看操作系统字符集的命令:chcp
在这里插入图片描述在这里插入图片描述
为什么会出现乱码呢?就是在这个过程中有编码方式不对应,就会把二进制字符按照不对应的编码输出,我们看来就”乱码“了。
在MySQL中,如果有中文,要用utf8或者gbk(比如建表的时候就把表的字符集设置为utf8) 如果不这样设置,改变比较规则也是会改变到字符集的。
设置为gbk,就与Windows系统的编码集gbk以及那3个系统变量一致,就不会出现中文录不进去或者乱码问题。(但是不能保证每个中文都可,毕竟gbkmb64是4位的,应该是弥补3位不够的缺陷的。 )
在这里插入图片描述

三:补充

1,乱码是如何产生的:
字符’我’在utf8字符集编码下的字节串长这样:0xE68891.
如果一个程序把这个字节串发送到另一个程序里,另一个程序用不同的字符集去解码这个字节串:
假设使用的是gbk字符集来解释这串字节,解码过程就是这样的:
首先看第一个字节0xE6,它的值大于0x7F(十进制:127),说明是两字节编码,继续读一字节后是0xE688,然后从gbk编码表中查找字节为0xE688对应的字符,发现是字符’鎴’
继续读一个字节0x91,它的值也大于0x7F,再往后读一个字节发现木有了,所以这是半个字符。
所以0xE68891被gbk字符集解释成一个字符’鎴’和半个字符。
假设用iso-8859-1,也就是latin1字符集去解释这串字节,解码过程如下:
先读第一个字节0xE6,它对应的latin1字符为æ
再读第二个字节0x88,它对应的latin1字符为ˆ
再读第三个字节0x91,它对应的latin1字符为
所以整串字节0xE68891被latin1字符集解释后的字符串就是’我
可见,如果对于同一个字符串编码和解码使用的字符集不一样,会产生意想不到的结果,作为人类的我们看上去就像是产生了乱码一样。
2.从发送请求到接收结果过程中发生的字符集转换:
(我觉得这个还蛮重要的 。)
(1) 客户端使用操作系统的字符集编码请求字符串,向服务器发送的是经过编码的一个字节串。
(2) 服务器将客户端发送来的字节串采用character_set_client代表的字符集进行解码,将解码后的字符串再按照character_set_connection代表的字符集进行编码。
(3) 如果character_set_connection代表的字符集和具体操作的列使用的字符集一致,则直接进行相应操作,否则的话需要将请求中的字符串从character_set_connection代表的字符集转换为具体操作的列使用的字符集之后再进行操作。
(4) 将从某个列获取到的字节串从该列使用的字符集转换为character_set_results代表的字符集后发送到客户端。
(5) 客户端使用操作系统的字符集解析收到的结果集字节串。

这也就解释了为什么插入的元组中有汉字时,需要

create table t (......)
character set utf8  /  gbk

Windows系统默认的字符集是gbk了,(1)与(2)都一致,即操作系统与character_set_clientcharacter_set_connection是一致的。
而到了(3), character_set_connection仍是gbk,而具体操作的列使用的默认和表是一致的,也就是utf8gbk,
这时需要将请求的字符串从 character_set_connectiongbk转换成列使用的utf8gbk。(所以中文就允许喽,如果不设置,默认是latain1 不支持中文的 。)
然后到了(4),将从某个列得到的字符串从该列使用的utf8gbk转换成character_set_resultsgbk ,然后发送到客户端 。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值