1,常规字符集及校对
假设我们有一个字母表使用了四个字母:‘A’、‘B’、‘a’、‘b’。我们为每个字母赋予一个数值:‘A’=0,‘B’= 1,‘a’= 2,‘b’= 3。字母‘A’是一个符号,数字0是‘A’的编码,这四个字母和它们的编码组合在一起是一个字符集。希望比较两个字符串的值:‘A’和‘B’。比较的最简单的方法是查找编码:‘A’为0,‘B’为1。因为0 小于1,我们可以说‘A’小于‘B’。我们做的仅仅是在我们的字符集上应用了一个 校对规则:对编码进行比较。在实际生活中,大多数字符集有许多字符;在实际生活中,大多数 校对规则有许多个规则。MySQL5.1能够做这些事情: · 使用多种字符集来存储字符串
· 使用多种校对规则来比较字符串
· 在同一台服务器、同一个数据库或甚至在同一个表中使用不同字符集或校对规则来混合字符串
· 允许定义任何级别的字符集和校对规则
MySQL中的字符集及其校对
使用SHOW CHARACTER SET语句列出可用的字符集。任何一个给定的字符集至少有一个校对规则。它可能有几个校对规则。
要想列出一个字符集的校对规则,使用SHOW COLLATION语句。例如,要想查看latin1(“西欧ISO-8859-1”)字符集的 校对规则,使用下面的语句查找那些名字以latin1开头的字符集的校对规则:
mysql> show collation like 'latin1%';
校对规则一般有这些特征:
· 两个不同的字符集不能有相同的校对规则。
· 每个字符集有一个默认校对规则。例如,latin1默认校对规则是latin1_swedish_ci。
· 存在校对规则命名约定:它们以其相关的字符集名开始,通常包括一个语言名,并且以_ci(大小写不敏感)、_cs(大小写敏感)或_bin(二元)结束。
MySQL服务器字符集和校对
MySQL按照如下方法确定服务器字符集和服务器校对规则:
· 当服务器启动时根据有效的选项设置
· 根据运行时的设定值
当前的服务器字符集和校对规则可以用作character_set_server和collation_server系统变量的值。在运行时能够改变这些变量的值。 启动服务器时字符集的设定:
服务器级别,确定方法很简单。当启动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
数据库字符集和校对
每一个数据库有一个数据库字符集和一个数据库校对规则,它不能够为空。CREATE DATABASE和ALTER DATABASE语句有一个可选的子句来指定数据库字符集和校对规则:
create/alter database db_name
[default] character set charset_name
[default] collate collation_name
eg:
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和CHARACTER SET X的默认校对规则。
· 否则,采用服务器字符集和服务器校对规则。
默认数据库的字符集和校对规则可以用作character_set_database和 collation_database系统变量。如果没有 默认数据库,这两个变量与相应的服务器级别的变量(character_set_server和collation_server)具有相同的值。
表字符集和校对
每一个表有一个表字符集和一个校对规则,它不能为空。为指定表字符集和校对规则,CREATE TABLE 和ALTER TABLE语句有一个可选的子句:
CREATE/alter TABLE tbl_name (column_list)
[DEFAULT CHARACTER SET charset_name [COLLATE collation_name]]
eg:
create table t1(...)
default character set latin1 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的默认校对规则。
· 否则,采用服务器字符集和服务器校对规则。
如果在列定义中没有指定列字符集和校对规则,则默认使用表字符集和校对规则。
列字符集和校对
每一个“字符”列(即,CHAR、VARCHAR或TEXT类型的列)有一个列字符集和一个列
校对规则,它不能为空。列定义语法有一个可选子句来指定列字符集和校对规则:
create table table1(
column1 varchar(5) character set latin1 collate latin1_german1_ci
);
MySQL按照下面的方式选择列字符集和校对规则:
· 如果指定了CHARACTER SET X和COLLATE Y,那么采用CHARACTER SET X和COLLATE Y。
· 如果指定了CHARACTER SET X而没有指定COLLATE Y,那么采用CHARACTER SET X和CHARACTER SET X的默认校对规则。
· 否则,采用表字符集和服务器校对规则。
示例1:表和列定义
create table t1(c1 char(19) character set latin1 collate latin1_german1_ci)
default character set latin2 collate latin2_bin;
示例2:
create table t1(
c1 char(10) character set latin1
)default character set latin1 collate latin1_danish_ci;
这次我们有一个列使用latin1字符集和一个默认校对规则。尽管它显得自然,默认校对规则却不是表级。相反,因为latin1的默认校对规则总是latin1_swedish_ci,列c1有一个校对规则latin1_swedish_ci(而不是latin1_danish_ci)。
示例3:表和列定义
create table t1(c1 char(10))default character set latin1 collate latin1_danish_ci;
我们有一个列使用一个默认字符集和一个默认校对规则。在这种情况下,MySQL查找表级别来确定列字符集和 校对规则。因此,列c1的字符集是latin1,它的 校对规则是latin1_danish_ci。
============
本文介绍的的规则是基于MYSQL5.1,低版本数据库略有不同。
请大家先理解两个概念:
引用
1.什么叫做字符集
字符集就是一套符号和字符编码的集合。
2.什么叫做校对规则
校对规则就是在字符集内用于比较字符的一套规则。
引用
MYSQL5.1数据库可以做到
· 使用多种字符集来存储字符串
· 使用多种校对规则来比较字符串
· 在同一台服务器、同一个数据库或甚至在同一个表中使用不同字符集或校对规则来混合字符串
· 允许定义任何级别的字符集和校对规则
引用
MYSQL能定义下面4种级别的字符集和校对规则:
1.服务器级别的字符集和校对规则
设置方法:mysqld --default-character-set=latin1 --default-collation=latin1_swedish_ci
2.数据库级别的字符集和校对规则
设置方法:建立库时:CREATE DATABASE db_name DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci;
修改库时:ALTER DATABASE db_name DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci;
3.表级别的字符集和校对规则
设置方法:
建表: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]
4.列级别的字符集和校对规则
设置方法:col_name {CHAR | VARCHAR | TEXT} (col_length) [CHARACTER SET charset_name [COLLATE collation_name]]
引用
连接字符集和校对规则
整个连接过程包括2个阶段,客户端发送请求,服务器端响应请求。其中涉及了3种连接过程中的字符集和校对规则:
1.当从客户端发送给服务器端的请求属于哪种字符集和校对规则
设置方法:SET character_set_client = x;
2.服务端收到请求后,应该将请求转换为哪种字符集和校对规则
设置方法:SET character_set_results = x;
3.服务端发送结果集或者错误信息给客户端用哪种字符集和校对规则
设置方法:SET character_set_connection = x;
综合设置方式:SET NAMES 'x'
这个语句等价于上面3条语句的集合,也就是3中情况都使用相同的字符集的时候,可以用这一句代替上面3句。
这样大家应该对字符集和校对规则有些了解了吧。
我来解释一下大家为什么会出现乱码的问题。其实也就是3个连接过程中的字符集和校对规则设定不匹配。
例如:数据库定义的字符集为GB2312,可是页面要求显示utf-8的,那么光配置SET NAMES 'utf8'是不能解决问题的。首先从页面将utf-8的数据传给程序,程序拿到以后就要使用utf-8的字符集将数据发送给服务器端。那么就要设置SET character_set_client = ‘utf8’;服务器端要使用GB2312的字符集存储数据或者读取数据,那么就要设置SET character_set_results = ‘GB2312’;之后服务器端再用utf8的字符集将数据返回到客户端,就要设置SET character_set_connection = ‘utf8’;这样就不会出现乱码了。
注:html页面上使用的编码为"utf-8",一般程序中使用的'utf8',这两个写法略有区别。
=========
utf8_unicode_ci与utf8_general_ci的说明:
当前,utf8_unicode_ci校对规则仅部分支持Unicode校对规则算法。一些字符还是不能支持。并且,不能完全支持组合的记号。这主要影响越南和俄罗斯的一些少数民族语言,如:Udmurt 、Tatar、Bashkir和Mari。 php程序员之家
utf8_unicode_ci的最主要的特色是支持扩展,即当把一个字母看作与其它字母组合相等时。例如,在德语和一些其它语言中‘ß’等于‘ss’。
utf8_general_ci是一个遗留的 校对规则,不支持扩展。它仅能够在字符之间进行逐个比较。这意味着utf8_general_ci校对规则进行的比较速度很快,但是与使用utf8_unicode_ci的 校对规则相比,比较正确性较差)。
例如,使用utf8_general_ci和utf8_unicode_ci两种 校对规则下面的比较相等:
Ä = A
Ö = O
Ü = U php程序员之家
两种校对规则之间的区别是,对于utf8_general_ci下面的等式成立:
ß = s
但是,对于utf8_unicode_ci下面等式成立:
ß = ss
对于一种语言仅当使用utf8_unicode_ci排序做的不好时,才执行与具体语言相关的utf8字符集 校对规则。例如,对于德语和法语,utf8_unicode_ci工作的很好,因此不再需要为这两种语言创建特殊的utf8校对规则。
utf8_general_ci也适用与德语和法语,除了‘ß’等于‘s’,而不是‘ss’之外。如果你的应用能够接受这些,那么应该使用utf8_general_ci,因为它速度快。否则,使用utf8_unicode_ci,因为它比较准确。