前言

在更新数据库时,有时会遇到这样的错误:

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字符集支持及编码研究的更多相关文章

  1. 关于Unicode,字符集,字符编码,每个程序员都应该知道的事

    关于Unicode,字符集,字符编码,每个程序员都应该知道的事 作者:Jack47 李笑来的文章如何判断一个人是否聪明?中提到: 必要.清晰.且准确的概念,是一切思考的基石.所谓思考,很大程度上,就是 ...

  2. CodePage------Encoding 类支持的编码以及与这些编码关联的代码页(CodePage)

    Encoding 类 .NET Framework 4  表示字符编码. 继承层次结构 System.Object  System.Text.Encoding    System.Text.ASCII ...

  3. [转]字符集、字符编码、XML中的中文编码

    字符集.字符编码.XML中的中文编码 作为程序员的你是不是对于ASCII .UNICODE.GB2321.UTF-7.UTF-8等等不时出现在你面前的这些有着奇怪意义的词感到很讨厌呢,是不是总觉得好象 ...

  4. 字符集、字符编码、XML中的中文编码

    字符集.字符编码.XML中的中文编码 作为程序员的你是不是对于ASCII .UNICODE.GB2321.UTF-7.UTF-8等等不时出现在你面前的这些有着奇怪意义的词感到很讨厌呢,是不是总觉得好象 ...

  5. libiconv 支持的编码

    libiconv 支持的编码 php 中的 iconv() 函数常用来作编码转换用.作一些不同编码的动态数据的转换时常遇到一些未知编码的数据,这时 iconv() 支持那些编码转换就很重要. 刚开始, ...

  6. 字符集、字符编码、国际化、本地化简要总结(UNICODE/UTF/ASCII/GB2312/GBK/GB18030)

    PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 环境说明   普通的linux 和 普通的windows.    ...

  7. 字符集与字符编码 (charset & encoding)

    乱码是个大坑,相信每个人都遇过,而且是个绕不过去的坑.我理解每个程序员都应该写一篇编码相关的博文,梳理自己对这一块的理解,下面是我反复理解多次之后的学习小结. 1.从记事本的不同编码说起: 打开记事本 ...

  8. 刨根究底字符编码之十——Unicode字符集的字符编码方式CEF

    Unicode字符集的字符编码方式CEF 一.字符编码方式CEF的选择 1. 由于Unicode字符集非常大,有些字符的编号(码点值)需要两个或两个以上字节来表示,而要对这样的编号进行编码,也必须使用 ...

  9. 让ffmpeg支持10bit编码

    文章版权由作者柯O德尔和博客园共有,请尊重并支持原创,若转载请于明显处标明出处:http://www.cnblogs.com/koder/ 最近因为工作需要,要进行265 10bit编码,于是从ffm ...

随机推荐

  1. Android开发学习—— 消息机制

    ###主线程不能被阻塞* 在Android中,主线程被阻塞会导致应用不能刷新ui界面,不能响应用户操作,用户体验将非常差* 主线程阻塞时间过长,系统会抛出ANR异常* ANR:Application ...

  2. MyEclipse开启Jquery智能提示

    myeclipse 增加javascript提示和jquery提示等不用安装插件自带功能 (对着需要提示的项目右键,点击properties) 不行的话就得安装插件: http://www.spket ...

  3. WPF学习07:MVVM 预备知识之数据绑定

    MVVM是一种模式,而WPF的数据绑定机制是一种WPF内建的功能集,两者是不相关的. 但是,借助WPF各种内建功能集,如数据绑定.命令.数据模板,我们可以高效的在WPF上实现MVVM.因此,我们需要对 ...

  4. @GetMapping和@PostMapping 和@RequestMapping区别

    @GetMapping 用于将HTTP GET请求映射到特定处理程序方法的注释. 具体来说,@GetMapping是一个作为快捷方式的组合注释@RequestMapping(method = Requ ...

  5. Activity的四种启动模式区别

    (1) standard 模式启动模式,每次激活Activity时都会创建Activity,并放入任务栈中. (2) singleTop 如果在任务的栈顶正好存在该Activity的实例, 就重用该实 ...

  6. XCode的debug断点调试

    debug 流程控制 当你通过 Xcode 的源码编辑器的侧边槽 (或者通过下面的方法) 插入一个断点,程序到达断点时会就会停止运行. 调试条上会出现四个你可以用来控制程序的执行流程的按钮. 从左到右 ...

  7. SQL——连接查询、聚合函数、开窗函数、分组功能、联合查询、子查询

    连接查询 inner join,用的最多,表示多张表一一对应 聚合函数 操作行数据,进行合并 sum.avg.count.max.min 开窗函数 将合并的数据分布到原表的每一行,相当于多出来了一列, ...

  8. 微擎we7模块和模板安装方法

    2017年06月08日 09:26:55 源码学习分享 阅读数:15643 标签: we7 更多 个人分类: 微擎we7   版权声明:本文为博主原创文章,未经博主允许不得转载. https://bl ...

  9. 关于Maven项目的pom.xml中的依赖或插件失效的解决方法

    1.请将<dependency>标签包含的依赖从<dependencyManagement>中拿出来,单独放在<dependencies>标签里面.2.请将< ...

  10. bootstrap不兼容ie8如何解决

    说起bootstrap大家一定都不陌生,可以说是目前最受欢迎的前端框架,简洁.直观.强悍.移动设备优先的前端开发框架,让web开发更迅速.简单. 但是在实际运用中也会遇到各种各样的问题,比如最近项目中 ...