沈阳蓝德网站建设,网站备案后内容,公众号免费推广平台,wordpress本地nginx字符集和比较规则简介
字符集简介
我们知道在计算机中只能以二进制的方式对数据进行存储#xff0c;那么他们之间是怎样对应并进行转换的#xff1f;我们需要了解两个概念#xff1a;
字符范围#xff1a;我们可以将哪些字符转换成二进制数据#xff0c;也就是规定好字…字符集和比较规则简介
字符集简介
我们知道在计算机中只能以二进制的方式对数据进行存储那么他们之间是怎样对应并进行转换的我们需要了解两个概念
字符范围我们可以将哪些字符转换成二进制数据也就是规定好字符范围。转换过程将一个字符转换成一个二进制数据的过程也叫做编码 将一个二进制数据转换成一个字符的过程叫做解码 。
我们抽象出一个字符集的概念来描述某个字符范围的编码规则。比方说我们来自定义一个名称为 margu的字符集它包含的字符范围和编码规则如下包含字符 ‘a’ 、 ‘b’ 、 ‘A’ 、 ‘B’ 。 编码规则如下 采用1个字节编码一个字符的形式字符和字节的映射关系如下 ‘a’ - 00000001 (十六进制0x01) ‘b’ - 00000010 (十六进制0x02) ‘A’ - 00000011 (十六进制0x03) ‘B’ - 00000100 (十六进制0x04) 如果我们规定使用margu这个字符集我们就可以用二进制形式表示一些字符串了下边是一些字符串用 margu 字符集编码后的二进制表示 ‘Ba’ - 0000010000000001 (十六进制0x0401) ‘bAB’ - 000000100000001100000100 (十六进制0x020304) ‘CD’ - 无法表示字符集‘margu‘不包含字符’C’和’D’
所以如果你想表示某个字符一定要你选用的字符集支持。
比较规则简介
在我们确定了 margu字符集表示字符的范围以及编码规则后怎么比较两个字符的大小呢比较简单的就是直接比较这两个字符对应的二进制编码的大小比方说字符 ‘a’ 的编码为 0x01 字符 ‘b’ 的编码为 0x02 所以 ‘a’ 小于 ‘b’ 这种简单的比较规则也可以被称为二进制比较规则英文名为 binary collation 。 二进制比较规则是简单但有时候并不符合现实需求比如在很多场合对于英文字符我们都是不区分大小写的也就是说 ‘a’ 和 ‘A’ 是相等的在这种场合下二进制比较规则就不再适用了这时候我们可以这样指定比较规则 1 . 将两个大小写不同的字符全都转为大写或者小写。 2 . 再比较这两个字符对应的二进制数据。 这是一种稍微复杂一点的比较规则但是实际生活中的字符不止英文字符一种比如我们的汉字就有上万个对于某一种字符集来说比较两个字符大小的规则可以制定出很多种也就是说同一种字符集可以有多种比较规则后面会介绍目前常用的一些字符集以及它们的一些比较规则。
一些重要的字符集
目前字符集的种类有很多它们表示的字符范围和用到的编码规则可能都不一样。下面是一些常用的字符集
ASCII 字符集
共收录128个字符包括空格、标点符号、数字、大小写字母和一些不可见字符。由于总共128个字符所以可以使用1个字节8个bit位来进行编码我们看一些字符的编码方式 ‘A’ - 01000001十六进制0x41十进制65 ‘H’ - 01001000十六进制0x48十进制72
ISO 8859-1 字符集
共收录256个字符是在 ASCII 字符集的基础上又扩充了128个西欧常用字符(包括德法两国的字母)也可以使用1个字节来进行编码。这个字符集也有一个别名 latin1 。
GB2312 字符集
收录了汉字以及拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母。其中收录汉字6763个其他文字符号682个。同时这种字符集又兼容 ASCII 字符集所以在编码方式上显得有些奇怪
如果该字符在 ASCII 字符集中则采用1字节编码。否则采用2字节编码。
这种表示一个字符需要的字节数可能不同的编码方式称为变长编码方式 。比方说字符串 ‘爱u’ 其中 ‘爱’ 需要用2个字节进行编码编码后的十六进制表示为 0xCED2 ‘u’ 需要用1个字节进行编码编码后的十六进制表示为 0x75 所以拼合起来就是 0xCED275 。
注意如何区分某个字节代表一个单独的字符还是代表某个字符的一部分呢前面说过ASCII字符集只收录128个字符使用0127就可以表示全部字符所以如果某个字节是在0127之内的就意味着一个字节代表一个单独的字符否则就是两个字节代表一个单独的字符。
GBK 字符集
GBK 字符集只是在收录字符范围上对 GB2312 字符集作了扩充编码方式上兼容 GB2312 。
utf8
字符集收录地球上能想到的所有字符而且还在不断扩充。这种字符集兼容 ASCII 字符集采用变长编码方式编码一个字符需要使用14个字节比如 ‘A’ - 01000001十六进制0x41 ‘啊’ - 111001011001010110001010十六进制0xE5958A 注意其实准确的说utf8只是Unicode字符集的一种编码方案Unicode字符集可以采用utf8、utf16、utf32这几种编码方案utf8使用14个字节编码一个字符utf16使用2个或4个字节编码一个字符utf32使用4个字节编码一个字符。 MySQL中并不区分字符集和编码方案的概念所以后边唠叨的时候把utf8、utf16、utf32都当作 一种字符集对待。
对于同一个字符不同字符集也可能有不同的编码方式。比如对于汉字 ‘我’ 来说 ASCII 字符集中没有收录这个字符 utf8 和 gb2312 字符集对汉字 我 的编码方式如下 utf8编码111001101000100010010001 (3个字节十六进制表示是0xE68891) gb2312编码1100111011010010 (2个字节十六进制表示是0xCED2)
MySQL中支持的字符集和排序规则
MySQL中的utf8和utf8mb4
上边说过utf8 字符集表示一个字符需要使用14个字节但是我们常用的一些字符使用13个字节就可以表示了。而在Mysql中字符集表示一个字符所用最大字节长度在某些方面会影响系统的存储和性能所以Mysql衍生出utf8的两个子字符集概念 utf8mb3 精简版的utf8 字符集只使用13个字节表示字符。 utf8mb4 标准版的utf8 字符集使用14个字节表示字符。 重点注意在 MySQL 中 utf8 是 utf8mb3 的别名所以之后在 MySQL 中提到 utf8 就意味着使用1~3个字节来表示一个字符如果要想使用4字节编码一个字符的情况比如存储一些emoji表情那么需要完整指定使用utf8mb4 字符集。
字符集的查看
MySQL 支持好多好多种字符集查看当前 MySQL 中支持的字符集可以用下边这个语句 SHOW (CHARACTER SET|CHARSET) [LIKE 匹配的模式]; 其中 CHARACTER SET 和 CHARSET 是同义词用任意一个都可以。
mysql show character set;
------------------------------------------------------------------------
| Charset | Description | Default collation | Maxlen |
------------------------------------------------------------------------
| big5 | Big5 Traditional Chinese | big5_chinese_ci | 2 |
| dec8 | DEC West European | dec8_swedish_ci | 1 |
| cp850 | DOS West European | cp850_general_ci | 1 |
| hp8 | HP West European | hp8_english_ci | 1 |
| koi8r | KOI8-R Relcom Russian | koi8r_general_ci | 1 |
| latin1 | cp1252 West European | latin1_swedish_ci | 1 |
......
41 rows in set (0.00 sec)从返回的结果中可以看到目前使用的mysql5.7版本一共支持41种字符集其中的 Default collation 列表示这种字符集中一种默认的比较规则ci结尾的表示都是忽略大小写 。最后一列的Maxlen 它代表该种字符集表示一个字符最多需要几个字节。大家需要对常用的有印象如下
字符集名称描述默认比较规则最长字节数asciiUS ASCIIascii_general_ci1latin1cp1252 West Europeanlatin1_swedish_ci1gb2312GB2312 Simplified Chinesegb2312_chinese_ci2gbkGBK Simplified Chinesegbk_chinese_ci2utf8UTF-8 Unicodeutf8_general_ci3utf8mb4UTF-8 Unicodeutf8mb4_general_ci4
比较规则查看
查看 MySQL 中支持的比较规则的命令如下 SHOW COLLATION [LIKE 匹配的模式]; 一种字符集可能对应有多种比较规则 MySQL 支持的字符集就已经非常多了所以支持的比较规则更多我们先只查看一下 utf8 字符集下的比较规则
mysql 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_general_mysql500_ci | utf8 | 223 | | Yes | 1 |
--------------------------------------------------------------------
27 rows in set (0.00 sec)从返回的结果可以看到关于utf8的比较规则都有27种这些比较规则的命名有一定的规律具体规律如下
比较规则名称以与其关联的字符集的名称开头。如上图的查询结果的比较规则名称都是以 utf8 开头的。后边紧跟着该比较规则主要作用于哪种语言比如 utf8_spanish_ci 表示以西班牙语的规则比较utf8_roman_ci 是以罗马语的规则比较 utf8_general_ci 是一种通用的比较规则。 名称后缀意味着该比较规则是否区分语言中的重音、大小等具体可以用的值如下 _aiaccent insensitive 不区分重音insentive不敏感的_asaccent sensitive 区分重音_cicase insensitive 不区分大小写_cscase sensitive区分大小写_binbinary 以二进制方式进行比较 比如 utf8_general_ci 这个比较规则是以 ci 结尾的说明不区分大小写。 每种字符集对应若干种比较规则每种字符集都有一种默认的比较规则 SHOW COLLATION 的返回结果中的Default 列的值为 YES 的就是该字符集的默认比较规则比方说 utf8 字符集默认的比较规则就是utf8_general_ci 。
字符集和比较规则的应用
各级别的字符集和比较规则
MySQL 有4个级别的字符集和比较规则分别是
服务器级别数据库级别表级别列级别 接下来看看怎么查看和设置这几个级别的字符集和比较规则。
服务器级别
MySQL 提供了两个系统变量来表示服务器级别的字符集和比较规则
系统变量说明character_set_server服务器级别的字符集collation_server服务器级别的比较规则
我们看一下这两个系统变量的值记不住全称的可以用%进行匹配。
mysql show variables like %_server;
---------------------------------------
| Variable_name | Value |
---------------------------------------
| character_set_server | utf8 |
| collation_server | utf8_general_ci |
---------------------------------------
2 rows in set (0.01 sec)可以看到在我的计算机中服务器级别默认的字符集是 utf8 默认的比较规则是utf8_general_ci 。 我们可以在启动服务器程序时通过启动选项或者在服务器程序运行过程中使用 SET 语句修改这两个变量的值。比如我们可以在配置文件中这样配置 [server] character_set_servergbk collation_servergbk_chinese_ci 当服务器启动的时候读取这个配置文件后这两个系统变量的值便修改了。
数据库级别
我们在创建和修改数据库的时候可以指定该数据库的字符集和比较规则具体语法如下 CREATE DATABASE 数据库名 [[DEFAULT] CHARACTER SET 字符集名称] [[DEFAULT] COLLATE 比较规则名称];
ALTER DATABASE 数据库名 [[DEFAULT] CHARACTER SET 字符集名称] [[DEFAULT] COLLATE 比较规则名称]; 其中的 DEFAULT 可以省略并不影响语句的语义。比方说我们新创建一个名叫 charset_demo_db 的数据库在创 建的时候指定它使用的字符集为 gb2312 比较规则为 gb2312_chinese_ci
mysql create database charset_demo_db character set gb2312 collate gb2312_chinese_ci;
Query OK, 1 row affected (0.00 sec)mysql如果想查看当前数据库使用的字符集和比较规则可以查看下面两个系统变量的值前提是使用 USE 语句选择要查看的数据库如果没有指定要查看的数据库则变量与相应的服务器级系统变量具有相同的值
#未指定数据库值与服务器级别的系统变量一致
mysql show variables like %_database;
-----------------------------------------
| Variable_name | Value |
-----------------------------------------
| character_set_database | utf8 |
| collation_database | utf8_general_ci |
| skip_show_database | OFF |
-----------------------------------------
3 rows in set (0.00 sec)
mysql use charset_demo_db;
Database changed
mysql show variables like %_database;
-------------------------------------------
| Variable_name | Value |
-------------------------------------------
| character_set_database | gb2312 |
| collation_database | gb2312_chinese_ci |
| skip_show_database | OFF |
-------------------------------------------
3 rows in set (0.01 sec)可以看到这个 charset_demo_db 数据库的字符集和比较规则就是我们在创建语句中指定的。需要注意的是数据库中存在的两个变量(character_set_database、collation_database)都是只读的没法通过修改这两个变量的值来修改数据的字符集和比较规则想要修改数据库的字符集和比较规则需要在创建或者修改数据库的时手动指定character set和collation变量的值如果不指定的话则默认使用服务器级别的字符集和比较规则。
表级别
我们也可以在创建和修改表的时候指定表的字符集和比较规则语法如下 CREATE TABLE 表名 (列的信息) [[DEFAULT] CHARACTER SET 字符集名称] [COLLATE 比较规则名称]]
ALTER TABLE 表名 [[DEFAULT] CHARACTER SET 字符集名称] [COLLATE 比较规则名称] 比方说我们在刚刚创建的 charset_demo_db 数据库中创建一个名为 test 的表并指定这个表的字符集和比较规则
mysql create table test(name varchar(10) ) CHARACTER SET utf8 COLLATE utf8_general_ci;
Query OK, 0 rows affected (0.08 sec)mysql 如果创建和修改表的语句中没有指明字符集和比较规则将使用该表所在数据库的字符集和比较规则作为该表的字符集和比较规则。假设我们的创建表 test 的语句是这么写的 CREATE TABLE test(name varchar(10) ) ; 因为表test的建表语句中并没有明确指定字符集和比较规则则表test 的字符集和比较规则将继承所在数据库charset_demo_db 的字符集和比较规则也就是 gb2312 和gb2312_chinese_ci 。
列级别
需要注意的是对于存储字符串的列同一个表中的不同的列也可以有不同的字符集和比较规则。我们在创建和修改列定义的时候可以指定该列的字符集和比较规则语法如下 CREATE TABLE 表名( 列名 字符串类型 [CHARACTER SET 字符集名称] [COLLATE 比较规则名称], 其他列… ); ALTER TABLE 表名 MODIFY 列名 字符串类型 [CHARACTER SET 字符集名称] [COLLATE 比较规则名称];
比如我们修改一下表 test 中列 name的字符集和比较规则可以这么写
mysql alter table test modify name varchar(10) charset gbk collate gbk_chinese_ci;
Query OK, 0 rows affected (0.21 sec)
Records: 0 Duplicates: 0 Warnings: 0对于某个列来说如果在创建和修改的语句中没有指明字符集和比较规则将使用该列所在表的字符集和比较规则作为该列的字符集和比较规则。比方说表 test的字符集是 utf8 比较规则是 utf8_general_ci 修改列 name的 语句是这么写的 ALTER TABLE test MODIFY name VARCHAR(10); 那列name的字符集和编码将使用表test的字符集和比较规则也就是utf8和utf8_general_ci 。 注意在转换列的字符集时需要注意如果转换前列中存储的数据不能用转换后的字符集进行表示会发生错误。比方说原先列使用的字符集是utf8列中存储了一些汉字而现在把列的字符集转换为ascii的话就会出错因为ascii字符集并不能表示汉字字符。
仅修改字符集或仅修改比较规则
由于字符集和比较规则是互相有联系的如果我们只修改了字符集比较规则也会跟着变化如果只修改了比较规则字符集也会跟着变化具体规则如下
只修改字符集则比较规则将变为修改后的字符集默认的比较规则。只修改比较规则则字符集将变为修改后的比较规则对应的字符集。
不论哪个级别的字符集和比较规则这两条规则都适用下面以服务器级别的字符集和比较规则为例测试一下
只修改字符集则比较规则将变为修改后的字符集默认的比较规则。
mysql set character_set_server gb2312;
Query OK, 0 rows affected (0.00 sec)
mysql show variables like %_server;
-----------------------------------------
| Variable_name | Value |
-----------------------------------------
| character_set_server | gb2312 |
| collation_server | gb2312_chinese_ci |
-----------------------------------------
2 rows in set (0.00 sec)只修改比较规则则字符集将变为修改后的比较规则对应的字符集。
mysql set collation_server utf8_general_ci;
Query OK, 0 rows affected (0.00 sec)mysql show variables like %_server;
---------------------------------------
| Variable_name | Value |
---------------------------------------
| character_set_server | utf8 |
| collation_server | utf8_general_ci |
---------------------------------------
2 rows in set (0.00 sec)各级别字符集和比较规则小结
下面总结以上4个级别字符集和比较规则之间的联系
如果创建或修改列时没有显式的指定字符集和比较规则则该列默认用表的字符集和比较规则如果创建或修改表时没有显式的指定字符集和比较规则则该表默认用数据库的字符集和比较规则如果创建或修改数据库时没有显式的指定字符集和比较规则则该数据库默认用服务器的字符集和比较规则
知道了这些规则之后对于给定的表我们应该知道它的各个列的字符集和比较规则是什么从而根据这个列的类型来确定存储数据时每个列的实际数据占用的存储空间大小了。具体使用的字符集类型可以通过show create table test;进行查看注意表名需要修改成自己要查询的表。
客户端和服务器通信中的字符集
编码和解码使用的字符集不一致的后果
说到底字符串在计算机上的体现就是一个字节串如果你使用不同字符集去解码这个字节串最后得到的结果可能千奇百怪。 我们知道字符 ‘我’ 在 utf8 字符集编码下的字节串长这样: 0xE68891 如果一个程序把这个字节串发送到另一个程序里另一个程序用不同的字符集去解码这个字节串假设使用的是 gbk 字符集来解释这串字节解码过程就是这样的:
首先看第一个字节 0xE6 它的值大于 0x7F (十进制:127)说明是两字节编码继续读一字节后是 0xE688 然后从 gbk 编码表中查找字节为 0xE688 对应的字符发现是字符 ‘鎴’继续读一个字节 0x91 它的值也大于 0x7F 再往后读一个字节发现木有了所以这是半个字符。所以 0xE68891 被 gbk 字符集解释成一个字符 ‘鎴’ 和半个字符。
假设用 latin1 字符集去解释这串字节解码过程如下:
先读第一个字节 0xE6 它对应的 latin1 字符为 æ 。再读第二个字节 0x88 它对应的 latin1 字符为 ˆ 。再读第二个字节 0x91 它对应的 latin1 字符为 ‘ 。所以整串字节 0xE68891 被 latin1 字符集解释后的字符串就是 ‘我’ 可见如果对于同一个字符串编码和解码使用的字符集不一样会产生意想不到的结果作为使用者的我们看上去就像是产生了乱码一样。
字符集转换的概念
如果接收 0xE68891 这个字节串的程序按照 utf8 字符集进行解码然后又把它按照 gbk 字符集进行编码最后编码后的字节串就是 0xCED2 我们把这个过程称为 字符集的转换 也就是字符串 ‘我’ 从 utf8 字符集转换为gbk 字符集。
Mysql中字符集的转换
我们知道从客户端发往服务器的请求本质上就是一个字符串服务器向客户端返回的结果本质上也是一个字符串而字符串其实是使用某种字符集编码的二进制数据。这个字符串可不是使用一种字符集的编码方式一条道走到黑的从发送请求到返回结果这个过程中伴随着多次字符集的转换在这个过程中会用到3个系统变量我们先把它们写出来看一下:
系统变量描述character_set_client服务器解码请求时使用的字符集character_set_connection服务器处理请求时会把请求字符串从 character_set_client 转为 character_set_connectioncharacter_set_results服务器向客户端返回数据时使用的字符集
这几个系统变量在我的计算机上的默认值如下(不同操作系统的默认值可能不同)注意只关注上面给的几个变量其他的在测试过程中应该手动改过。
mysql show variables like character_set_%;
------------------------------------------------------------
| Variable_name | Value |
------------------------------------------------------------
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | gb2312 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | utf8 |
| character_set_system | utf8 |
| character_sets_dir | /usr/local/mysql/share/charsets/ |
------------------------------------------------------------
8 rows in set (0.01 sec)可以看到这三个系统变量的值都是 utf8 为了体现出字符集在请求处理过程中的变化我们这里特意修改 一个系统变量的值: mysql set character_set_connection gbk; Query OK, 0 rows affected (0.00 sec) 所以现在系统变量 character_set_client 和 character_set_results 的值还是 utf8 而 character_set_connection 的值为 gbk 。现在假设我们客户端发送的请求是下边这个字符串: SELECT * FROM t WHERE s ‘我’; 为了方便大家理解这个过程我们只分析字符 ‘我’ 在这个过程中字符集的转换。 现在看一下在请求从发送到结果返回过程中字符集的变化:
客户端发送请求所使用的字符集 一般情况下客户端所使用的字符集和当前操作系统一致不同操作系统使用的字符集可能不一样如下:
Linux系统使用的是 utf8Windows 使用的是 gbk 我在windows服务器上使用的xshell客户端并设置了编码格式为utf8。所以字符 ‘我’ 在发送给服务器的请求中的字节形式就是: 0xE68891 注意如果使用的是可视化工具比如securecrt/xshell之类的这些工具可以使用自定义的字符集来编码发送到服务器的字符串而不采用操作系统默认的字符集。
服务器接收到客户端发送来的请求其实是一串二进制的字节它会认为这串字节采用的字符集是 character_set_client 然后把这串字节转换为 character_set_connection 字符集编码的字符。 由于我的计算机上 character_set_client 的值是 utf8 首先会按照 utf8 字符集对字节串 0xE68891 进行解码得到的字符串就是 ‘我’ 然后按照 character_set_connection 代表的字符集也就是 gbk 进行编码得到的结果就是字节串 0xCED2 。因为表 test 的列 name 采用的是 gbk 字符集与 character_set_connection 一致所以直接到列中找字节值为 0xCED2 的记录最后找到了一条记录。 注意如果某个列使用的字符集和character_set_connection代表的字符集不一致的话还需要进行一次字符集转换。上一步骤找到的记录中的 name 列其实是一个字节串 0xCED2 name列是采用 gbk 进行编码的所以首先会将这个字节串使用 gbk 进行解码得到字符串 ‘我’ 然后再把这个字符串使用 character_set_results 代表 的字符集也就是 utf8 进行编码得到了新的字节串: 0xE68891 然后发送给客户端。由于客户端是用的字符集是 utf8 所以可以顺利的将 0xE68891 解释成字符‘我’ 从而显示到我们的显示器上所以我们使用者也正确读懂了返回的结果。 总的可以参照下面这个图来总结以上的这几个步骤 上面这个图中我们需要注意以下几个地方:
服务器认为客户端发送过来的请求是用 character_set_client 编码的。假设你的客户端采用的字符集和 character_set_client 不一样的话也就是编码和解码的规则不一样这就会出现意想不到的情况。比如我的客户端使用的是 utf8 字符集如果把系统变量 character_set_client 的值设置为 ascii 的话服务器可能无法理解我们发送的请求更别谈处理这个请求了。服务器将把得到的结果集使用 character_set_results 编码后发送给客户端。 假设你的客户端采用的字符集和 character_set_results 不一样的话这就可能会出现客户端无法解码结果 集的情况结果就是在你的屏幕上出现乱码。比如我的客户端使用的是 utf8 字符集如果把系统变量character_set_results 的值设置为 ascii 的话可能会产生乱码。character_set_connection 只是服务器在将请求的字节串从 character_set_client 转换为 character_set_connection 时使用它是什么其实没多重要但是一定要注意该字符集包含的字符范围一定要涵盖请求中的字符要不然会导致有的字符无法使用character_set_connection 代表的字符集进行编码。比如你把 character_set_client 设置为 utf8 把 character_set_connection 设置成 ascii 那么此时你如果从客户端发送一个汉字到服务器那么服务器无法使用 ascii 字符集来编码这个汉字就会向用户发出一个警告。
了解了在 MySQL 中从发送请求到返回结果过程里发生的各种字符集转换但是为啥要这样转来转去的呢?不觉得很繁琐么 答是的很繁琐所以我们通常都把 character_set_client 、character_set_connection、 character_set_results 这三个系统变量设置成和客户端使用的字符集一致的情况这样减少了很多无谓的字符集转换。为了方便我们设置 MySQL 提供了一条非常简便的语句: SET NAMES 字符集名; 这一条语句产生的效果和我们执行这3条的效果是一样的: SET character_set_client 字符集名; SET character_set_connection 字符集名; SET character_set_results 字符集名; 比方说我的客户端使用的是 utf8 字符集所以需要把这几个系统变量的值都设置为 utf8 :
mysql SET names utf8;
Query OK, 0 rows affected (0.00 sec)
mysql show variables like character_set_%;
------------------------------------------------------------
| Variable_name | Value |
------------------------------------------------------------
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | gb2312 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | utf8 |
| character_set_system | utf8 |
| character_sets_dir | /usr/local/mysql/share/charsets/ |
------------------------------------------------------------
8 rows in set (0.01 sec)注意: 如果使用的是Windows系统作为客户端也就是没有用其他的终端软件如xshell那应该设置成gbk。 另外如果你想在启动客户端的时候就把 character_set_client 、 character_set_connection 、 character_set_results 这三个系统变量的值设置成一样的那我们可以在启动客户端的时候指定一个叫 default-character-set 的启动选项比如在配置文件里可以这么写: [client] default-character-setutf8 它起到的效果和执行一遍 SET NAMES utf8 是一样一样的都会将那三个系统变量的值设置成 utf8 。
比较规则的应用
比较规则的作用通常体现比较字符串大小的表达式以及对某个字符串列进行排序所以有时候也称为排序规则 。比方说表 test 的列 name 使用的字符集是 gbk 使用的比较规则是 gbk_chinese_ci 我们向里边插入几条记录:
mysql INSERT INTO test(name) VALUES(a), (b), (A), (B);
Query OK, 4 rows affected (0.04 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql select * from test order by name;
------
| name |
------
| a |
| A |
| b |
| B |
| 我 |
------
5 rows in set (0.00 sec)
mysql 可以看到在默认的比较规则 gbk_chinese_ci 中是不区分大小写的我们现在把列 name 的比较规则修改为 gbk_bin :
mysql ALTER TABLE test MODIFY name VARCHAR(10) COLLATE gbk_bin;
Query OK, 5 rows affected (0.17 sec)
Records: 5 Duplicates: 0 Warnings: 0由于 gbk_bin 是直接比较字符的编码所以是区分大小写的我们再看一下排序后的查询结果:
mysql select * from test order by name;
------
| name |
------
| A |
| B |
| a |
| b |
| 我 |
------
5 rows in set (0.01 sec)所以如果以后大家在对字符串做比较或者对某个字符串列做排序操作时没有得到想象中的结果需要思考一下是不是字符规则的问题。
总结总的来说在选用字符集时要选择能支持表示字符的字符集并尽量精简。其次使用时尽量保证客户端服务端包括服务器级别数据库级别表级别列级别字符集及比较规则一致避免进行多次转化及转换出错。
更多关于mysql的知识分享请前往博客主页。编写过程中难免出现差错敬请指出 文章转载自: http://www.morning.lkkgq.cn.gov.cn.lkkgq.cn http://www.morning.qsyyp.cn.gov.cn.qsyyp.cn http://www.morning.sjftk.cn.gov.cn.sjftk.cn http://www.morning.ychrn.cn.gov.cn.ychrn.cn http://www.morning.pphbn.cn.gov.cn.pphbn.cn http://www.morning.qrmry.cn.gov.cn.qrmry.cn http://www.morning.ylxgw.cn.gov.cn.ylxgw.cn http://www.morning.jjzrh.cn.gov.cn.jjzrh.cn http://www.morning.qbmjf.cn.gov.cn.qbmjf.cn http://www.morning.mggwr.cn.gov.cn.mggwr.cn http://www.morning.xhkgl.cn.gov.cn.xhkgl.cn http://www.morning.fksdd.cn.gov.cn.fksdd.cn http://www.morning.hqqpy.cn.gov.cn.hqqpy.cn http://www.morning.pxrfm.cn.gov.cn.pxrfm.cn http://www.morning.zyndj.cn.gov.cn.zyndj.cn http://www.morning.pslzp.cn.gov.cn.pslzp.cn http://www.morning.prsxj.cn.gov.cn.prsxj.cn http://www.morning.rfqk.cn.gov.cn.rfqk.cn http://www.morning.jnvivi.com.gov.cn.jnvivi.com http://www.morning.rkdw.cn.gov.cn.rkdw.cn http://www.morning.mnslh.cn.gov.cn.mnslh.cn http://www.morning.qpmmg.cn.gov.cn.qpmmg.cn http://www.morning.zzjpy.cn.gov.cn.zzjpy.cn http://www.morning.wqjpl.cn.gov.cn.wqjpl.cn http://www.morning.kfqzd.cn.gov.cn.kfqzd.cn http://www.morning.lmhcy.cn.gov.cn.lmhcy.cn http://www.morning.lkgqb.cn.gov.cn.lkgqb.cn http://www.morning.plchy.cn.gov.cn.plchy.cn http://www.morning.fktlg.cn.gov.cn.fktlg.cn http://www.morning.zrkp.cn.gov.cn.zrkp.cn http://www.morning.rnxs.cn.gov.cn.rnxs.cn http://www.morning.nlcw.cn.gov.cn.nlcw.cn http://www.morning.c7498.cn.gov.cn.c7498.cn http://www.morning.rwfj.cn.gov.cn.rwfj.cn http://www.morning.qnywy.cn.gov.cn.qnywy.cn http://www.morning.mznqz.cn.gov.cn.mznqz.cn http://www.morning.lwyqd.cn.gov.cn.lwyqd.cn http://www.morning.mrbmc.cn.gov.cn.mrbmc.cn http://www.morning.wlqll.cn.gov.cn.wlqll.cn http://www.morning.pnntx.cn.gov.cn.pnntx.cn http://www.morning.kyzja.com.gov.cn.kyzja.com http://www.morning.xrksf.cn.gov.cn.xrksf.cn http://www.morning.xdnhw.cn.gov.cn.xdnhw.cn http://www.morning.kybyf.cn.gov.cn.kybyf.cn http://www.morning.xqkcs.cn.gov.cn.xqkcs.cn http://www.morning.qrwdg.cn.gov.cn.qrwdg.cn http://www.morning.dycbp.cn.gov.cn.dycbp.cn http://www.morning.wflpj.cn.gov.cn.wflpj.cn http://www.morning.nmfxs.cn.gov.cn.nmfxs.cn http://www.morning.sqmbb.cn.gov.cn.sqmbb.cn http://www.morning.wzyfk.cn.gov.cn.wzyfk.cn http://www.morning.rhqn.cn.gov.cn.rhqn.cn http://www.morning.kxwsn.cn.gov.cn.kxwsn.cn http://www.morning.krjrb.cn.gov.cn.krjrb.cn http://www.morning.xkjrs.cn.gov.cn.xkjrs.cn http://www.morning.ncqzb.cn.gov.cn.ncqzb.cn http://www.morning.bqpgq.cn.gov.cn.bqpgq.cn http://www.morning.zcqtr.cn.gov.cn.zcqtr.cn http://www.morning.bqmhm.cn.gov.cn.bqmhm.cn http://www.morning.ybhjs.cn.gov.cn.ybhjs.cn http://www.morning.nqrfd.cn.gov.cn.nqrfd.cn http://www.morning.uqrphxm.cn.gov.cn.uqrphxm.cn http://www.morning.txfzt.cn.gov.cn.txfzt.cn http://www.morning.zmlbq.cn.gov.cn.zmlbq.cn http://www.morning.kqxng.cn.gov.cn.kqxng.cn http://www.morning.dpjtn.cn.gov.cn.dpjtn.cn http://www.morning.wnwjf.cn.gov.cn.wnwjf.cn http://www.morning.rxydr.cn.gov.cn.rxydr.cn http://www.morning.lptjt.cn.gov.cn.lptjt.cn http://www.morning.mjbjq.cn.gov.cn.mjbjq.cn http://www.morning.rqrh.cn.gov.cn.rqrh.cn http://www.morning.mhnb.cn.gov.cn.mhnb.cn http://www.morning.qtwd.cn.gov.cn.qtwd.cn http://www.morning.lgnbr.cn.gov.cn.lgnbr.cn http://www.morning.ddrdt.cn.gov.cn.ddrdt.cn http://www.morning.dsncg.cn.gov.cn.dsncg.cn http://www.morning.gtkyr.cn.gov.cn.gtkyr.cn http://www.morning.ggmls.cn.gov.cn.ggmls.cn http://www.morning.qlrwf.cn.gov.cn.qlrwf.cn http://www.morning.vnuwdy.cn.gov.cn.vnuwdy.cn