0

このシステムは、MySQL データベースにアクセスする PHP アプリケーションです。最初のテーブルは、標準の latin1 エンコーディングで作成され、エンコーディングを設定せずに、PHP の mysqli を介して入力されました。PHP スクリプトとデータはすべて UTF-8 で動作します。

新しいテーブルではエンコーディングが utf8_bin に設定されており、すべてのトランザクションの前にSET CHARACTER SET utf8送信されます。

(HeidiSQL などの SQL エクスプローラーを使用して) mysql データベースの新しいテーブルを見ると、すべての特殊文字が正しく表示されます。ただし、すべての古いテーブルでは、典型的な latin1-utf8 エラーが ü の Ü のように表示されます。

次のいずれかの方法でこれを修正する簡単な方法はありますか。

  • SQL エクスプローラーで正しく表示されるように各テーブルのエンコーディングを修正しますが、PHP コードはそのままにしておきます (すべてのステートメントと共に、SET CHARACTER SET utf8またはlatin1すべてのステートメントの前に、テーブルのエンコーディングを適合させます。(単なる回避策)
  • すべてのテーブルのエンコーディングを utf8 に切り替えます ->SET CHARACTER SET utf8すべての mysqli 接続の開始時に送信する必要があります (または、これを標準として設定する方法がありますか?)
  • すべてのテーブルのエンコードを latin1 に切り替えます ->SET CHARACTER SET utf8トランザクションの前に送信する必要はもうありませんが、データベース エクスプローラーでエンコードが正しくありません。

データベースがすべてのテーブルを utf8 として受け取り、latin1 テーブルを間違った文字で表示しているように見えます。Mysqli は、特に指示がない限り、すべてのテーブルを latin1 と見なします。

アプリケーションは生産的であり、すべてのステートメントの前に適切なエンコーディングが mysqli に通知されるため、エンコーディングの問題はユーザーには見えません。しかし、それは良い習慣ではないように感じます。

データベースのセットアップ方法に問題があることを認識しており、これを修正するためのベスト プラクティスを学びたいと考えています。

4

2 に答える 2

0

最初のテーブルは、標準の latin1 エンコーディングで作成され、PHP の mysqli を介して入力されました。

したがって、それらのテーブルにはゴミがあります。データを回復する必要がありますか?

すべてのトランザクションの前に SET CHARACTER SET utf8 が送信されます。

それは役に立たない。代わりに、SET NAMES utf8接続後に 1 回実行します。

ÜのモジバケですÜ。このフォーラムで Mojibake を検索してください。

utf8 バイトの latin1 テーブルがいくつかあり、他のテーブルは utf8 です。今すぐやめて、混乱を一掃してください。ずっとutf8に行きます。

モジバケのまとめ:

  • クライアントにあるバイトは、utf8 (良好) で正しくエンコードされています。
  • おそらくデフォルトでSET NAMES latin1(またはまたは...)に接続しました。set_charset('latin1')(だったはずutf8です。)
  • xx 表の列が宣言されCHARACTER SET latin1ました。(または、テーブル/データベースから継承された可能性があります。) (だったはずutf8です。)
  • 表の列は である場合とそうでない場合がありますがCHARACTER SET utf8、そうである必要があります。

データを修正する必要がある場合は、次のような「2段階のALTER」が必要です

ALTER TABLE Tbl MODIFY COLUMN col VARBINARY(...) ...;
ALTER TABLE Tbl MODIFY COLUMN col VARCHAR(...) ... CHARACTER SET utf8 ...;
于 2015-08-28T16:13:05.073 に答える
0

OK、mysqldump を使用して、関連するテーブルを含む .sql ファイルを作成することはできません。HeidiSQL と同じ文字化けが発生する可能性があります。

しかし、PHP アプリケーションと同じ間違った文字セットで .sql ファイルを作成して、PHP スクリプトでそれを行うことができます。その PHP スクリプトは次のことを行う必要があります。

mb_internal_encoding("UTF-8");
$link = mysqli_connect('localhost', 'root', '');

mysqli_set_charset($link, "latin1");

$result = mysqli_query($link, "SELECT * FROM table1", MYSQLI_USE_RESULT);
while($row = mysqli_fetch_assoc($result))
{
  # Generate INSERT statements for table1 using some PHP logic, and write these into a new file, named e.g. fixencoding.sql
}
mysqli_free_result($result);
mysqli_query($link, "DELETE * FROM table1");
mysqli_query($link, "ALTER TABLE table1 COLLATE='utf8_general_ci'");

$result = mysqli_query($link, "SELECT * FROM table2", MYSQLI_USE_RESULT);
while($row = mysqli_fetch_assoc($result))
{
  # Generate INSERT statements for table2 and append these into the .sql file created above
}
mysqli_free_result($result);
mysqli_query($link, "DELETE * FROM table2");
mysqli_query($link, "ALTER TABLE table2 COLLATE='utf8_general_ci'");

# etc. - repeat above steps for every broken table

mysqli_close($link);

作成された fixencoding.sql ファイルは、BOM のない utf-8 でエンコードされたファイルになり、mysql.exe を使用してインポートできます。

C:\path\to\mysql\bin\mysql.exe -hlocalhost -uroot name-of-database <fixencoding.sql 

すべてがうまくいけば、PHP アプリケーションには正しい MySQL 文字セットが含まれているはずです。

mysqli_set_charset($link, 'utf8');

また、HeidiSQL およびその他のクライアントは、実際の utf-8 文字を表示する必要があります。

これはすべてテストされていません!DELETE クエリと ALTER クエリをコメントアウトして、最初に予行演習を行うことを忘れないでください。

于 2015-08-28T16:13:33.530 に答える