最近一直在弄一个有关mysql proxy的项目,中间涉及到对sql语句的解析。之前对mysql了解的并不是太多,随着项目的推进,不得不补补了。今天突然看到mysql的charset设置,自己很多地方都没法解释清楚,对一些相关的sql语句背后的工作机制一知半解,于是找了点资料补习下,顺便做点儿笔记。
一、字符集和校对规则
字符集是一套符号和编号。校对规则是在字符集内用于比较字符的一套规则。
字符(character)是人类 语言中最小的表义符号。例如字母’A’、’B’等;给定一系列字符,对每个字符赋予一个数值,用数值来代表对应的字符,这一数值就是字符的编码(Encoding)。例如,我们给字符’A’赋予数值0,给字符’B’赋予数值1,则0就是字符’A’的编码,1就是字符’B’的编码;给定一系列字符并赋予对应的编码后,所有这些字符和编码对组成的集合就是字符集(Character Set)。
校对规则(collation)是指在同一字符集内字符之间的比较规则;确定校对规则后,才能在一个字符集上定义什么是等价的字符,以及字符之间的大小关系;每个校对规则唯一对应一种字符集,但一个字符集可以对应多种校对规则,其中有一个是默认校对规则(Default Collation)。
mysql能够做这些事情:
使用多种字符集来存储字符串使用多种校对规则来比较字符串在同一台服务器、同一个
数据库或甚至在同一个表中使用不同字符集或校对规则来混合字 符串允许定义任何级别的字符集和校对规则
二、mysql的字符集和校对
mysql服务器能够支持多种字符集,可以使用show character set;语句列出可用的字符集:
要想列出校对规则可以使用show collation;语句:
两个不同的字符集不能有相同的校对规则;另外,mysql中的校对规则名称遵从命名惯例:它们以对应的字符集名称开头;以_ci(大小写不敏感)、_cs(大小写敏感)或_bin(按编码值比较)结尾。
mysql的字符集和校对规则有4个级别的默认设置:服务器级、数据库级、表级和连接级。
1、服务器字符集和校对
mysql服务器有一个服务器字符集和一个服务器校对规则,它们均不能设置为空。
mysql按照如下方法确定服务器字符集和服务器校对规则:
当服务器启动时根据有效的选项设置根据运行时的设定值
当启动mysqld时,根据使用的初始选项设置来确定服务器字符集和校对规则。可以使用--default-character-set设置字符集,并且可以在字符集后面为校对规则添加--default-collation。如果没有指定一个字符集,那就与--default-character-set=latin1相同。如果仅指定了一个字符集(例如,latin1),但是没有指定一个校对规则,那就与--default-charset=latin1 --default- collation=latin1_swedish_ci相同,因为latin1_swedish_ci是latin1的默认校对规则。因此,以下三个命令有相 同的效果:
shell> mysqld
shell> mysqld --default-character-set=latin1
shell> mysqld --default-character-set=latin1 --default-collation=latin1_swedish_ci
如果希望在从源程序构建时更改默认服务器字符集和校对规则,可以通过重新编译,使用:--with-charset和--with-collation作为configure的参量。例如:
shell> ./configure --with-charset=latin1
或者:
shell> ./configure --with-charset=latin1 --with-collation=latin1_german1_ci
mysqld和configure都验证字符集/校对规则组合是否有效。如果无效,每个程序都显示一个错误信息,然后终止。
当前的服务器字符集和校对规则可以用作character_set_server和collation_server系统变量的值。在运行时能够改变这些变量的值,从而改变运行时的服务器字符集和校对规则。
2、数据库字符集和校对
每一个数据库有一个数据库字符集和一个数据库校对规则,它不能够为空。
create database和alter database语句有一个可选的子句来指定数据库字符集和校对规则:
create database db_name
[[default] CHARACTER SET charset_name] [[default] COLLATE collation_name];
alter database db_name
[[default] CHARACTER SET charset_name] [[DEFAULT] COLLATE collation_name];
例如:
create database db_name default CHARACTER SET latin1 COLLATE latin1_swedish_ci;
mysql这样选择数据库字符集和数据库校对规则:
如果指定了CHARACTER SET X和COLLATE Y,那么采用字符集 X 和校对规则 Y 。如果指定了CHARACTER SET X而没有指定COLLATE Y,那么采用CHARACTER SET X的默认校对规则。否则,采用服务器字符集和服务器校对规则。
mysql的create database ... default CHARACTER SET ...语法与标准sql的create table ... CHARACTER SET ...语法类似。因此,可以在同一个mysql服务器上创建使用不同字符集和校对规则的数据库。
如果在create table语句中没有指定表字符集和校对规则,则使用数据库字符集和校对规则作为默认值。
默认数据库的字符集和校对规则可以用作character_set_database和 collation_database系统变量。无论何时默认数据库更改了,服务器都设置这两个变量的值。如果没有默认数据库,这两个变量与相应的服务器级别的变量(character_set_server和collation_server)具有相同的值。
3、表字符集和校对
每一个表有一个表字符集和一个校对规则,它不能为空。
为指定表字符集和校对规则,create table和alter table语句有一个可选的子句:
create table tbl_name ( column_list )
[default CHARACTER SET charset_name [COLLATE collation_name ]];
alter table tbl_name
[default CHARACTER SET charset_name] [COLLATE collation_name ]
例如:
create table t1 ( ... ) default CHARACTER SET latin1 COLLATE latin1_danish_ci;
mysql按照下面的方式选择表字符集