库级别
创建数据库的时候,可以指定字符集还有排序规则。
mysql> create database test_db character set utf8mb4 collate utf8mb4_general_ci; Query OK, 1 row affected (0.01 sec)
不指定的话,就用实例级别的字符集还有排序规则。
查看当前数据库的字符集还有排序规则则是通过use
命令指定数据库之后,查看character_set_database
变量以及collation_database
来实现:
mysql> show variables like 'character_set_database'; +------------------------+---------+ | Variable_name | Value | +------------------------+---------+ | character_set_database | utf8mb4 | +------------------------+---------+ 1 row in set (0.07 sec) mysql> show variables like 'collation_database'; +--------------------+--------------------+ | Variable_name | Value | +--------------------+--------------------+ | collation_database | utf8mb4_general_ci | +--------------------+--------------------+ 1 row in set (0.09 sec)
就算设置这两个变量,也是无效的:
mysql> set character_set_database = 'utf8'; Query OK, 0 rows affected (0.00 sec) mysql> show variables like 'character_set_database'; +------------------------+---------+ | Variable_name | Value | +------------------------+---------+ | character_set_database | utf8mb4 | +------------------------+---------+ 1 row in set (0.09 sec)
修改数据库的字符集还有排序规则的方式:
mysql> alter database test_db character set = 'utf8'; Query OK, 1 row affected (0.01 sec) mysql> show variables like 'character_set_database'; +------------------------+-------+ | Variable_name | Value | +------------------------+-------+ | character_set_database | utf8 | +------------------------+-------+ 1 row in set (0.08 sec)
这个更新只会对新建的表如果没指定字符集和排序规则的生效,并不会更新老表的字符集还有排序规则。
表级别
可以在创建时指定字符集合排序规则,不指定的话,用数据库的字符集还有排序规则,也可以修改字符集和排序规则。
mysql> create table test (name varchar(32)) character set utf8mb4 collate utf8mb4_bin; Query OK, 0 rows affected (0.04 sec) mysql> show create table test; +-------+---------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +-------+---------------------------------------------------------------------------------------------------------------------------------------+ | test | CREATE TABLE `test` ( `name` varchar(32) COLLATE utf8mb4_bin DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin | +-------+---------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.09 sec) mysql> alter table test character set = 'utf8'; Query OK, 0 rows affected (0.02 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> show create table test; +-------+--------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +-------+--------------------------------------------------------------------------------------------------------------------------------------+ | test | CREATE TABLE `test` ( `name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 | +-------+--------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.06 sec)
可以看出,仅仅是表的字符集还有排序规则变了,对于已有字段,并没有改变编码和排序规则。
列级别
可以在创建表的时候,指定不同的列有不同的字符集和排序规则,也可以修改列的字符集和排序规则:
mysql> create table test (name varchar(32) character set utf8 collate utf8_bin) character set utf8mb4 collate utf8mb4_bin; Query OK, 0 rows affected (0.03 sec) mysql> show create table test; +-------+-------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +-------+-------------------------------------------------------------------------------------------------------------------------------------------------------+ | test | CREATE TABLE `test` ( `name` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin | +-------+-------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.09 sec) mysql> alter table test modify column name varchar(32) COLLATE latin1_bin; Query OK, 0 rows affected (0.09 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> show create table test; +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ | test | CREATE TABLE `test` ( `name` varchar(32) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin | +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.09 sec)
MySQL客户端字符编码问题
有时候,我们会遇到字符编码不一致导致的程序问题。例如我们的 Java 程序,使用 jdbc 链接。读取的数据,打印出来是乱码。或者是,MySQL 无法识别我们客户端发来的命令。这涉及到字符编码问题。我们需要保持 Java 程序的字符编码与 JDBC 链接指定的字符编码一致,这样才不会有乱码的问题。
**指定 Java 程序编码:**通过启动参数:-Dfile.encoding=UTF-8
设置默认的字符编码(java.nio.charset.Charset.defaultCharset();
)是utf-8
(对应 MySQL 的utf8
还有utf8mb4
)。
指定 JDBC 链接编码:
jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8
mysql客户端命令行指定字符集
mysql -h 127.0.0.1 -P 3306 -u root --default-character-set=utf8mb4 -p
之后查看有关编码的环境变量,都是和设置的这个字符集一样。
mysql> SHOW VARIABLES LIKE 'character_set_client'; +----------------------+---------+ | Variable_name | Value | +----------------------+---------+ | character_set_client | utf8mb4 | +----------------------+---------+ 1 row in set, 1 warning (0.00 sec) mysql> SHOW VARIABLES LIKE 'character_set_connection'; +--------------------------+---------+ | Variable_name | Value | +--------------------------+---------+ | character_set_connection | utf8mb4 | +--------------------------+---------+ 1 row in set, 1 warning (0.00 sec) mysql> SHOW VARIABLES LIKE 'character_set_results'; +-----------------------+---------+ | Variable_name | Value | +-----------------------+---------+ | character_set_results | utf8mb4 | +-----------------------+---------+ 1 row in set, 1 warning (0.00 sec)
其中:
character_set_client
: 服务器解码请求时使用的字符集character_set_connection
:服务器处理请求时将字符集转换成这个字符集处理。操作具体列时,在转换为具体列的编码。character_set_results
:服务器向客户端返回数据时使用的字符集
MySQL 设计这三个编码的时候,出于以下考虑:
- 一个 MySQL,可能有多种不同语言和操作系统或者国家的客户端,所以通过设置
character_set_client
还有character_set_results
进行兼容。 - 由于操作具体列数据的时候需要编码转换,如果
character_set_connection
和字段一致的话,就不用转换了,所以设置character_set_connection
可以让 MySQL 用一种编码理解命令统一处理,同时设置character_set_connection
为最常用的可以减少转换。
一般情况下,保持这三个一致就好。我们就设置好连接使用的字符集就行了。