web-dev-qa-db-ja.com

Latin1エンコードされた列でUTF-8文字を検出する方法-MySQL

私は、データベースをLatin1からUTF-8に変換するという退屈で面倒な作業を引き受けようとしています。

この時点で、テーブルに格納したデータの種類を確認するだけです。これにより、データの変換に使用する方法が決まります。

具体的には、Latin1列にUTF-8文字があるかどうかを確認したいのですが、これを行うための最良の方法は何ですか?数行のみが影響を受ける場合は、手動で修正できます。

オプション1. MySQLダンプを実行し、Perlを使用してUTF-8文字を検索しますか?

オプション2. MySQL CHAR_LENGTHを使用してマルチバイト文字を含む行を検索しますか?例えばSELECT name FROM clients WHERE LENGTH(name) != CHAR_LENGTH(name);これで十分ですか?

現在、MysqlクライアントのエンコーディングをUTF-8に切り替えています。

16
dinie

タイムゾーンと同様に、文字エンコーディングは常に問題の原因です。

「high-ASCII」文字はLATIN1アクセント付き文字または記号、またはUTF-8マルチバイト文字の最初のいずれかであるため、実行できることは何ですか。あなたが少しカンニングしない限り、違いを伝えるのは簡単ではありません。

どのエンコーディングが正しいかを理解するには、2つの異なるバージョンをSELECTして視覚的に比較するだけです。次に例を示します。

_SELECT CONVERT(CONVERT(name USING BINARY) USING latin1) AS latin1, 
       CONVERT(CONVERT(name USING BINARY) USING utf8) AS utf8 
FROM users 
WHERE CONVERT(name USING BINARY) RLIKE CONCAT('[', UNHEX('80'), '-', UNHEX('FF'), ']')
_

MySQL正規表現エンジンは_\x80_のようなものを無視するようであり、代わりにUNHEX()メソッドを使用する必要があるため、これは非常に複雑になります。

これにより、次のような結果が生成されます。

_latin1                utf8
----------------------------------------
Björn                Björn
_
48
tadman

あなたの質問は完全に明確ではないので、いくつかのシナリオを想定してみましょう:

  1. これまで間違った接続: latin1エンコーディングを使用してデータベースに正しく接続していませんが、データベースにUTF-8データを保存しています(この場合、列のエンコーディングは関係ありません)。これが私が説明したケース here です。この場合、修正は簡単です。データベースの内容をファイルにダンプしますlatin1接続。これにより、正しく保存されていないデータが、正しく保存されているUTF-8に変換されます(これまでの動作)(詳細については、前述の記事を参照してください)。次に、正しく設定されたutf8接続を介してデータベースにデータを再インポートすると、データが適切に保存されます。
  2. これまで間違った列エンコード: UTF-8データが、utf8接続を介してlatin1列に挿入されました。その場合、それを忘れると、データはなくなります。 Latin1以外の文字は?に置き換える必要があります。
  3. これまですべて問題なく、今後はUTF-8のサポートが追加されます: Latin-1データがlatin1列に正しく格納され、latin1接続を介して挿入されていますが、UTF-8データも許可するように拡張したい。その場合は、列のエンコーディングをutf8に変更してください。 MySQLが既存のデータを変換します。次に、UTF-8データを挿入するときに、データベース接続がutf8に設定されていることを確認してください。
9
deceze

この種のものに役立つ githubのスクリプト があります。

データベースのダンプを作成し、すべての有効なUTF8シーケンスのgrepを作成します。どこからそれを取得するかは、取得する内容によって異なります。 SOには無効なUTF8の識別について複数の質問があります。基本的には、ロジックを逆にするだけです。

編集:基本的に、完全に7ビットで構成されるフィールドASCIIは安全であり、無効なUTF-8シーケンスを含むフィールドはすべてラテン語であると見なすことができます1.残りのデータを検査する必要があります-運が良ければ、少数の明らかな置換によって絶対的な過半数が修正されます(öをLatin-1öに置き換えるなど)。

0
tripleee