【MySQL管理维护-第5章】MySQL字符集三

五、字符集操作示例

通过一个最简单的示例:“向某测试表插入记录,确保写入的记录能被正确地保存,并能被正常地读取”。

先来创建一个测试表13,拥有3个列,并为每个列分别指定不同的字符集,所指定的3种字符集,也是目前MySQL环境最为常见的字符集,执行操作如下:

([email protected])[leedb]> use leedb;
Database changed
([email protected])[leedb]> 
([email protected])[leedb]> 
([email protected])[leedb]> create table t3(
    -> v1 varchar(20) charset latin1,
    -> v2 varchar(20) charset gbk,
    -> v3 varchar(20) charset utf8
    -> );
Query OK, 0 rows affected (0.05 sec)

设置当前客户端连接会话的字符集为utf8:

([email protected])[leedb]> set names utf8;
Query OK, 0 rows affected (0.00 sec)

([email protected])[leedb]> 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       | /usr/local/mysql/share/charsets/ |
+--------------------------+----------------------------------+
8 rows in set (0.01 sec)

向这个表中插入一条记录,每个列都指定相同的值,中英文字符混合:

([email protected])[leedb]> insert into t3 values (‘cn 中国‘,‘cn 中国‘,‘cn 中国‘); 
ERROR 1366 (HY000): Incorrect string value: ‘\xD6\xD0\xB9\xFA‘ for column ‘v1‘ at row 1

返回1366号错误信息,细看提示就能明白,原来在提示vl列指定了错误的字符串值,导致插入失败。这个错误提示可以理解,因为前面说过,latinl是西文字符集,并不支持中文这样的多字节字符,因此插入时就报错了。

不过,考虑到MySQL 5.6正式版本刚出不久,大部分用户仍在使用5.6之前的版本, 需要提醒大家的是,在MySQL 5.6之前版本,1366号信息并非错误,而是一条警告,也就是说在之前版本中,出现这种情况只会抛出一条警告,但插入操作仍能成功。但是,都出现警告 了,实际插入的数据出现异常的概率也就相当的高了,若是以为插入成功,但查询时才发现信息错误,那就麻烦了。因此这就需要大家更加慎重地对待,因为有时候 操作失败报错,要比操作(同样)失败报警更合理一些呐。进入5.6版本后,MySQL修改1366号的错误级别。

提示:此处1366错误级别由系统变量sql_mode来控制

sql_mode系统变量,顾名思义用来控制SQL模式,MySQL提供的模式众多,不同模式提供了不同的功能或限制条件。在MySQL 5.6版本之前,sql_mode默认为空,而进入到5.6版本后, Sql_mode、默认值改为STRICT_TRANS_TABLES,这个变量值的功能是对于支持事务的存储引擎对象,启动严格限制模式,这种情况下,就会出现插入值非法则直接报错,而非警告。

若仍然希望像5.6版本之前,插入字符串值不匹配抛出警告而非错误,则将sql_mode值改为空,如果该系统变量拥有多个值,则去除STRICT_TRANS_TABLES值即可。

下面修改一下col1待插入的值,而后再次执行INSERT语句:

([email protected])[leedb]> insert into t3 values (‘china‘,‘cn 中国‘,‘cn 中国‘); 
ERROR 1366 (HY000): Incorrect string value: ‘\xD6\xD0\xB9\xFA‘ for column ‘v2‘ at row 1

又报了几乎一模一样的错误,不过这回变成v2列字符串,即使我们继续尝试,把v2列值改一下,再次尝试插入时又会抛出错误,提示v3列的字符有误。

vl这种latinl编码的列,插入中文字符出现错误还可以理解,因为它确实不支持中文编码,但为什么v2和v3这两列也会是乱码呢?这两个一个使用gbk编码,一个基于utf8编码,应该是都能够支持中文字符的呀!

既然存储阶段的字符集设置没有问题,我们输入的字符也没有问题,那就只有一个可能:连接阶段的字符集编码不对。可是,回想一下,在操作之前,我们己经显式地指定了当前连接会话的字符集为utf8了呀,utf8能够支持中文的不是嘛?

utf8编码能够支持中文不假,但是,utf8编码格式下的“中国”,就是我们输入的“中国”这两个字符呢?这明明是gb2312或者说gbk编码的字符形式。

插入时报错,不是我们输入的不对,或者表列的字符集设置不对,而是客户端的字符集和存储所用字符集不匹配的结果。通过实际操作验证一下,先把当前客户端会话的字符集改为gbk,然后再执行相同的INSERT操作看一看:

([email protected])[leedb]> set names gbk;
Query OK, 0 rows affected (0.00 sec)

([email protected])[leedb]> insert into t3 values (‘china‘,‘cn 中国‘,‘cn 中国‘); 
Query OK, 1 row affected (0.01 sec)

([email protected])[leedb]> select * from t3;
+-------+---------+---------+
| v1    | v2      | v3      |
+-------+---------+---------+
| china | cn 中国 | cn 中国 |
+-------+---------+---------+
1 row in set (0.00 sec)

可以看到,连接时字符集和存储时的字符集一致,结果才能正常显示。

那么utf8字符集的v3列为什么也能正常显示?就是character_result系统变量的功劳了嘛,它被转换成了 gbk字符集形式.

再把连接会话的字符集改为utf8,看看表中的记录又会变成什么样呢

([email protected])[leedb]> set names utf8;
Query OK, 0 rows affected (0.00 sec)

([email protected])[leedb]> select v1,v2,v3,length(v1),length(v2),length(v3) from t3;
+-------+-----------+-----------+------------+------------+------------+
| v1    | v2        | v3        | length(v1) | length(v2) | length(v3) |
+-------+-----------+-----------+------------+------------+------------+
| china | cn 涓浗 | cn 涓浗 |          5 |          7 |          9 |
+-------+-----------+-----------+------------+------------+------------+
1 row in set (0.00 sec)

验证:

([email protected])[leedb]> insert into t3 values(‘china‘,‘cn 涓浗‘,‘cn 涓浗‘);
Query OK, 1 row affected (0.04 sec)

([email protected])[leedb]> set names gbk;
Query OK, 0 rows affected (0.00 sec)

([email protected])[leedb]> select * from t3;
+-------+---------+---------+
| v1    | v2      | v3      |
+-------+---------+---------+
| china | cn 中国 | cn 中国 |
| china | cn 中国 | cn 中国 |
+-------+---------+---------+
2 rows in set (0.00 sec)

可以看到,UTF8编码中的“cn 涓浗”正是GBK编码的“中国”。

六、字符集设置

1、字符串的字符集

字符集是针对MySQL数据库中的字符类型,我们一般设置字符集,都是对存储对象进行设置,这里还有一个很细节的问题,对于那些并非保存在数据库对象里的字符是否拥有字符集呢?比如下面这个语句:

select ‘cn 中国‘;

这个语句中的字符串有字符集吗?这点毋庸置疑,字符类型都有字符集。不过出现在SQL语句中某个角落的字符串,多数情况下我们都是理所当然地就用了,它们的字符集却被我们忽视。

针对字符串,用户可以在使用时, 通过相应语句来显式地设置字符集及校对规则,其基础语法如下:

[_charset_name]‘string‘ [COLLATE collation_name]

这其中:

[_charset_name]:指定字符集,其中_符号是固定格式,后面跟字符集名称,由于是可选项,因此一般都忽略了。

‘string‘:列或列值。

[collation_name]:指定校对规则。

下面SQL语句中选择的几个字符串的列值结果是相同的:

([email protected])[leedb]> select ‘cn 中国‘,_gbk‘cn 中国‘,_utf8‘cn 涓浗‘ collate utf8_general_ci;
+---------+---------+-----------------------------------------+
| cn 中国 | cn 中国 | _utf8‘cn 涓?浗‘ collate utf8_general_ci |
+---------+---------+-----------------------------------------+
| cn 中国 | cn 中国 | cn 中国                                 |
+---------+---------+-----------------------------------------+
1 row in set (0.00 sec)

这就是_charset_name表达式的作用,它会告诉解析器使用其后的字符串作为字符集。大多数情况下,我们都忽略了指定字符串的字符集,不管指定不指定,字符串都是有字符集的,那么MySQL是采用何种策略确定该字符串的字符集呢?这其中有一定的规则, 取决于当前的系统环境设置:

  • 如果同时指定了字符集和校对规则,则按照指定的设置。
  • 如果仅指定了校对规则,那么采用校对规则所属的字符集作为默认字符集。
  • 如果均未指定(通常都是这样),那么会按照系统变量character_set_connection和 collation_connection的设置作为默认的字符集和校对规则。

2、错误提示的字符集

服务端返回的错误或警告信息也是字符,当然也有字符集.对于MySQL服务来说,服务端固定使用utl8字符集组织错误信息,返回到客户端时,转换成character_set_results系统变量指定的字符集。

服务端在组织错误或警告信息时,按照下列的方式处理信息的几个组成部分:

  • 首先,消息模板使用utf8字符集。
  • 而后,消息模板中的参数替换成指定的错误事件,包括几个子项:

> 标识符,比如表名或者列名这类内部即使用utf8字符集的仍然用该字符集输出。

> 字符串值(不含二进制)则从原始字符集转换成utf8。

> 二进制字符串转换成字节方式表示,范围在0x20Ox7e之间,超出该范围则使用\x十六进制编码。比如说一个键复制错误,尝试插入0x41CF9F到 VARBINARY唯一列时,返回的错误信息如下:

Duplicate entry ‘A\xC3\x9f‘ for key 1

这些信息被组合后返回消息到客户端,服务器将其从utf8转换成character_set_results系统变量所指定的字符集,如果 character_set_results变量值为空或binary,那么就不会发生转换操作,当然如果该变量设置的值就是UTF8也不会发生转换。

如果信息中的字符串,不能被以character_set_results变量中所指定的字符集展示,那么转换过程中可能就会触发另外的编码方案:

  • 字符在基本多文种平面(Basic Multilingual Plane、BMP,也即Unicode编码的0号平面)范围0x0000OxFFFF区间的使用n\nnnnn标记输出。
  • 字符不在BMP范围0x01000OxlOFFFF区间的使用n\+nnnnnnn标识输出。

设置错误信息的语言

默认情况下,mysqld进程会使用英文返回错误信息,这当然不代表它只能以英文显示,实现上它还支持其他很多种语言,包括 Czech、Danish、Dutch、Estonian、French、German、

Greek、Hungarian、Italian、Japanese、Korean、Norwegian、Norwegian-ny、Polish、Portuguese、 Romanian、Russian、Slovak、Spanish或者Swedish,用户可以选择上面提到的任意一种语言来显示错误信息,遗憾的是目前还不支持中文。

如何设置错误信息的显示语言呢?

MySQL服务在启动时,会读取--lc_messages_dir选项的值,并会在该选指定的路径下查找错误信息对应的语言文件。该选项的默认路径是MySQL软件安装目录下的share目录。例如:

[[email protected] ~]$ ll /usr/local/mysql/share/
总用量 1424
drwxr-xr-x. 2 mysql mysql   4096 5月   1 22:51 aclocal
drwxr-xr-x. 2 mysql mysql   4096 5月   1 22:51 bulgarian
drwxr-xr-x. 2 mysql mysql   4096 5月   1 22:51 charsets
drwxr-xr-x. 2 mysql mysql   4096 5月   1 22:51 czech
drwxr-xr-x. 2 mysql mysql   4096 5月   1 22:51 danish
-rw-r--r--. 1 mysql mysql  25575 7月   3 2013 dictionary.txt
drwxr-xr-x. 2 mysql mysql   4096 5月   1 22:51 dutch
drwxr-xr-x. 2 mysql mysql   4096 5月   1 22:51 english
-rw-r--r--. 1 mysql mysql 503623 7月   3 2013 errmsg-utf8.txt
drwxr-xr-x. 2 mysql mysql   4096 5月   1 22:51 estonian
-rw-r--r--. 1 mysql mysql 699282 7月   3 2013 fill_help_tables.sql
drwxr-xr-x. 2 mysql mysql   4096 5月   1 22:51 french
drwxr-xr-x. 2 mysql mysql   4096 5月   1 22:51 german
drwxr-xr-x. 2 mysql mysql   4096 5月   1 22:51 greek
drwxr-xr-x. 2 mysql mysql   4096 5月   1 22:51 hungarian
-rwxr-xr-x. 1 mysql mysql   3963 7月   3 2013 innodb_memcached_config.sql
drwxr-xr-x. 2 mysql mysql   4096 5月   1 22:51 italian
drwxr-xr-x. 2 mysql mysql   4096 5月   1 22:51 japanese
drwxr-xr-x. 2 mysql mysql   4096 5月   1 22:51 korean
-rw-r--r--. 1 mysql mysql   1695 7月   3 2013 mysql_security_commands.sql
-rw-r--r--. 1 mysql mysql   3506 7月   3 2013 mysql_system_tables_data.sql
-rw-r--r--. 1 mysql mysql  92882 7月   3 2013 mysql_system_tables.sql
-rw-r--r--. 1 mysql mysql  10375 7月   3 2013 mysql_test_data_timezone.sql
drwxr-xr-x. 2 mysql mysql   4096 5月   1 22:51 norwegian
drwxr-xr-x. 2 mysql mysql   4096 5月   1 22:51 norwegian-ny
drwxr-xr-x. 2 mysql mysql   4096 5月   1 22:51 polish
drwxr-xr-x. 2 mysql mysql   4096 5月   1 22:51 portuguese
drwxr-xr-x. 2 mysql mysql   4096 5月   1 22:51 romanian
drwxr-xr-x. 2 mysql mysql   4096 5月   1 22:51 russian
drwxr-xr-x. 2 mysql mysql   4096 5月   1 22:51 serbian
drwxr-xr-x. 2 mysql mysql   4096 5月   1 22:51 slovak
drwxr-xr-x. 2 mysql mysql   4096 5月   1 22:51 spanish
drwxr-xr-x. 2 mysql mysql   4096 5月   1 22:51 swedish
drwxr-xr-x. 2 mysql mysql   4096 5月   1 22:51 ukrainian

还有一个选项--lc_messages, 这个选项就是用来指定错误信息的语言。

lc_messages_dir是个只读的系统变量,MySQL服务启动后就无法修改,它只是指定路径而己,决定语言的lc_messages系统变量则可以在MySQL服务运行时随意修改,并且既可以在全局粒度修改,也可以在会话粒度修改。

修改当前错误信息的语言为法文,即修改当前会话中lc_messages系统变量的值,执行命令如下:

([email protected])[leedb]> set lc_messages=fr_FR;
Query OK, 0 rows affected (1.81 sec)

触发个错误看看:

([email protected])[leedb]> select abc;
ERROR 1054 (42S22): Champ ‘abc‘ inconnu dans field list

上面提到的两个系统变量lc_messages_dir和lc_messages是从MySQL 5.5 版本才开始引入的,在之前的版本中,要设置语言是通过--language选项,该参数相当于-lc_messages_dir和-lc_messages的集合,比如说,仍然设置法语显示,则在MySQL 5.5之前的版本中,需要在启动时加载-language选项,执行命令如下:

$ mysqld safe --language=/usr/local/mysql55/share/french

3、国家字符集

MySQL中还存在NCHAR、NVARCHAR这样的字符类型,这其中的N代表的就是NATIONAL,这类字符类型在MySQL数据库中拥有固定的字符集设置,在MySQL 5.6版本中,使用utf8作为这种类型在存储时的字符集。

也就是说,在MySQL 5.6版本中,不管如何设置字符集,当使用N[char/varchar/text] 数据类型时,这些列的字符集均为utf8.这也是它被称为“国家字符集”的原因,拥有更好的兼容性,不管所使用的字符究竟是何种,均能够被正确支持和保存。

基于这一点,下面几种列的字义在功能上是完全相同的:

CHAR(10) CHARACTER SET utf8

NATIONAL CHARACTER(10)

NCHAR(IO)

时间: 2024-12-28 09:02:08

【MySQL管理维护-第5章】MySQL字符集三的相关文章

【MySQL管理维护-第5章】MySQL字符集一

字符集对于数据库中存储的数据来说非常之重要,特别是对于中文环境这类多字节编码的字符尤其特殊,设置不当就极有可能遇到乱码的情况. 一.关于字符集 数据库中的字符集究竟是什么?在数据库看来,字符集就是各种字符编码的一个集合.对于数据库来说,即使是同一个字符,不同的字符集在处理时它的编码格式都有可能不同. 总体来说,字符集就是指符号和字符编码的集合. 在数据库中应用字符集时,对于具体字符集的设置同样也非常的重要,为了能让字符正确地被保存,同时还能正确地被读取出来,到最终正确地显示给用户,这中间 每一个

深入浅出MySQL开发优化和管理维护学习笔记之MySQL日志文件

一.配置文件分类与参数 错误日志 数据库启停过程中错误,运行过程中的异常. 保存方式: 文件 启用方式:无需使用开关参数启用,默认开启 相关参数 文件位置参数log_error,如果不指定值默认在DATADIR目录下,名称为host_name.error. 2.二进制(bin)日志 所有DDL和DML但不包含查询语句. 保存方式: 文件 启用方式:需要配置文件中设置开关参数启用,默认关闭(OFF) 文件位置参数log_bin,如果不指定名称,名称为host_name-bin.NUM:如果只指定名

高性能MySQL笔记:第1章 MySQL架构

MySQL 最重要.最与众不同的特性是他的存储引擎架构,这种架构的设计将查询处理(Query Precessing)及其系统任务(Server Task)和数据的存储/提取相分离. 1.1 MySQL 逻辑架构 基础服务层 第一层构架 :包含连接处理.授权认证.安全等基础服务功能: 核心服务层 第二层构架 :包含查询解析.分析.优化(包括重写查询.决定表的读取顺序.选择合适的索引等).缓存以及内置函数,所有跨存储引擎的功能也在这一层实现:存储过程.触发器.视图等: 存储引擎层 第三层构架 :响应

MySQL学习笔记——第2章 MySQL的安装与配置

在Windows下安装MySQL:http://jingyan.baidu.com/article/4b07be3c67853c48b380f311.html 在Linux下安装MySQL:http://blog.itblood.com/under-linux-mysql-latest-version-installation-diagram-tutorial.html

使用MySQL管理心得讲述

今天我们要和大家一起分享的是使用MySQL管理心得,我们大家都知道在windows中MySQL数据库其是以服务形式存在的,我们在使用前应确保此服务处于启动的状态,未启动可用net start MySQL命令启动. 而Linux中启动时可用"/etc/rc.d/init.d/MySQLd start"命令,注意启动者应具有MySQL管理员权限. 刚安装好的MySQL包含一个含空密码的root帐户和一个匿名帐户,这是很大的安全隐患,对于一些重要的应用我们应将安全性尽可能提高,在这里应把匿名

第09章 mysql 字符集

2015-10-24 目录 参考资料 [1] 唐汉明.深入浅出MySQL 数据库开发.优化与管理维护(第2版)[M].北京:人民邮电出版社,2014 [2] Schwartz.高性能MySQL(第3版)[M].北京:电子工业出版社,2013 [3] 范德兰斯.MySQL开发者SQL权威指南 [M].北京:机械工业出版社,2008 [4] Forta.MySQL必知必会 [M].北京:人民邮电出版社,2009 [5] Mysql字符集设置 [6] 修改及查看mysql数据库的字符集 [7] MyS

第01章 mySQL用户和权限管理v1

韩立刚老师视频教学网站 http://www.91xueit.com 韩老师QQ458717185 第01章 MySQL用户和权限管理 mySQL权限控制通过两步控制,能不能连接(验证用户身份),能执行什么操作(验证用户权限). 验证用户身份,需要验证,连接mySQL的计算机的IP地址或计算机名称,用户账户和密码.验证过程如下: 管理mySQL用户 查看mySQL用户账户 mySQL用户存储在mysql数据库的user表,该表在mySQL服务启动时自动加载到内存,控制用户的登录. [[email

第15章 mysql 用户、权限管理

2015-10-24 目录 参考资料 [1] 唐汉明.深入浅出MySQL 数据库开发.优化与管理维护(第2版)[M].北京:人民邮电出版社,2014 [2] Schwartz.高性能MySQL(第3版)[M].北京:电子工业出版社,2013 [3] 范德兰斯.MySQL开发者SQL权威指南 [M].北京:机械工业出版社,2008 [4] Forta.MySQL必知必会 [M].北京:人民邮电出版社,2009 [5] Chapter 6 Security [6] 5.7. MySQL访问权限系统

(DBA之路十)《深入浅出MySQL数据库开发优化与管理维护》的读书笔记

1>mysql的配置文件在/etc下的my.cnf 2)mysql服务是一系列后台进程,mysql数据库是一系列数据目录和数据文件 mysql数据库必须在mysql服务启动之后才可以进行访问 3)查看mysql服务的状态: netstat -nlp 4)启动/关闭服务 cd /usr/bin ./mysqld_safe & mysqladmin -uroot shutdown 5)PRM包安装的启动/关闭服务 service mysql start service mysql restart