MySQL提供多级字符集机制,其字符集分为服务器字符集、数据库字符集、表字符集、列字符集以及连接字符集和返回结果字符集等等。因此,对字符集进行设置可能会影响到数据库的正常使用,尤其会影响到涉及中文字符的那些操作。
1.引言
(1)字符集:字符集是一套符号和编码。比如对字母a, b, c进行编码,分别编码为0, 1, 2。这些字符和编码组成的字符-编码对的集合就是一个字符集。
(2)校对规则:同一字符集内的字符比较规则称为校对规则。
2.对字符集的相关操作
(1)显示MySQL服务器支持的字符集:
mysql> SHOW CHARACTER SET;
(2)显示某个字符集的校对规则:
mysql> SHOW COLLATION LIKE ‘utf8%’;
(3)显示字符集相关的系统变量:
mysql> SHOW VARIABLES LIKE ‘character%’;
1 2 3 4 5 6 7 8 9 10 11 12 13 |
mysql> SHOW VARIABLES LIKE 'character%'; +--------------------------+-----------------------------------------------------+ | Variable_name | Value | +--------------------------+-----------------------------------------------------+ | character_set_client | utf8 | | character_set_connection | utf8 | | character_set_database | utf8 | | character_set_filesystem | binary | | character_set_results | utf8 | | character_set_server | utf8 | | character_set_system | utf8 | | character_sets_dir | /opt/mysql/share/charsets/ | +--------------------------+-----------------------------------------------------+ |
其中,各变量代表的意义:
(a)character_set_client:客户端来源数据使用的字符集;
(b)character_set_connection:连接层字符集;
(c)character_set_database:当前选中数据库的默认字符集;
(d)character_set_results:查询结果字符集;
(e)character_set_server:默认的内部操作字符集;
(f)character_set_system:系统元数据(字段名等)字符集;
(4)显示字符集校对规则相关的系统变量:
mysql> SHOW VARIABLES LIKE ‘collation%’;
3.多级字符集
(1)服务器字符集和校对
服务器字符集和校对可以使用–default-character-set设置字符集,并且在字符集后面添加默认校对规则–default-collation。比如:
shell> mysqld –defualt-character-set=latinl
当前服务器的字符集和校对规则对应作系统变量character_set_server和collation_server,在运行时也可以改变这些变量的值。
(2)数据库字符集和校对
每一个数据库有一个数据库字符集和校对规则,CREATE DATABASE和ALTER DATABASE语句有一个可选的子句来指定数据库字符集和校对规则:
1 2 3 4 5 6 7 8 9 10 11 |
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; |
如果没有指定任何字符集和校对规则,则采用服务器字符集和服务器校对规则。
(3)表字符集和校对
每一个表有一个表字符集和校对规则,CREATE TABLE和ALTER TABLE语句有一个可选的子句可以用来对其进行设置:
1 2 3 4 5 6 7 8 9 |
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; |
如果没有指定任何字符集和校对规则,则采用服务器字符集和服务器校对规则。
(4)列字符集和校对
每一个“字符”列(如CHAR, VARCHAR或TEXT类型的列)有一个列字符集和校对规则。列定义语法有一个可选子句来指定列字符集和校对规则:
1 2 3 4 5 6 7 8 9 10 11 |
col_name {CHAR | VARCHAR | TEXT} (col_length) [CHARACTER SET charset_name [COLLATE collation_name]] 例如: CREATE TABLE Table1 ( column1 VARCHAR(5) CHARACTER SET latin1 COLLATE latin1_german1_ci ); |
如果没有指定任何字符集和校对规则,则采用表字符集和服务器校对规则。
(5)SET NAMES charset_name
SET NAMES charset_name语句与下面三个语句是等价的:
1 2 3 |
mysql> SET character_set_client = charset_name; mysql> SET character_set_results = charset_name; mysql> SET character_set_connection = charset_name; |
4. ERROR 1366
调试程序中,有如下报错:
ERROR 1366 Incorrect string value: ‘\xD2\xFD\xC7\xE6ME…’ for column ‘mark’ at row 1
(1)背景
源程序调用mysql C API进行插入操作,其中插入的字段包含中文字符,每次执行时都会报错:ERROR 1366 Incorrect string value: ‘\xD2\xFD\xC7\xE6ME…’ for column ‘mark’ at row 1
错误说单引号括着的十六进制表示的字符值无法插入表字段mark中去,查看源代码发现某个字段待插入的数据为中文。于是尝试将中文数据改为英文,遂插入成功。因此判断是中文编码问题导致的错误。
此为背景。
(2)调试过程
查看服务器、数据库、表以及表字段的字符集,均为utf8===》猜测mysql相关字符集设置应该没有问题;
于是在mysql的命令行界面尝试对该字段插入中文数据,成功插入===》确定mysql字符集设置没有问题的结论。
转而查看源程序:发现源代码文件的编码格式gb2312。——与mysql服务设置的utf8编码不同,因此造成了插入中文数据失败。
(3)解决办法
一种解决办法是顺应GB2312,在源程序每次调用接口函数进行INSERT操作之前调用一次SET NAMES gbk;(set names charset_name等同于哪三个操作还记得吗?查看前文)。
另一种方法是将包含待插入中文数据的源文件转码为utf8编码(notepad++可以实现转码)即可。
(4)结论
造成这个错误的主要原因是,在windows和linux两种系统下切换着工作并忘记转换文件的编码方式导致。