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

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

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

业务同学线上业务执行 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 在看” 你最好看!

喜欢,就关注我吧!

图片

### JDBC 查询 MySQL 表时出现 `Illegal mix of collations` 错误的原因 当执行 SQL 查询操作(如 `'case'` 或其他运算符)时,如果涉及多个字段或表之间的比较,而这些字段具有不同的字符集或排序规则,则可能会引发 `java.sql.SQLException: Illegal mix of collations` 的异常。此错误表明参与计算的列之间存在不兼容的排序规则。 具体来说,在当前情况下,可能是某些字段使用了 `utf8mb4_general_ci` 排序规则,而另一些字段则使用了 `utf8mb4_0900_ai_ci` 排序规则[^1]。由于这两种排序规则并不完全一致,因此无法直接用于相等性判断或其他逻辑运算。 --- ### 解决方案 #### 方法一:统一字段的字符集和排序规则 可以通过修改数据库中的字段定义来确保它们都采用相同的字符集和排序规则。例如: ```sql ALTER TABLE your_table MODIFY column_name VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; ``` 通过上述语句可以将指定字段设置为与目标字段匹配的排序规则。注意替换 `your_table` 和 `column_name` 为你实际使用的表名和字段名称。 这种方法适用于能够调整数据库结构的情况,并且推荐作为长期解决方案以减少潜在问题的发生概率[^1]。 #### 方法二:强制转换数据类型 如果不允许更改现有数据库模式或者希望快速解决问题,可以在查询过程中显式地对某一侧的数据进行类型转换。比如利用 CAST 函数实现如下效果: ```sql SELECT * FROM your_table WHERE CAST(column_a AS CHAR CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci) = column_b; ``` 这里我们将 `column_a` 转换成了与 `column_b` 相同的排序规则形式后再做对比处理[^3]。尽管这种方式能够在一定程度上缓解即时需求的压力,但从性能角度考虑它可能不如方法一所述那样高效稳定。 #### 方法三:配置客户端连接参数 有时即使服务器端各对象间保持了一致性的设定仍会出现此类状况,这往往是因为客户端默认采用了不同于预期之外的编码方式所致。为此我们还可以尝试向 jdbc url 中加入额外属性来明确声明期望遵循的标准: 对于 UTF-8 编码环境而言: ```properties jdbc:mysql://localhost:3306/your_database?useUnicode=true&characterEncoding=utf8mb4&serverTimezone=UTC ``` 而对于 GBK/Gb2312 场景下可相应改为: ```properties jdbc:mysql://localhost:3306/your_database?useUnicode=true&characterEncoding=GB2312&serverTimezone=UTC ``` 这样做的目的是让驱动程序按照所给定指示加载资源从而避免不必要的误解发生. --- ### 总结 针对 `JDBC MySQL Illegal mix of collations for operation 'case'` 这类错误,主要可以从三个方面入手解决:一是标准化所有关联要素至同一套体系之下;二是借助 SQL 内置功能完成临时适配动作;三是优化外部交互接口部分使之契合内部实际情况。每种策略都有其适用范围以及局限之处,需依据项目具体情况灵活选用最佳实践路径。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值