1. ホーム
  2. mysql

[解決済み] UTF-8文字に関するトラブル:見たものと保存したものが違う

2023-04-01 10:09:22

質問

UTF-8を使おうとしたところ、問題が発生しました。

いろいろと試してみたのですが、以下のような結果になりました。

  • ???? というように、アジア系の文字ではなく 欧文でも Se?or に対して Señor .
  • などの奇妙な文字列(モジバケ? Señor または 新浪新闻 に対して 新浪新闻 .
  • Se�or などのブラックダイヤモンド。
  • 最後に、データが失われる、あるいは少なくとも切り捨てられるという事態に陥ったのです。 Se に対して Señor .
  • にテキストが入っても を見る が正しく表示されても ソート を正しくソートできませんでした。

私は何を間違えているのでしょうか?どうすれば コード ? を回復できますか? データ もしそうなら、どのように?

どのように解決するのですか?

この問題は、このサイトの参加者だけでなく、多くの人を悩ませています。

の主な5つのケースを挙げていますね。 CHARACTER SET のトラブルです。

ベストプラクティス

今後は CHARACTER SET utf8mb4COLLATION utf8mb4_unicode_520_ci . (パイプラインに新しいバージョンの Unicode 照合順序があります)。

utf8mb4 のスーパーセットです。 utf8 の上位互換で、絵文字や一部の中国語で必要とされる4バイトのutf8コードを扱えるようになります。

MySQL 以外では、"UTF-8" はすべてのサイズエンコーディングを指すため、事実上 MySQL の utf8mb4 ではなく utf8 .

以下では、MySQL の内部と外部を区別するために、これらのスペルと大文字を使用するようにします。

あなたが すべきこと すること

  • エディタなどをUTF-8に設定してください。
  • HTMLフォームは次のように始めます。 <form accept-charset="UTF-8"> .
  • バイトをUTF-8でエンコードさせる。
  • クライアントで使用されているエンコーディングとしてUTF-8を確立します。
  • カラム/テーブルを宣言させる CHARACTER SET utf8mb4 (チェックは SHOW CREATE TABLE .)
  • <meta charset=UTF-8> HTMLの冒頭で
  • ストアドルーチンは現在の文字セット/照合順序を取得します。 それらは再構築が必要かもしれません。

ずっとUTF-8

コンピュータ言語に関する詳細 (およびその次のセクション)

データをテストする

データをツールで表示したり SELECT は信頼できません。 そのようなクライアント、特にブラウザは、間違ったエンコーディングを補おうとして、データベースがこじれていても正しいテキストを表示するものがあまりに多いのです。 そこで、英語以外のテキストを含むテーブルとカラムを選び、次の操作を行います。

SELECT col, HEX(col) FROM tbl WHERE ...

正しく格納されたUTF-8のHEXは次のようになります。

  • 空白の場合(どの言語でも) 20
  • 英語の場合 4x , 5x , 6x または 7x
  • 西ヨーロッパの大部分では、アクセント記号付きの文字は Cxyy
  • キリル文字、ヘブライ語、ペルシア語/アラビア語。 Dxyy
  • アジアの大部分 Exyyzz
  • 絵文字と中国語の一部 F0yyzzww
  • 詳細

見受けられる問題の具体的な原因と対処法

切り捨て テキスト ( Se に対して Señor ):

  • 格納されるバイトがutf8mb4でエンコードされていません。これを修正します。
  • また、読み込み時の接続がUTF-8であることを確認してください。

ブラック・ダイアモンズ クエスチョンマーク ( Se�or に対して Señor ); のどちらかのケースが存在します。

ケース1 (元のバイトが ではない UTF-8ではない)。

  • 格納されるバイトがutf8でエンコードされていません。これを修正します。
  • 接続(または SET NAMES ) のための INSERT SELECT がutf8/utf8mb4でなかった。 これを修正します。
  • また、データベース内のカラムが CHARACTER SET utf8 (またはutf8mb4)であることを確認してください。

ケース2(オリジナルバイト UTF-8)です。

  • 接続(または SET NAMES ) のための SELECT がutf8/utf8mb4でなかった。 これを修正する。
  • また、データベース内のカラムが CHARACTER SET utf8 (またはutf8mb4)であることを確認してください。

黒い菱形は、ブラウザが <meta charset=UTF-8> .

クエスチョンマーク (黒い菱形でない普通のもの) ( Se?or に対して Señor ):

  • 格納されるバイトがutf8/utf8mb4でエンコードされていません。 これを修正します。
  • データベース内のカラムが CHARACTER SET utf8 (または utf8mb4) になっています。 これを修正します。 (使用する SHOW CREATE TABLE .)
  • また、読み込み時の接続がUTF-8であることを確認します。

モジバケ ( Señor に対して Señor ): (この議論は ダブルエンコーディング にも当てはまります。)

  • 格納するバイトはUTF-8でエンコードする必要があります。 これを修正します。
  • のときの接続は INSERTingSELECTing のテキストは、utf8 または utf8mb4 を指定する必要があります。 これを修正します。
  • カラムは宣言する必要があります CHARACTER SET utf8 (または utf8mb4) である必要があります。 これを修正します。
  • で始まるHTMLが必要です。 <meta charset=UTF-8> .

データが正しく見えるのに、正しくソートされない場合、次のようなことが考えられます。 照合順序を間違えている。 または、あなたのニーズに合った照合順序がない。 あるいは ダブルエンコーディング .

ダブルエンコード を行うことで確認することができます。 SELECT .. HEX .. で確認できます。

é should come back C3A9, but instead shows C383C2A9
The Emoji ???? should come back F09F91BD, but comes back C3B0C5B8E28098C2BD

つまり、16進数は本来あるべき長さの約2倍になっています。 これは、latin1(またはその他)からutf8に変換した後、それらのバイトをlatin1であるかのように扱い、変換を繰り返したために発生します。 をlatin1であるかのように扱い、変換を繰り返したためです。 ソート(と比較)が正しく動作しないのは、例えば次のようなことが原因です。 であるかのようにソートするため,正しく動作しません。 Señor .

可能な限り、データを修正する

については 切り捨て クエスチョンマーク を使用すると、データが失われます。

の場合 もじばけ / ダブルエンコード , ...

の場合 ブラックダイヤモンド , ...

フィックス はここにリストアップされています。 (5つの異なる状況に対する5つの異なる修正方法。慎重に選んでください)。 http://mysql.rjweb.org/doc.php/charcoll#fixes_for_various_cases