暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL的字符集与字符序

释福 2021-08-30
1817

前言------>>本文由浅入深,分别介绍了如下内容:

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


    以上均为个人学习笔记及其思考,以及个人的经历,如有不当之处,还想各位前辈们、道友们纠正、吐槽一番。

文章转载自释福,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论