MySQL 04-EMOJI 表情与 UTF8MB4 的故事

2024-04-13 04:28

本文主要是介绍MySQL 04-EMOJI 表情与 UTF8MB4 的故事,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

拓展阅读

MySQL View

MySQL truncate table 与 delete 清空表的区别和坑

MySQL Ruler mysql 日常开发规范

MySQL datetime timestamp 以及如何自动更新,如何实现范围查询

MySQL 06 mysql 如何实现类似 oracle 的 merge into

MySQL 05 MySQL入门教程(MySQL tutorial book)

MySQL 04- EMOJI 表情与 UTF8MB4 的故事

MySQL Expression 1 of ORDER BY clause is not in SELECT list,references column

emoji

想在 mysql 数据库插入 emoji 表情,结果报错:

### Cause: java.sql.SQLException: Incorrect string value: '\xF0\x9F\x92\x8B' for column 'name' at row 1

错误原因很多小伙伴也知道,mysql 种的 utf8 和 java 的 utf-8 并不是完全对等的。

应该指定 mysql 的编码为 utf8mb4 才是正确的。

修改编码

查看编码

show variables like 'character_set_database'; # 查看数据库编码
show create table comment; # 查看表编码

修改数据库 & 表编码

可以在原来的基础上直接修改:

alter database <数据库名> character set utf8mb4; # 修改数据库
alter table <表名> character set utf8mb4; # 修改表
alter table <表名> change <字段名> <字段名> <类型> character set utf8mb4; # 修改字段

建表时指定

drop database echo_blog;
CREATE DATABASE echo_blog DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;drop table comment;
create table comment
(id int unsigned auto_increment comment '主键' primary key,create_time timestamp default CURRENT_TIMESTAMP not null comment '创建时间',update_time timestamp default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间'
) comment '评论信息' ENGINE=Innodb default charset=UTF8MB4 auto_increment=1;

乱码问题

修改完成之后,插入成功。

但是数据库中全部是 ??? 之类的内容,而不是表情内容。

到底哪里出问题了呢?

mysql 编码问题

查看 mysql 编码

SHOW VARIABLES WHERE Variable_name LIKE 'character_set_%' OR Variable_name LIKE 'collation%';

如下:

mysql> SHOW VARIABLES WHERE Variable_name LIKE 'character_set_%' OR Variable_name LIKE 'collation%';
+--------------------------+----------------------------------------------------+
| Variable_name            | Value                                              |
+--------------------------+----------------------------------------------------+
| character_set_client     | utf8mb4                                            |
| character_set_connection | utf8mb4                                            |
| character_set_database   | utf8mb4                                            |
| character_set_filesystem | binary                                             |
| character_set_results    | utf8mb4                                            |
| character_set_server     | utf8mb4                                            |
| character_set_system     | utf8                                               |
| character_sets_dir       | D:\tools\mysql\mysql-5.7.24-winx64\share\charsets\ |
| collation_connection     | utf8mb4_unicode_ci                                 |
| collation_database       | utf8mb4_unicode_ci                                 |
| collation_server         | utf8mb4_unicode_ci                                 |
+--------------------------+----------------------------------------------------+

属性说明:

character_set_client

主要用来设置客户端使用的字符集。通俗的讲就是mysql把客户端传递过来的数据都当成是utf8mb4

character_set_connection

主要用来设置连接数据库时的字符集,如果程序中没有指明连接数据库使用的字符集类型则按照这个字符集设置。

character_set_database

主要用来设置默认创建数据库的编码格式,如果在创建数据库时没有设置编码格式,就按照这个格式设置。

character_set_filesystem

文件系统的编码格式,把操作系统上的文件名转化成此字符集,即把 character_set_client转换character_set_filesystem, 默认binary是不做任何转换的。

character_set_results

数据库给客户端返回时使用的编码格式,如果没有指明,使用服务器默认的编码格式。通俗的讲就是mysql发送个客户端的数据是utf8mb4的

character_set_server

服务器安装时指定的默认编码格式,这个变量建议由系统自己管理,不要人为定义。

character_set_system

数据库系统使用的编码格式,这个值一直是utf8,不需要设置,它是为存储系统元数据的编码格式。

character_sets_dir

这个变量是字符集安装的目录。

Mysql的字符集内部处理

1.mysql Server收到请求时将请求数据从 character_set_client 转换为 character_set_connection

2.进行内部操作前将请求数据从 character_set_connection 转换为内部操作字符集,步骤如下

  A. 使用每个数据字段的 CHARACTER SET 设定值;

  B. 若上述值不存在,则使用对应数据表的字符集设定值

  C. 若上述值不存在,则使用对应数据库的字符集设定值;

  D. 若上述值不存在,则使用 character_set_server 设定值。

3.最后将操作结果从内部操作字符集转换为 character_set_results

mysql charsets

临时修改配置

上面的配置都可以通过命令临时修改:

SET character_set_client = utf8mb4;
SET character_set_connection = utf8mb4;
SET character_set_database = utf8mb4;
SET character_set_results = utf8mb4;
SET character_set_server = utf8mb4;SET collation_connection = utf8mb4_unicode_ci;
SET collation_database = utf8mb4_unicode_ci;
SET collation_server = utf8mb4_unicode_ci;

当然,也可以通过修改 my.ini 配置文件。

修改 mysql 服务器配置文件

比如 windows 下个人的 mysql 安装目录为:D:\tools\mysql\mysql-5.7.24-winx64

那就在下面创建 my.ini(如果没有的话)。

内容如下:

[mysql]
# 设置mysql客户端默认字符集
default-character-set=utf8mb4[mysqld]
# 设置3306端口
port=3306
# 允许最大连接数
max_connections=20
# 服务端使用的字符集默认为8比特编码的latin1字符集
character-set-server=utf8mb4
# 创建新表时将使用的默认存储引擎
default-storage-engine=INNODBcollation-server=utf8mb4_unicode_ci
init_connect='SET NAMES utf8mb4'character-set-client-handshake = FALSE
explicit_defaults_for_timestamp=true[client]
default-character-set=utf8mb4

修改完成后需要重启 mysql 服务。

可以在 bin 下执行 mysqld restart。这个实践下来只初始化了部分编码。

个人实在 windows services(服务) 下,把 mysql 服务进行了重新启动。

jdbc 配置

druid 数据源配置

spring:datasource:druid:username: rootpassword: xxxxxxurl: jdbc:mysql://localhost:3306/echo_blog?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTCdriver-class-name: com.mysql.jdbc.Driverconnection-init-sqls: set names utf8mb4;

官方资料

https://dev.mysql.com/doc/connectors/en/connector-j-reference-charsets.html

Notes
For Connector/J 8.0.12 and earlier: In order to use the utf8mb4 character set for the connection, the server MUST be configured with character_set_server=utf8mb4; if that is not the case, when UTF-8 is used for characterEncoding in the connection string, it will map to the MySQL character set name utf8, which is an alias for utf8mb3.For Connector/J 8.0.13 and later:When UTF-8 is used for characterEncoding in the connection string, it maps to the MySQL character set name utf8mb4.If the connection option connectionCollation is also set alongside characterEncoding and is incompatible with it, characterEncoding will be overridden with the encoding corresponding to connectionCollation.Because there is no Java-style character set name for utfmb3 that you can use with the connection option charaterEncoding, the only way to use utf8mb3 as your connection character set is to use a utf8mb3 collation (for example, utf8_general_ci) for the connection option connectionCollation, which forces a utf8mb3 character set to be used, as explained in the last bullet.Warning
Do not issue the query SET NAMES with Connector/J, as the driver will not detect that the character set has been changed by the query, and will continue to use the character set configured when the connection was first set up.

说明:

提示
mysql-connector-java 版本在8.0.12之前的,包括8.0.12,服务端必须设置character_set_server=utf8mb4;如果不是的话,就算设置了characterEncoding=UTF-8,照样会被设置为MYSQL的 utf8字符集,也就是utf8mb3。对于8.0.13和以后的版本,如果设置了characterEncoding=UTF-8,他会映射到MYSQL的utf8mb4字符集。如果connectionCollation 也和characterEncoding一起设置了,但是不兼容,characterEncoding会被connectionCollation的设置覆盖掉。由于没有Java-Style的utfmb3对应的字符集名称可以用在connection选项charaterEncoding上,唯一的设置utf8mb3的方式就是在连接选项设置utf8mb3 collation(例如utf8_general_ci),这会强制使用utf8mb3字符集,正如上文所述。警告
不要通过Connector发起SET NAMES指令,因为driver不会检测字符集是不是被查询语句改动,并且当连接第一次建立之后,会继续使用当时的字符集设置。

可以发现 jdbc 中的配置 connection-init-sqls: set names utf8mb4; 这句话是没啥用的。

建议老老实实的修改 mysql 服务端的配置。

依然乱码

这个时候 java 客户端保存 emoji,依然有部分乱码。

比如:

💔✊💓💖😧😯 I Love this!

用命令行查看,数据库变成了:

 �✊���� I Love this!

部分乱码? what's up?

java 程序断点

在 java 应用中进行断点,发现内容是对的。

mysql 命令行插入

我们直接在 mysql 命令行执行插入:

insert into comment (content) values ('💔✊💓💖😧😯 I Love this!');

MD,发现无法执行,这条路走不通。

命令行终端不支持 emoji 表情。

乱码的原因

这个乱码是因为 mysql 终端导致的,还是别的原因?

我们测试一下,使用 java 程序对内容进行查询。

测试代码

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class CommentServiceTest {@Autowiredprivate CommentService commentService;@Testpublic void selectTest() {Comment comment = commentService.selectById(20);System.out.println(comment);}}

测试效果

日志如下:

Comment{id=20, content=💔✊💓💖😧😯 I Love this!, ackFlag=N, createTime=Sun Aug 15 10:13:56 CST 2021, updateTime=Sun Aug 15 10:13:56 CST 2021}

可以发现,存储的数据本身是没有问题的。

是命令行终端的问题。

命令行的问题

已有的命令行

一开始使用的是 windows10 自带的 cmd,发现不行。

使用 cmder 命令行,还是不行。

powershell

我们测试下微软商店的 Terminal 命令行,也就是新版本的 powershell。

cd D:\tools\mysql\mysql-5.7.24-winx64\bin
.\mysql -uroot -p

登录后执行查询,结果如下:

💔✊💓💖😧😯 I Love this! 

纠结了半天的乱码,经确认是命令行终端的问题。

参考资料

MySQL的utf8、utf8mb4、编码问题详解

mysql字符集utf8mb4失效踩坑

Mysql UTF-8mb4字符集的问题

这篇关于MySQL 04-EMOJI 表情与 UTF8MB4 的故事的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/899131

相关文章

MySQL 表的内外连接案例详解

《MySQL表的内外连接案例详解》本文给大家介绍MySQL表的内外连接,结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录表的内外连接(重点)内连接外连接表的内外连接(重点)内连接内连接实际上就是利用where子句对两种表形成的笛卡儿积进行筛选,我

基于Python+PyQt5打造一个跨平台Emoji表情管理神器

《基于Python+PyQt5打造一个跨平台Emoji表情管理神器》在当今数字化社交时代,Emoji已成为全球通用的视觉语言,本文主要为大家详细介绍了如何使用Python和PyQt5开发一个功能全面的... 目录概述功能特性1. 全量Emoji集合2. 智能搜索系统3. 高效交互设计4. 现代化UI展示效果

MySQL的ALTER TABLE命令的使用解读

《MySQL的ALTERTABLE命令的使用解读》:本文主要介绍MySQL的ALTERTABLE命令的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、查看所建表的编China编程码格式2、修改表的编码格式3、修改列队数据类型4、添加列5、修改列的位置5.1、把列

Mybatis嵌套子查询动态SQL编写实践

《Mybatis嵌套子查询动态SQL编写实践》:本文主要介绍Mybatis嵌套子查询动态SQL编写方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言一、实体类1、主类2、子类二、Mapper三、XML四、详解总结前言MyBATis的xml文件编写动态SQL

解决mysql插入数据锁等待超时报错:Lock wait timeout exceeded;try restarting transaction

《解决mysql插入数据锁等待超时报错:Lockwaittimeoutexceeded;tryrestartingtransaction》:本文主要介绍解决mysql插入数据锁等待超时报... 目录报错信息解决办法1、数据库中执行如下sql2、再到 INNODB_TRX 事务表中查看总结报错信息Lock

MySQL启动报错:InnoDB表空间丢失问题及解决方法

《MySQL启动报错:InnoDB表空间丢失问题及解决方法》在启动MySQL时,遇到了InnoDB:Tablespace5975wasnotfound,该错误表明MySQL在启动过程中无法找到指定的s... 目录mysql 启动报错:InnoDB 表空间丢失问题及解决方法错误分析解决方案1. 启用 inno

MySQL 安装配置超完整教程

《MySQL安装配置超完整教程》MySQL是一款广泛使用的开源关系型数据库管理系统(RDBMS),由瑞典MySQLAB公司开发,目前属于Oracle公司旗下产品,:本文主要介绍MySQL安装配置... 目录一、mysql 简介二、下载 MySQL三、安装 MySQL四、配置环境变量五、配置 MySQL5.1

MySQL 添加索引5种方式示例详解(实用sql代码)

《MySQL添加索引5种方式示例详解(实用sql代码)》在MySQL数据库中添加索引可以帮助提高查询性能,尤其是在数据量大的表中,下面给大家分享MySQL添加索引5种方式示例详解(实用sql代码),... 在mysql数据库中添加索引可以帮助提高查询性能,尤其是在数据量大的表中。索引可以在创建表时定义,也可

Mybatis Plus JSqlParser解析sql语句及JSqlParser安装步骤

《MybatisPlusJSqlParser解析sql语句及JSqlParser安装步骤》JSqlParser是一个用于解析SQL语句的Java库,它可以将SQL语句解析为一个Java对象树,允许... 目录【一】jsqlParser 是什么【二】JSqlParser 的安装步骤【三】使用场景【1】sql语

MySQL 存储引擎 MyISAM详解(最新推荐)

《MySQL存储引擎MyISAM详解(最新推荐)》使用MyISAM存储引擎的表占用空间很小,但是由于使用表级锁定,所以限制了读/写操作的性能,通常用于中小型的Web应用和数据仓库配置中的只读或主要... 目录mysql 5.5 之前默认的存储引擎️‍一、MyISAM 存储引擎的特性️‍二、MyISAM 的主