MySQL字符集详解
一、什么是字符集:
简单的说吧、字符集就是一组对应关系的集合;
1、现在的计算机是在二进制的基础上建立出来的、二进制是数值的一种表达方式、也就是说二进制只的表达“数”、如十进制的3,在二进制中
就可以写成00000011;
2、然而在现实生活当中相对于"数"而言我们用到更多的是“文字”;那这个问题(怎么保存文字)怎么解决呢?然而这个问题根本没有难道
他们、它们决定用一个折中的方式解决;如:保存'a'的时候我就保存一个0,保存'b'的时候我就保存一个1,保存‘A'的时候我就保存一个2
保存’B‘的时候我就保存一个3。于是整个对应关系就变成了这样
字符 -> 编码
'a' --> 0
'b' --> 1
'A' --> 2
'B' --> 3
就这样我们就定义了一个只有4个字符的字符集了;只不过我们这个字符集相比gbk\utf8这样的字符集不知道low到那里去了。
二、什么是排序规则:
1、上面的内容我们已经自己定义了一个字符集了,有了字符集一些最基本的操作就可能做了,如:我想知道一个字符它是不是'a'那么
我只要去看这个字符的编码是不是0就可以了,这样就把一个字符问题变成了一个数字问题了,这样数据上的相等(=),大小(>,<),也就有了
新的意义了。
2、我们这个字符集还有什么不足吗?如:要做到不区分大小写,那么我们之前的 =,<,>也就都来灵了;我们还要给这个字符集加上新的
规则才行;如我们在这里可以粗鲁的加上规则 1:0=2 ,2: 1=3;这样就可能做不区分大小写了。
三、mysql数据库中有哪些字符集可供选择:
select * from information_schema.character_sets; +--------------------+----------------------+---------------------------------+--------+ | CHARACTER_SET_NAME | DEFAULT_COLLATE_NAME | DESCRIPTION | MAXLEN | +--------------------+----------------------+---------------------------------+--------+ | big5 | big5_chinese_ci | Big5 Traditional Chinese | 2 | | dec8 | dec8_swedish_ci | DEC West European | 1 | | cp850 | cp850_general_ci | DOS West European | 1 | | hp8 | hp8_english_ci | HP West European | 1 | | koi8r | koi8r_general_ci | KOI8-R Relcom Russian | 1 | | latin1 | latin1_swedish_ci | cp1252 West European | 1 | | latin2 | latin2_general_ci | ISO 8859-2 Central European | 1 | | swe7 | swe7_swedish_ci | 7bit Swedish | 1 | | ascii | ascii_general_ci | US ASCII | 1 | | ujis | ujis_japanese_ci | EUC-JP Japanese | 3 | | sjis | sjis_japanese_ci | Shift-JIS Japanese | 2 | | hebrew | hebrew_general_ci | ISO 8859-8 Hebrew | 1 | | tis620 | tis620_thai_ci | TIS620 Thai | 1 | | euckr | euckr_korean_ci | EUC-KR Korean | 2 | | koi8u | koi8u_general_ci | KOI8-U Ukrainian | 1 | | gb2312 | gb2312_chinese_ci | GB2312 Simplified Chinese | 2 | | greek | greek_general_ci | ISO 8859-7 Greek | 1 | | cp1250 | cp1250_general_ci | Windows Central European | 1 | | gbk | gbk_chinese_ci | GBK Simplified Chinese | 2 | | latin5 | latin5_turkish_ci | ISO 8859-9 Turkish | 1 | | armscii8 | armscii8_general_ci | ARMSCII-8 Armenian | 1 | | utf8 | utf8_general_ci | UTF-8 Unicode | 3 | | ucs2 | ucs2_general_ci | UCS-2 Unicode | 2 | | cp866 | cp866_general_ci | DOS Russian | 1 | | keybcs2 | keybcs2_general_ci | DOS Kamenicky Czech-Slovak | 1 | | macce | macce_general_ci | Mac Central European | 1 | | macroman | macroman_general_ci | Mac West European | 1 | | cp852 | cp852_general_ci | DOS Central European | 1 | | latin7 | latin7_general_ci | ISO 8859-13 Baltic | 1 | | utf8mb4 | utf8mb4_general_ci | UTF-8 Unicode | 4 | | cp1251 | cp1251_general_ci | Windows Cyrillic | 1 | | utf16 | utf16_general_ci | UTF-16 Unicode | 4 | | utf16le | utf16le_general_ci | UTF-16LE Unicode | 4 | | cp1256 | cp1256_general_ci | Windows Arabic | 1 | | cp1257 | cp1257_general_ci | Windows Baltic | 1 | | utf32 | utf32_general_ci | UTF-32 Unicode | 4 | | binary | binary | Binary pseudo charset | 1 | | geostd8 | geostd8_general_ci | GEOSTD8 Georgian | 1 | | cp932 | cp932_japanese_ci | SJIS for Windows Japanese | 2 | | eucjpms | eucjpms_japanese_ci | UJIS for Windows Japanese | 3 | | gb18030 | gb18030_chinese_ci | China National Standard GB18030 | 4 | +--------------------+----------------------+---------------------------------+--------+
-- character_set_name 表示字符集的名字
四、mysql中可以怎么指定字符集:
1、mysql可以在实例级别指定默认字符集、配置项名:character_set_server
2、可以在创建库的时候指定字符集
create database testdb character set utf8;
3、可以在创建表的时候指定表级的字符集
create table person(id int not null auto_increment primary key,name varchar(4)) character set utf8; -- 在表级别指定字符集是utf8
4、可以在创建表的时候指定
create table person(id int not null auto_increment primary key,name varchar(4) character set utf8); -- 指定name 列的字符集是utf8
五、有些编码不能由用户定义:
1、先看一个例子
create table user(id int auto_increment primary key,name char(8)); Query OK, 0 rows affected (0.01 sec)
这样的会在元数据中记录user这个表、别的不说表名是一定要记录在元数据中的吧!好、我们下面再看一个放荡不羁的写法
create table 用户(id int auto_increment primary key,name char(8)); Query OK, 0 rows affected (0.01 sec)
2、如果元数据用的是ascii码来保存那么“用户” 这个表名是会乱码的
select _ascii '用户'; +--------+ | | +--------+ | ?????? | +--------+ 1 row in set, 1 warning (0.00 sec)
3、那么元数据中对字符的保存用的是什么字符集呢?
show global variables like 'character_set_system'; +----------------------+-------+ | Variable_name | Value | +----------------------+-------+ | character_set_system | utf8 | +----------------------+-------+
4、给你见识一下mysql对元数据所用的字符集的保护有多强大
set @@global.character_set_system='GB2312'; ERROR 1238 (HY000): Variable 'character_set_system' is a read only variable mysql> show grants; +---------------------------------------------------------------------+ | Grants for root@localhost | +---------------------------------------------------------------------+ | GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION | | GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION | +---------------------------------------------------------------------+ 2 rows in set (0.00 sec) -- root 也不是什么都能做的!
六、中文乱码了怎么办?:
1、最为本质的原因是你用了错误的编码去查看数据、如数据是以gb2312编码的,然而你用utf8的方式去看(解码),当然会有问题。
2、从应用程序与MySQL的交互过程来分析乱码
2.1 为了使client 发过去的语句MySQL可以正确解析、所以MySQL它就要知道client发送过来的SQL语句的编码、
这个编码由character_set_client设定
2.2 为了使MySQL发过去的结果集Client 可以正确解析、所以client它就要知道MySQL发送过来的结果集的编码、
这个编码由character_set_results设定
2.3 实现上MySQL会把client 发过来的语句进行一次转码、这次转换的目标编码是由character_set_connection来设定的
3、为什么要有 character_set_connection ? 知道了character_set_client 就可以解码数据了,为什么还要转码?
我们来看一下这个例子:
select _utf8'蒋乐哥哥' = _gb2312 '蒋乐哥哥'; ERROR 1267 (HY000): Illegal mix of collations (utf8_general_ci,COERCIBLE) and (gb2312_chinese_ci,COERCIBLE) for operation '=' -- 如果两个字符集之间不能兼容的话、是不能进行操作的、所以要兼容就只能转码! select _utf8'abc' = _ascii 'abc'; +---------------------------+ | _utf8'abc' = _ascii 'abc' | +---------------------------+ | 1 | +---------------------------+ -- 两个兼容的字符集之间是可以进行操作的
4、为了让上图中的这个闭环能走通(client --sql--> mysqld --结果集--> client)
character_set_client、character_set_results、character_set_connection 要把这三个变量设置成客户
端所使用的字符集;你可以一个个的设置、但是我这里想说一个简便的方法,它就是set names
set names 'gb2312';
mysql> show variables like 'char%'; +--------------------------+------------------------------------------------------------------------+ | 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 | /usr/local/mysql-advanced-5.7.18-linux-glibc2.5-x86_64/share/charsets/ | +--------------------------+------------------------------------------------------------------------+ 8 rows in set (0.00 sec) mysql> set names 'gb2312'; Query OK, 0 rows affected (0.00 sec) mysql> show variables like 'char%'; +--------------------------+------------------------------------------------------------------------+ | Variable_name | Value | +--------------------------+------------------------------------------------------------------------+ | character_set_client | gb2312 | | character_set_connection | gb2312 | | character_set_database | utf8 | | character_set_filesystem | binary | | character_set_results | gb2312 | | character_set_server | utf8 | | character_set_system | utf8 | | character_sets_dir | /usr/local/mysql-advanced-5.7.18-linux-glibc2.5-x86_64/share/charsets/ | +--------------------------+------------------------------------------------------------------------+ 8 rows in set (0.00 sec)
5 好吧、乱码了怎么办?通过set names 'xxx'; 把字符集设置的与客户端所用的一样、4 中有例子!
----
交流学习