[转]MySQL5字符集支持及编码研究
前言
在更新数据库时,有时会遇到这样的错误:
Illegal mix of collations (gbk_chinese_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation '='
这是什么原因呢,先来讲一下字符集的相关知识吧。
深入分析问题
1、MySQL5的字符集支持
MySQL5.1 中的字符集支持包括在MyISAM、MEMORY和InnoDB存储引擎中。MySQL5支持多种字符集来存储字符串,对每种字符集也有相应的校对规则 (Collation)来进行比较。MySQL5还支持从服务器、数据库到数据库表、列、连接等多种级别的字符集和校对规则。
2、MySQL5字符集及校对规则
MySQL5字符集和校对规则有4个级别的默认设置:服务器级、数据库级、表级和连接级。
1)服务器字符集和校对
MySQL服务器有一个服务器字符集和一个服务器校对规则,它们均不能设置为空。
MySQL按照如下方法确定服务器字符集和服务器校对规则:
·当服务器启动时根据有效的选项设置
·根据运行时的设定值
可以通过在构建安装程序时将--with-charset和--with-collation作为configure的参数来设定服务器字符集和校对。
如 shell> ./configure --with-charset=latin1 --with-collation=latin1_german1_ci
运行时服务器字符集和校对规则是character_set_server和collation_server这两个系统变量表示的,可以通过修改它们来相应的改变。
2)数据库字符集和校对
每一个数据库有一个数据库字符集和一个数据库校对规则,它不能够为空。MySQL这样选择数据库字符集和数据库校对规则:
·如果在数据库创建SQL中指定了CHARACTER SET X和COLLATE Y,那么采用字符集X和校对规则Y。如 CREATE DATABASE db_name DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci;
·如果指定了CHARACTER SET X而没有指定COLLATE Y,那么采用CHARACTER SET X和CHARACTER SET X的默认校对规则(查看什么是默认校对规则)。
·否则,采用服务器字符集和服务器校对规则。即MYSQL系统变量character_set_server和collation_server的值
默认数据库的字符集和校对规则通过character_set_database和 collation_database系统变量的值表示。无论何时默认数据库更改了,服务器都设置这两个变量的值。如果没有 默认数据库,这两个变量与相应的服务器级别的变量(character_set_server和collation_server)具有相同的值。
3)表字符集和校对
每一个表有一个表字符集和一个校对规则,它不能为空。MySQL按照下面的方式选择表字符集和校对规则:
· 如果在创建表的SQL语句中指定了CHARACTER SET X和COLLATE Y,那么采用CHARACTER SET X和COLLATE Y。如 CREATE TABLE A DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci
·如果指定了CHARACTER SET X而没有指定COLLATE Y,那么采用CHARACTER SET X和CHARACTER SET X的默认校对规则。
·否则,采用数据库字符集和数据库校对规则。
如果在列定义中没有指定列字符集和校对规则,则默认使用表字符集和校对规则。表字符集和校对规则是MySQL的扩展;在标准SQL中没有。
4)列字符集和校对
每一个“字符”列(即,CHAR、VARCHAR或TEXT类型的列)有一个列字符集和一个列校对规则,它不能为空。MySQL按照下面的方式选择列字符集和校对规则:
·如果指定了CHARACTER SET X和COLLATE Y,那么采用CHARACTER SET X和COLLATE Y。如
CREATE TABLE Table1
(
column1 VARCHAR(5) CHARACTER SET latin1 COLLATE latin1_german1_ci
);
·如果指定了CHARACTER SET X而没有指定COLLATE Y,那么采用CHARACTER SET X和CHARACTER SET X的默认校对规则。
·否则,采用表字符集和服务器校对规则。
5)连接字符集和校对
在客户端和服务器的连接处理中也涉及了字符集和校对规则变量。它们分别是character-set-client,character-set-connnection,character-set-results,collation-connection。
客户端发送SQL语句,例如查询,通过连接发送到服务器。服务器通过连接发送响应给客户端,例如结果集。
·客户端发送查询命令及请求数据,服务器要把这些数据当做什么字符集呢?
服务器使用character_set_client变量作为客户端发送的查询中使用的字符集。
·服务器接收到查询后应该转换为哪种字符集?
转换时,服务器使用character_set_connection和collation_connection系统变量。它将客户端发送的查询从 character_set_client指定的字符集转换为character_set_connection指定的字符集(除非字符串文字具有象_latin1或 _utf8的引介词)。collation_connection对比较文字字符串是重要的。对于列值的字符串比较,它不重要,因为列具有更高的校对规则优先级。
·服务器发送结果集或返回错误信息到客户端之前应该转换为哪种字符集?
character_set_results变量指示服务器返回查询结果到客户端使用的字符集。包括结果数据,例如列值和结果元数据(如列名)。
用户可以修改这几个系统变量的值。在MYSQL中,SET NAMES 'charset_name'能够影响连接字符集
SET NAMES 'x' 语句与下列三个语句等价:
mysql> SET character_set_client = x;mysql> SET character_set_results = x;mysql> SET character_set_connection = x;
7)字符串文字字符集和校对
每一字符串字符文字有一个字符集和一个校对规则,它不能为空。一个字符串文字可能有一个可选的字符集引用介词和COLLATE子句。如 SELECT _latin1'string' COLLATE latin1_danish_ci;
MySQL这样确定一个文字字符集和校对规则:
·如果指定了CHARACTER SET X和COLLATE Y,那么使用CHARACTER SET X和COLLATE Y。
·如果指定了CHARACTER SET X而没有指定COLLATE Y,那么使用CHARACTER SET X和CHARACTER SET X的默认校对规则。
·否则,使用通过character_set_connection和collation_connection系统变量给出的字符集和校对规则。
3、异常原因分析
通过上述对MySQL5字符集和校对规则的了解,就能够很清楚的分析出前言中的异常发生的原因了:
异常发生时的MySQL字符集和校对方式情况:
character_set_connection=utf8,校对方式为utf8默认校对方式
character_set_server=utf8,校对方式为utf8默认校对方式
character_set_database=utf8,校对方式为utf8默认校对方式
对于异常 Illegal mix of collations (gbk_chinese_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation '=';
分析:其发生的SQL语句形如:SELECT COUNT(*) FROM urltable WHERE url='http://snap.xxx.com/中文';由于没有显示的指定字符串的字符集,因此MySQL采用 character_set_connection和collation_connection系统变量指定的值来处理,即utf8编码字符串,以 utf8的默认校对规则来处理'http://snap.xxx.com/中文';同时,由于列url是gbk编码的,因此MySQL对 url列采用的是gbk的字符集和gbk默认校对规则处理。因此在该SQL语句中'='两端的校对规则不一致,也就产生了先前的异常。
4、总结一下查询时的转换过程
1. MySQL Server收到请求时将请求数据从character_set_client转换为character_set_connection;
2. 进行内部操作前将请求数据从character_set_connection转换为内部操作字符集,其确定方法如下:
• 使用每个数据字段的CHARACTER SET设定值;
• 若上述值不存在,则使用对应数据表的DEFAULT CHARACTER SET设定值(MySQL扩展,非SQL标准);
• 若上述值不存在,则使用对应数据库的DEFAULT CHARACTER SET设定值;
• 若上述值不存在,则使用character_set_server设定值。
3. 将操作结果从内部操作字符集转换为character_set_results。
相关资料
• 字符(Character)是指人类语言中最小的表义符号。例如’A'、’B'等;
• 给定一系列字符,对每个字符赋予一个数值,用数值来代表对应的字符,这一数值就是字符的编码(Encoding)。例如,我们给字符’A'赋予数值0,给字符’B'赋予数值1,则0就是字符’A'的编码;
• 给定一系列字符并赋予对应的编码后,所有这些字符和编码对组成的集合就是字符集(Character Set)。例如,给定字符列表为{‘A’,'B’}时,{‘A’=>0, ‘B’=>1}就是一个字符集;
• 校对规则(Collation)是指在同一字符集内字符之间的比较规则;
• 确定校对规则后,才能在一个字符集上定义什么是等价的字符,以及字符之间的大小关系;
• 每个校对规则唯一对应一种字符集,但一个字符集可以对应多种字符序,其中有一个是默认字符序(Default Collation);
• MySQL中的校对规则名称遵从命名惯例:以字符序对应的字符集名称开头;以_ci(表示大小写不敏感)、_cs(表示大小写敏感)或_bin(表示按编码值比较)结尾。例如:在字符序“utf8_general_ci”下,字符“a”和“A”是等价的;
• 用introducer指定文本字符串的字符集:
– 格式为:[_charset] ‘string’ [COLLATE collation]
– 例如:
- SELECT _latin1 ‘string’;
- SELECT _utf8 ‘你好’ COLLATE utf8_general_ci;
– 由introducer修饰的文本字符串在请求过程中不经过多余的转码,直接转换为内部字符集处理。
参考:
http://www.laruence.com/2008/01/05/12.html
[转]MySQL5字符集支持及编码研究的更多相关文章
- 关于Unicode,字符集,字符编码,每个程序员都应该知道的事
关于Unicode,字符集,字符编码,每个程序员都应该知道的事 作者:Jack47 李笑来的文章如何判断一个人是否聪明?中提到: 必要.清晰.且准确的概念,是一切思考的基石.所谓思考,很大程度上,就是 ...
- CodePage------Encoding 类支持的编码以及与这些编码关联的代码页(CodePage)
Encoding 类 .NET Framework 4 表示字符编码. 继承层次结构 System.Object System.Text.Encoding System.Text.ASCII ...
- [转]字符集、字符编码、XML中的中文编码
字符集.字符编码.XML中的中文编码 作为程序员的你是不是对于ASCII .UNICODE.GB2321.UTF-7.UTF-8等等不时出现在你面前的这些有着奇怪意义的词感到很讨厌呢,是不是总觉得好象 ...
- 字符集、字符编码、XML中的中文编码
字符集.字符编码.XML中的中文编码 作为程序员的你是不是对于ASCII .UNICODE.GB2321.UTF-7.UTF-8等等不时出现在你面前的这些有着奇怪意义的词感到很讨厌呢,是不是总觉得好象 ...
- libiconv 支持的编码
libiconv 支持的编码 php 中的 iconv() 函数常用来作编码转换用.作一些不同编码的动态数据的转换时常遇到一些未知编码的数据,这时 iconv() 支持那些编码转换就很重要. 刚开始, ...
- 字符集、字符编码、国际化、本地化简要总结(UNICODE/UTF/ASCII/GB2312/GBK/GB18030)
PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 环境说明 普通的linux 和 普通的windows. ...
- 字符集与字符编码 (charset & encoding)
乱码是个大坑,相信每个人都遇过,而且是个绕不过去的坑.我理解每个程序员都应该写一篇编码相关的博文,梳理自己对这一块的理解,下面是我反复理解多次之后的学习小结. 1.从记事本的不同编码说起: 打开记事本 ...
- 刨根究底字符编码之十——Unicode字符集的字符编码方式CEF
Unicode字符集的字符编码方式CEF 一.字符编码方式CEF的选择 1. 由于Unicode字符集非常大,有些字符的编号(码点值)需要两个或两个以上字节来表示,而要对这样的编号进行编码,也必须使用 ...
- 让ffmpeg支持10bit编码
文章版权由作者柯O德尔和博客园共有,请尊重并支持原创,若转载请于明显处标明出处:http://www.cnblogs.com/koder/ 最近因为工作需要,要进行265 10bit编码,于是从ffm ...
随机推荐
- 转 PHP抽象类:无法实例化 (不错)
http://blog.csdn.net/kaituozheboke/article/details/52183726 一.抽象类: 无法实例化 类前加 abstract, 此类就成为抽象类,无法实例 ...
- DEV—【GridControl 按钮列无法触发点击事件解决方案】
需要在按钮列的OptionColumn属性栏中找到下面两个属性,并且改为True AllowEdit=True,AllowFocus=True.
- JDK集合框架--ArrayList
ArrayList,从类名就可以看出来,这是由数组实现的List,即内部是用数组保存元素的有序集合.先看看主要的成员变量,比较简单: public class ArrayList<E> e ...
- AJPFX总结IO流中的缓冲思想
缓冲思想 (因为内存的运算速度要远大于硬盘的原酸速度,所以只要降低硬盘的读写次数,就可以提高效率) 1. 字节流一次读写一个数组的速度明显比一次读写一个字节的速度快很多, 2. 这是加 ...
- 8.JAVA-向上转型、向下转型
父子对象之间的转换分为了向上转型和向下转型,它们区别如下: 向上转型 : 通过子类对象(小范围)实例化父类对象(大范围),这种属于自动转换 向下转型 : 通过父类对象(大范围)实例化子类对象(小范围) ...
- hihocoder编程练习赛52-1 字符串排序
思路: 将字符串按照新的顺序映射之后再排序. 实现: #include <bits/stdc++.h> using namespace std; int main() { int n; s ...
- 全志R58平台调通s5k5eya(RAW+MIPI)
全志R58平台调通s5k5eya(RAW+MIPI) 2017/5/31 10:30 版本:V1.1 1.前期使用的是s5k5eyx的ISP的固件/tuning 文件 Y:\s5k5eya_r58_d ...
- java io性能分析
摘要: 本文大多技术围绕调整磁盘文件 I/O,但是有些内容也同样适合网络 I/O 和窗口输出. 第一部分技术讨论底层的I/O问题,然后讨论诸如压缩,格式化和串行化等高级I/O问题.然而这个讨论没有包含 ...
- Okhttp3发送xml、json、文件的请求方法
1.引入依赖 <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okht ...
- 使用Gson解析Json数组遇到的泛型类型擦除问题解决方法
谷歌Gson转换Json串有如下方法: public Object fromJson(String json, Type typeOfT);1可以使用它进行数组解析.如下,使用此方法解析Json串为类 ...