前言------>>本文由浅入深,分别介绍了如下内容:
1、字符集、字符序的基本概念及联系;
2、MySQL支持的字符集、字符序设置级,各设置级别之间的联系
3、server、database、table、column级字符集、字符序的查看及设置
4、应该何时设置字符集、字符序
一、概念与联系
1、字符集(character set):定义了字符的编码规则。
2、字符序(collation):定义了字符的比较规则。
二、MySQL支持的字符集、字符集
1、查看支持的字符集,及其默认字符序(各版本或有差异,以实际情况为准)
方式一:select * from
information_schema.character_sets;
方式二:show character set; 其后可加过过滤跳条件like "%utf8%"或者 where charset = "utf8"
方式二查询字符集(character set)结果如下图:

2、查看支持的字符序,及其所属的字符集,是否是所属字符集的默认字符序
方式一:select *
from information_schema.collactions;
方式二:show collaction; 其后可加过过滤跳条件:like "%utf8%"或者where charset = "utf8"
方式二的查询字符序(collation)结果如下:

通过以上两个步骤的查询结果可知,字符序的命名规范皆以其所属的字符集名为前缀。
三、server的字符集、字符序
用途:创建数据库时未指定字符集、字符序时,server字符集、server字符序就会作为该数据库的默认字符集、排序规则。
指定:MySQL服务启动时,可通过命令行参数指定。也可以通过配置文件的变量指定。
server默认字符集、字符序:在MySQL编译的时候,通过编译参数指定。
character_set_server、collation_server分别对应server字符集、server字符序。
1、查看server字符集、字符序
分别对应character_set_server、collation_server两个系统变量。
SHOW VARIABLES LIKE "character_set_server";
SHOW VARIABLES LIKE "collation_server";

2、启动服务时指定
可以在MySQL服务启动时,指定server字符集、字符序。如不指定,默认的字符序分别为utf8mb4、utf8mb4_0900_ai_ci
mysqld --character-set-server=utf8mb4\
--collation-server=utf8mb4_0900_ai_ci
单独指定server字符集,此时,server字符序为latin1的默认字符序utf8mb4_0900_ai_ci。
mysqld --character-set-server=utf8mb4
3、配置文件指定
除了在命令行参数里指定,也可以在配置文件里指定,如下所示。
[client]:default-character-set=utf8mb4
[mysql]:default-character-set=utf8mb4
[mysqld]:collation-server = utf8mb4_0900_ai_ci
init-connect='SET NAMES utf8mb4
character-set-server = utf8mb4
4、运行时修改
例子:运行时修改(重启后会失效,如果想要重启后保持不变,需要写进配置文件里)
SET character_set_server = utf8mb4;
5、编译时指定默认字符集、字符序
character_set_server、collation_server的默认值,可以在MySQL编译时,通过编译选项指定:
cmake . -DDEFAULT_CHARSET=utf8mb4 \
-DDEFAULT_COLLATION=utf8mb4_0900_ai_ci
四、database的字符集、字符序
用途:指定数据库级别的字符集、字符序。同一个MySQL服务下的数据库,可以分别指定不同的字符集/字符序。
1、设置数据的字符集/字符序
可以在创建、修改数据库的时候,通过CHARACTER SET、COLLATE指定数据库的字符集、排序规则。
创建数据库:
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]
举个栗子:创建数据库test_db,字符集设置为utf8mb4,此时默认的排序规则为utf8mb4_0900_ai_ci:
CREATE DATABASE `test_db`
DEFAULT CHARACTER SET utf8mb4;
2、查看数据库的字符集/字符序
3种方式可以查看数据库的字符集/字符序。
方式一:查看world的字符集、排序规则。(需要切换默认数据库)
use database_name;
SELECT @@character_set_database,
@@collation_database;

方式二:通过下面系统表information_schema.SCHEMATA来查看指定的数据库的字符集、数据库(不需要切换默认数据库)
SELECT *
FROM INFORMATION_SCHEMA
WHERE
SCHEMA_NAME = 'database_name';

方式三:通过查看创建数据库的语句,来查看字符集。
show create database 'database_name';

3、database字符集、字符序的确认
创建数据库时,只指定了CHARACTER SET而未指定COLLATE,则字符序为该字符集的默认字符序;
创建数据库时,只指定了COLLATE而未指定CHARACTER SET,则字符集为该字符序所属的字符集;
创建数据库时,没有指定字符集、及其字符序,则以character_set_server、collation_server为准,即使用sever的字符集与字符序。
五、table的字符集、字符序
创建表、修改表的语法如下,可通过CHARACTER SET、COLLATE设置字符集、字符序。
CREATE TABLE tbl_name (columns)
[[DEFAULT] CHARACTER SET charset_name]
[COLLATE collation_name]]
ALTER TABLE tbl_name
[[DEFAULT] CHARACTER SET charset_name]
[COLLATE collation_name]
1、创建table并指定字符集/字符序
举个栗子:指定字符集为utf8mb4,字符序则采用默认的utf8mb4_0900_ai_ci
CREATE TABLE `test_schema`.`test_table` (
`id` INT NOT NULL COMMENT '',
PRIMARY KEY (`id`) COMMENT ''
DEFAULT CHARACTER SET = utf8mb4;
2、查看table的字符集/字符序
3种方式可以查看table的字符集/字符序。
方式一:通过命令 SHOW TABLE STATUS FROM database_name \G; 或者默认查询当前数据库 SHOW TABLE STATUS FROM \G;
如下图:Collation为utf8_bin,对应的字符集为utf8。

方式二:查看information_schema.TABLES的信息。
SELECT * FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'database_name' AND TABLE_NAME = 'table_name';

方式三:通过SHOW CREATE TABLE确认。
SHOW CREATE TABLE database_name.table_name;

3、table字符集、字符序的确定
假如CHARACTER SET值为charset_name,COLLATE值为collation_name。
创建table时:
显示明确指定了charset_name、collation_name,则采用charset_name、collation_name;
显示明确指定了charset_name,但未明确指定collation_name,则字符集采用charset_name,字符序采用charset_name对应的默认字符序;
显示明确指定了collation_name,但未明确指定charset_name,则字符序采用collation_name,字符集采用collation_name关联的字符集;
charset_name、collation_name均未显示明确指定,则采用数据库的字符集、字符序设置。
六、column的字符集、字符序
类型为CHAR、VARCHAR、TEXT的列,可以指定字符集/字符序,语法如下:
column_name {CHAR | VARCHAR | TEXT}
(col_length)
[CHARACTER SET charset_name]
[COLLATE collation_name]
1、新增column并指定字符集/排序规则(创建table类似)
ALTER TABLE table_name
ADD COLUMN char_column VARCHAR(25)
CHARACTER SET utf8mb4;
2、查看column的字符集/字符序
SELECT
CHARACTER_SET_NAME, COLLATION_NAME
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA="database_name"
AND TABLE_NAME="table_name"
AND COLUMN_NAME="cloumn_name";

3、column字符集/排序规则确定
假如CHARACTER SET值为charset_name,COLLATE值为collation_name。
若charset_name、collation_name均明确,则字符集、字符序以指定的charset_name、collation_name为准。
明确指定了charset_name,但未明确指定collation_name,则字符集为charset_name,字符序为charset_name的默认字符序。
明确指定了collation_name,但未明确指定charset_name,则字符序为collation_name,字符集为collation_name关联的字符集。
charset_name、collation_name均未明确,则以table的字符集、字符序为准。
七、字符集、字符序选择:
何时设置字符集、字符序?
一般来说,可以在三个地方进行配置:
1、创建数据库的时候进行配置;
2、mysql server启动的时候进行配置;
3、从源码编译mysql的时候,通过编译参数进行配置
方式一:创建数据库的时候进行配置
这种方式比较灵活,也比较保险,它不依赖于默认的字符集/字符序。
当你创建数据库的时候指定字符集/字符序,后续创建table、column的时候,如果不特殊指定,会继承对应数据库的字符集/字符序。
CREATE DATABASE databae_name
DEFAULT CHARACTER SET utf8mb4
DEFAULT COLLATE utf8mb4_0900_ai_ci;
方式二:mysql server启动的时候进行配置
可以添加以下配置,这样mysql server启动的时候,会对character-set-server、collation-server进行配置。
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_0900_ai_ci
当你通过mysql client创建database/table/column,且没有显示声明字符集/字符序,那么就会用character-set-server/collation-server作为默认的字符集/字符序。
另外,client、server连接时的字符集/字符序,还是需要通过SET NAMES 'utf8mb4';进行设置。
3、方式三:从源码编译mysql的时候,通过编译参数进行设置
编译时若指定了-DDEFAULT_CHARSET和-DDEFAULT_COLLATION,则:
创建database、table时,会将其作为默认的字符集/字符序;
client连接server时,则会将其作为默认的字符集/字符序,不用单独SET NAMES)。
shell> cmake .
-DDEFAULT_CHARSET=utf8mb4\
-DDEFAULT_COLLATION=utf8mb4_0900_ai_ci
八、注意点
字符集与字符序是配套使用的,交叉使用是会出错的!!!
错误栗子:

九、官方链接
https://dev.mysql.com/doc/refman/5.7/en/charset.html
十、实际工作中遇到过的情况
前几天因现网生产环境postgrepsql无法满足业务增长变化需要而要进行跨域容灾的问题,需要将postgrepsql切换未MySQL,遇到了字符类型的子段值的大写不区别,后排查发现:
建库时字符集进行显示指定了default character set utf8mb4,字符序进行了显示指定了default collate utf8mb4_bin;
但建表的DDL只显示指定了default character set = utf8mb4,但却未显示指定default collate的值,此时表table的字符序不会继承库级的字符序,而是使用了表级字符集utf8mb4默认的字符序,如下图:

utf8mb4默认的字符序即为utf8mb4_0900_ai_ci,使用这个字符序校验字符时对字母大小写时不敏感的(字符徐的后缀ci是case insensitive的缩写,意为字符大小写不敏感),而column的character set与collate均为显示明确指定,所以继承了表table级的character set与collate,从而导致了字符类型的字段值大小写不敏感的问题。
除了这个字符序的问题,还遇到文本转化的问题,即postgrepsql的text转MySQL的ext,出现长度不够的问题,经查询发现:
postgrepsql的TEXT是变长的文本类型,即长度无限制;

postgrepsql菜鸟链接:
https://www.runoob.com/postgresql/postgresql-data-type.html
但MySQL的text分为TEXT、MEDIUMTEXT、LONGTEXT,都是有长度限制的定长文本类型

MySQL的菜鸟链接:
https://www.runoob.com/mysql/mysql-data-types.html
以上均为个人学习笔记及其思考,以及个人的经历,如有不当之处,还想各位前辈们、道友们纠正、吐槽一番。




