操作“=”的排序规则(utf8mb4_unicode_ci,EXPLICIT)和(utf8_general_ci,COERCIBLE)的非法混合

Posted

技术标签:

【中文标题】操作“=”的排序规则(utf8mb4_unicode_ci,EXPLICIT)和(utf8_general_ci,COERCIBLE)的非法混合【英文标题】:Illegal mix of collations (utf8mb4_unicode_ci,EXPLICIT) and (utf8_general_ci,COERCIBLE) for operation '=' 【发布时间】:2015-12-07 07:06:17 【问题描述】:

好吧,我放弃了。我已经遇到此错误 2 天了,我需要帮助。

免责声明:我需要帮助来改进这个问题,并会尽力描述手头的问题,到目前为止我为解决这个问题所做的工作,并分享我读过的博客文章和文档寻找解决方案。

问题(也,在下面的上下文中提出):

所以问题是,为什么相同的查询在 从 Rails 而不是从 mysql 命令行运行?具体来说, "(utf8_general_ci,COERCIBLE)" 是从哪里来的?

问题:Autoresponder.find_by(keyword: '????') 失败并出现以下错误:

ActiveRecord::StatementInvalid: Mysql2::Error: Illegal mix of collations 
(utf8mb4_unicode_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) 
for operation '=': 
SELECT  `autoresponders`.* 
FROM `autoresponders`  
WHERE `autoresponders`.`keyword` = '????' 
LIMIT 1

Autoresponder 是具有keyword 属性的模型

我读到我需要指定我的排序规则。于是我测试了以下代码:

Autoresponder.where('keyword collate utf8mb4_unicode_ci = ?', '????')

并得到以下错误:

Illegal mix of collations 
(utf8mb4_unicode_ci,EXPLICIT) and (utf8_general_ci,COERCIBLE) 
for operation '=': 
SELECT `autoresponders`.* 
FROM `autoresponders`  
WHERE (keyword collate utf8mb4_unicode_ci = '????')

所做的只是将排序规则从 IMPLICIT 更改为 EXPLICIT。

我尝试在 Sequel Pro 中运行查询并且它有效(使用和不使用 collat​​e 关键字)。为了清楚起见,这里是查询:

SELECT `autoresponders`.* 
FROM `autoresponders`  
WHERE (keyword collate utf8mb4_unicode_ci = '????');

SELECT `autoresponders`.* 
FROM `autoresponders`  
WHERE (keyword = '???? ');

而且它有效!查询运行没有错误。我还运行了mysql 并且也能够在那里运行查询。但是当我将查询粘贴到mysql 命令行时,我注意到了一些事情。它自动使用字符的 Unicode 名称而不是实际字符。这是在 mysql 命令行中观察到的查询:

SELECT `autoresponders`.* 
FROM `autoresponders`  
WHERE (keyword collate utf8mb4_unicode_ci ='\U+1F615');

此查询有效。

所以问题是,为什么相同的查询在 Rails 中失败但在 Sequel Pro 中有效?具体来说,“(utf8_general_ci,COERCIBLE)”来自哪里,我该如何解决这个烂摊子?

我认为它可能来自 ActiveRecord,但在 Rails 控制台中运行 ActiveRecord::Base.connection.collation 会返回 utf8mb4_unicode_ci

这是我的 db 字符编码和排序规则变量(以及检索它们的查询)。

SHOW VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%';
character_set_client        utf8mb4
character_set_connection    utf8mb4
character_set_database      utf8mb4
character_set_filesystem    binary
character_set_results       utf8mb4
character_set_server        latin1
character_set_system        utf8
collation_connection        utf8mb4_unicode_ci
collation_database          utf8mb4_unicode_ci
collation_server            latin1_swedish_ci

这是 Autorsponders 表的创建语法:

CREATE TABLE `autoresponders` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `keyword` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT '',
  `body` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `created_at` datetime DEFAULT NULL,
  `updated_at` datetime DEFAULT NULL,
  `provisioned_number_id` int(11) DEFAULT NULL,
  `outgoing_provisioned_number_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC;

上下文:Rails 4.0.13,Mysql 版本 5.6.22-1+deb.sury.org~precise+1-log

以下是我目前阅读的一些博客文章和 SO 文章: https://mathiasbynens.be/notes/mysql-utf8mb4

http://airbladesoftware.com/notes/fixing-mysql-illegal-mix-of-collations/

Is "SET CHARACTER SET utf8" necessary?

Illegal mix of collations (utf8_unicode_ci,IMPLICIT) and (utf8_general_ci,IMPLICIT) for operation '='

Not case sensitive search with active record

https://dev.mysql.com/doc/refman/5.0/en/server-system-variables.html#sysvar_collation_server

所有这些都让我创造了这个模因:

真诚的,

一个筋疲力尽的开发伙伴。

谢谢。

【问题讨论】:

错误信息暗示 MySQL 声称 client 正在提供 '????'作为 utf8 字符。 (应该声称是 utf8mb4。)我不知道 Ruby 和 ActiveRecord 的来龙去脉,但那是我要看的地方。 谢谢。我暂时停止处理这个问题。我可能会在几周后回到它。如果我弄清楚了,我会在这里记录答案。奇怪的是,它现在可以在开发(OS X)中工作,但不能在登台(Ubuntu)中工作 我最终通过使用 blob 而不是文本来“解决”这个问题。 另外,我们现在使用 postgres,它支持开箱即用的 4 字节字符。 【参考方案1】:

我遇到了类似的问题并最终解决了。 一开始我的 MySQL conf 是:

character-set-server = utf8
collation-server     = utf8_general_ci

有一天,我发现只有使用 utf8mb4 才能正确保存 emoji,所以我将指定列的字符集和排序规则更改如下:

  `nickname` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci,

到目前为止,一切都很好,数据可以被java web应用程序正确保存和显示。

但是当我像这样查询数据时

SELECT * FROM table_name WHERE nickname LIKE '%?%';

错误引发。

最后我把 mysql conf 改成了

character-set-server = utf8mb4
collation-server     = utf8mb4_unicode_ci

一切顺利。

还要确保SET NAMES utf8; 的任何调用都被删除或替换为SET NAMES utf8mb4

Here is a screenshot of mysql client, notice the nickname attribute

【讨论】:

如果你有一个 ruby​​ on rails 应用程序,你可以通过在你的 database.yml 中添加以下内容来更改配置 encoding: utf8mb4 charset: utf8mb4 collation: utf8mb4_unicode_ci 确保它在 3 行中(*** 打破了这些行) 请给我们看整个文件【参考方案2】:

我已经通过将列的排序规则更改为utf8mb4_unicode_ci,从 phpMyAdmin 解决了这个问题。

【讨论】:

如果你能描述一下你做了什么,那就太好了。【参考方案3】:

我在 where 语句之后添加了排序规则时遇到了同样的错误

SELECT *  FROM chat_words where source ='forum';

将排序规则 (utf8mb4_unicode_ci,COERCIBLE) 和 (utf8mb4_general_ci,COERCIBLE) 的非法混合用于操作 '='

我后来改成

SELECT *  FROM chat_words where source collate utf8mb4_unicode_ci ='forum';

这次运行没有错误

【讨论】:

【参考方案4】:

当我将我的数据库复制到其他服务器时,我遇到了同样的问题。我已将排序规则更改为 utf8mb4_general_ci,它似乎工作正常。

【讨论】:

以上是关于操作“=”的排序规则(utf8mb4_unicode_ci,EXPLICIT)和(utf8_general_ci,COERCIBLE)的非法混合的主要内容,如果未能解决你的问题,请参考以下文章

utf8mb4_unicode_ci 在 PhpMyAdmin 中选择,但 WordPress 表使用 utf8mb4_unicode_520_ci 排序规则

排序规则将 utf8mb4_unicode_ci 更改为 utf8mb4_general_ci

MySql Unicode 排序规则 utf8mb4_german2_ci 未找到 *** 德语变音符号排序规则 ***

MySQL 数据库 - 将字符集和排序规则转换为 utf8mb4 和 utf8mb4_unicode_ci?

utf8mb4_unicode_ci 与 utf8mb4_bin

解决MySQL联表时出现字符集不一样