记录一次emoji写入到数据库发生的错误
问题描述
我在一个Web项目中,文本(content)加入了emoji的功能。
就像这样:😁👍😇
然后在调用后端接口中,报错了。
Error 3988 (HY000): Conversion from collation utf8mb3_general_ci into utf8mb4_0900_ai_ci impossible for parameter
知识点
- 字符集与排序规则:
- MySQL 使用字符集(charset)来定义存储的文本编码格式,最常见的是
utf8
和utf8mb4
。 utf8
是较旧的 UTF-8 编码格式,支持最多 3 字节的 Unicode 字符。(使用utf8
默认为utf8mb3
(UTF-8 MultiByte 3-byte)!)utf8mb4
是更新的 UTF-8 编码格式,支持最多 4 字节的 Unicode 字符,包括 Emoji 在内的所有 Unicode 字符。
- MySQL 使用字符集(charset)来定义存储的文本编码格式,最常见的是
- Emoji 和 UTF-8:
- Emoji 是 Unicode 字符的一部分,一些 Emoji 字符需要 4 字节才能正确存储和处理,因此需要使用
utf8mb4
字符集。
- Emoji 是 Unicode 字符的一部分,一些 Emoji 字符需要 4 字节才能正确存储和处理,因此需要使用
问题根因:
- 数据库表的字符集和排序规则未正确配置为
utf8mb4
,而是使用了较旧的utf8
。 - 当尝试向
utf8
字符集的表插入包含 Emoji 的文本时,MySQL 无法将utf8mb3
转换为utf8mb4
,因为utf8mb3
不支持 Emoji 和其他 4 字节的 Unicode 字符。
代码
在初始化数据库时代码需要改动:
driverName := "mysql"
user := "root"
password := "123456"
host := "localhost"
port := "3306"
database := "MyDatabase"
charset := "utf8mb4" // charset := "utf8" 是默认 utf8mb3 !
loc := "Asia/Shanghai"
args := fmt.Sprintf("%s:%s@(%s:%s)/%s?charset=%s&parseTime=true&loc=%s",
user,
password,
host,
port,
database,
charset,
url.QueryEscape(loc))
db, err := gorm.Open(driverName, args)
另外在数据库定义:
-
数据库
schema
: -
确保数据库表使用的字符集和排序规则是
utf8mb4
。- 通过修改表的
COLLATE
属性来实现,例如:ALTER TABLE your_table CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
- 通过修改表的
-
修改具体字段的字符集:
CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci
本文来自博客园,作者:江水为竭,转载请注明原文链接:https://www.cnblogs.com/Az1r/p/18257855