MySQL 查询遇到Illegal mix of collations的错误

文章讲述了业务同学在执行SQL时遇到的错误,原因在于非法混合了utf8mb4_general_ci和utf8mb4_0900_ai_ci排序规则,尤其是在涉及表情符号的LIKE操作中。解决方案是使用utf8mb4_0900_ai_ci,并解释了字符集、排序规则和Unicode/UTF-8的区别。
摘要由CSDN通过智能技术生成

业务同学线上业务执行 SQL 时报错,

### Error querying database.  Cause: java.sql.SQLException: Illegal mix of collations (utf8_general_ci,IMPLICIT) and (utf8mb4_0900_ai_ci,COERCIBLE) for operation 'like'

含义是对'like'操作非法混合了排序规则(utf8mb4_general_ci,IMPLICIT)和(utf8mb4_0900_ai_ci,COERCIBLE) ,所以大致猜想应该是 collation(排序规则)设置的问题。

业务执行出问题的查询语句为:

select * from fruits
where name like concat('%','爽爆🍋','%')

可以看到,这个语句中,用到了一个表情🍋,再看这张表的排序规则是 utf8mb4_general_ci 。

那就解释通了,原因是utf8mb4_general_ci对于表情的支持不是很好,当 where 条件中使用表情时,可能会出现非预期的结果,上述的例子就是其中一种。还有比较著名的 “sushi = beer”的问题:https://bugs.mysql.com/bug.php?id=76553,也是一个场景。

那么这个问题的解决方案就是:

使用 utf8mb4_0900_ai_ci 替换utf8mb4_general_ci

在 MySQL 8.0 中,默认字符集已从 latin1 更改为 ut8mb4。默认排序规则是 utf8mb4_0900_ai_ci,这也意味着 utf8mb4_0900*是更被推荐的。

所以 utf8mb4_0900_ai_ci 是什么呢?

首先我们要明白数据库中字符集和排序规则的含义。

字符集和排序规则

字符集(Character Set)是一组编码规则,用于将字符映射到数字编码。它定义了一个字符集合,并为每个字符分配要给唯一的编码值。常见的字符集包括 ASCII、UTF-8、UTF-16、GBK 等。

排序规则(collation): 定义了字符在排序和比较操作中的规则。它决定了字符之间的顺序、大小写敏感、重音符号等。排序规则是基于字符集的,同一个字符集可以有多个排序规则可供选择。例如,对于 utf-8 字符集来说,常见的排序规则有:utf8_general_ci、utf8_bin、utf8_0900_ai_ci。对于 utf8mb4 字符集来说,对应的排序规则则是:utf8mb4_general_ci、utf8mb4_bin、utf8mb4_0900_ai_ci。

扩展一下

Unicode和UTF-8有何区别?

Unicode和UTF-8是处理字符编码的两个相关概念,它们有以下区别:

定义和范围:Unicode是一个字符集,它定义了每个字符的唯一编码点。它为世界上几乎所有的字符分配了一个唯一的编码值,包括字母、数字、标点符号、符号、表情符号等。UTF-8是一种用于表示Unicode字符的编码方案,它定义了如何将Unicode字符编码为字节序列。

编码方式:Unicode使用固定的编码点来表示字符,每个字符都有一个唯一的编码值。UTF-8是一种可变长度的编码方案,它使用1到4个字节来表示不同的Unicode字符。根据字符的范围,UTF-8使用不同长度的字节序列来编码字符,从而实现更高的存储效率。

存储效率:由于UTF-8采用可变长度编码,它可以根据字符的范围选择适当长度的字节序列进行编码。对于只包含ASCII字符(0-127)的文本,UTF-8使用单个字节表示每个字符,与ASCII编码完全兼容,因此具有较高的存储效率。对于非ASCII字符,UTF-8使用多个字节表示,根据字符的范围选择适当长度的字节序列。

兼容性:Unicode是一个字符集,不依赖于特定的存储方式。UTF-8是Unicode的一种编码方案,它可以表示Unicode字符。UTF-8是一种广泛使用的编码方案,可以在各种计算机系统和应用程序之间进行交换和共享文本数据。

简单点来说就是Unicode只定义了字符集,但是UTF-8定义了编码格式。UTF的全称是Unicode Transformation Format,UTF-8则是它其中一个变换格式,还同时定义了编码格式(可变长度编码),此外还有UTF-16、UTF-32等等。

utf8和utf8mb4有何区别?

在MySQL数据库中,UTF-8被实现为一种最多使用3个字节的编码方式,被称为"utf8"。而utf8mb4使用最多4个字节来表示不同范围的Unicode字符。

在MySQL数据库中,"utf8"字符集实际上只支持部分的UTF-8编码范围,而"utf8mb4"字符集支持完整的UTF-8编码范围。因此,如果需要存储包括表情符号在内的广泛字符集,应该选择使用"utf8mb4"字符集。

回到正题,相比于旧的编码方式,utf8mb4_0900_ai_ci具有更好的排序规则和比较性能。它是基于Unicode Collation Algorithm (UCA) 的一种改进版本,能够更准确地排序和比较Unicode字符。

其中,utf8mb4代表字符集,0900代表是Unicode 9000规范,ai代表即不区分重音符号,ci代表不区分大小写。

新版本(8.0以上版本)中推荐使用utf8mb4_0900_ai_ci。

参考:https://www.lifesailor.me/archives/2676.html
https://www.modb.pro/db/100485

图片

点个“赞 or 在看” 你最好看!

喜欢,就关注我吧!

图片

  • 6
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值