了解しました。あきらめます。このエラーが発生してから2日が経過しましたが、サポートが必要です。
免責事項:私はこの質問を改善するための助けが必要であり、目前の問題、問題に対処するためにこれまでに行ったことをうまく説明し、ブログ投稿と私が読んだドキュメントを共有するように努めます。解決。
質問(また、文脈で以下に尋ねられます):
したがって、問題は、mysqlコマンドラインからではなくRailsから実行した場合、同じクエリの動作が異なるのはなぜですか?具体的には、「(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でクエリを実行してみましたが、機能しました(collateキーワードの有無にかかわらず)。わかりやすくするために、ここにクエリがあります。
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/
"SET CHARACTER SET utf8"は必要ですか?
操作 '=' の照合(utf8_unicode_ci、IMPLICIT)と(utf8_general_ci、IMPLICIT)の不正な組み合わせ
https://dev.mysql.com/doc/refman/5.0/en/server-system-variables.html#sysvar_collation_server
このすべてが私をこのミームを作成するように導きました:
よろしくお願いいたします。
疲れ果てた仲間の開発者。
ありがとう。
同様の問題に遭遇し、ようやく解決しました。最初、私のMySQLconfは次のとおりです。
character-set-server = utf8
collation-server = utf8_general_ci
ある日、utf8mb4でしか絵文字を正しく保存できないことがわかったので、指定した列の文字セットと照合順序を次のように変更します。
`nickname` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci,
今では、すべてがまだ正常であり、データはJava Webアプリケーションによって保存および正しく表示される可能性があります。
しかし、私が次のようなデータをクエリすると
SELECT * FROM table_name WHERE nickname LIKE '%????%';
エラーが発生します。
最後に、mysqlconfをに変更しました
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
そして、すべてがうまくいきます。
列の照合順序をutf8mb4_unicode_ci
に変更することで、phpMyAdminからこの問題を解決しました。
データベースを他のサーバーに複製するときにも同じ問題が発生します。照合順序をutf8mb4_general_ciに変更しましたが、正常に機能しているようです。