私の質問はここにあるものとほぼ同じです
MySQL - 1300 - 更新時の無効な utf8 文字列
解決策は提示されず、その人の助け (一時テーブルの作成) は役に立たないようでした。私が使用している選択ステートメントは次のとおりです。
SELECT
CONVERT(line_1 USING utf8mb4),
CONVERT(line_1 USING latin1),
HEX(line_1)
FROM address
WHERE ((CAST(CONVERT(line_1 USING latin1) AS CHAR)) <> (CAST(line_1 AS CHAR)))
AND CONVERT(line_1 USING utf8mb4) IS NULL;
+-------------------------------+------------------------------+----------------------------------------------------+
| CONVERT(line_1 USING utf8mb4) | CONVERT(line_1 USING latin1) | hex(line_1) |
+-------------------------------+------------------------------+----------------------------------------------------+
| NULL | Högbergsgatan 97 | 48F6676265726773676174616E203937 |
| NULL | Zücherstrasse 161 | 5AFC636865727374726173736520313631 |
| NULL | 2275, Rue de l'Université | 323237352C20527565206465206C27556E69766572736974E9 |
| NULL | Högbergsgatan 97 | 48F6676265726773676174616E203937 |
+-------------------------------+------------------------------+----------------------------------------------------+
次の更新コマンドを実行しようとすると、次のようになります。
UPDATE address
SET line_1 = CONVERT(CAST(CONVERT(line_1 USING latin1) AS CHAR) USING utf8mb4)
WHERE (CAST(CONVERT(line_1 USING latin1) AS CHAR) <> CAST(line_1 AS CHAR))
AND CONVERT(line_1 USING utf8mb4) IS NULL;
ERROR 1300 (HY000): Invalid utf8mb4 character string: 'F66762'
次の方法で行を設定しようとしましたが、すべて同じエラーが発生しました。
SET line_1 = CAST(CONVERT(line_1 USING latin1) AS CHAR)
SET line_1 = CONVERT(line_1 USING latin1)
http://jonisalonen.com/2012/fixing-doubly-utf-8-encoded-text-in-mysql/も調べて、二重エンコーディングの問題であるかどうかを確認しましたが、これらのどれも機能せず、取得し続けました同じ文字列エラーです。
さらに、変換手順を支援するためにhttps://mathiasbynens.be/notes/mysql-utf8mb4を調べましたが、utf8mb4 と utf8 がまったく同じ問題を引き起こしています。(最初は utf8 の問題だと思ったので、utf8mb4 に切り替えましたが、それでも同じ問題が発生し続けたとき、より深い問題があることがわかりました)
ご覧のとおり、何か奇妙なことが起こっています。show create address テーブルを見ると、文字セットが適切に設定されていることを確認できます。
SHOW CREATE TABLE address;
| address | CREATE TABLE `address` (
`addressid` bigint(20) NOT NULL AUTO_INCREMENT,
`addressuuid` char(32) COLLATE utf8mb4_unicode_ci NOT NULL,
`line_1` blob,
PRIMARY KEY (`addressid`)
) ENGINE=InnoDB AUTO_INCREMENT=48970 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='All potential addresses' |
さらに、私のインスタンスでは文字変数が正しいことがわかります。
mysql> show variables like 'char%';
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | utf8mb4 |
| character_set_connection | utf8mb4 |
| character_set_database | utf8 |
| character_set_filesystem | binary |
| character_set_results | utf8mb4 |
| character_set_server | utf8mb4 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)
私はどうやってここに来たのか
そのため、問題の原因が背景にある場合に備えて、問題に関する背景情報を提供することは有益な場合があります。
私は元々、すべてをエンコードする latin1 に設定されていたデータベースを持っていました。次に、次のコードを実行しました。
SET NAMES 'latin1';
/* We must change things to blob and then back again */
ALTER TABLE `address` CHANGE line_1 line_1 BLOB;
ALTER TABLE `address` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `address` CHANGE line_1 line_1 VARCHAR(64);
blob に切り替えてから varchar に戻す理由は、通常の推奨手順です。(www.percona.com/blog/2013/10/16/utf8-data-on-latin1-tables-converting-to-utf8-without-downtime-or-double-encoding/)
それが役立つかどうか、また提供できる情報が他にあるかどうか教えてください。私はMySQL 5.6を使用しているので、理論的にはより適切に処理できるはずですが、誰が知っていますか. 4 行しかないので、それぞれを手動で更新できますが、理論的には根本的な問題が大きく、実際にはさらに多くの列を通過する必要があるため、機能的な方法があることを確認することをお勧めします。かなりの数の行で何かを取得した場合に備えて、これらのケースを処理します。