web-dev-qa-db-ja.com

「SET CHARACTER SET utf8」は必要ですか?

私はデータベースクラス(PDOベース)を書き換えて、これで行き詰まりました。私は両方を使用するように教えられましたSET NAMES utf8およびSET CHARACTER SET utf8 PHPおよびMySQLでUTF-8を使用する場合。

PDOでは、PDO::MYSQL_ATTR_INIT_COMMANDパラメータですが、1つのクエリしかサポートしていません。

SET CHARACTER SET utf8必要ですか?

30
Znarkus

SET CHARACTER SET utf8を使用した後でSET NAMES utf8を使用すると、実際にcharacter_set_connectioncollation_connection
@@character_set_databaseおよび@@collation_databaseそれぞれ。

manual は、

  • SET NAMES x

    SET character_set_client = x;
    SET character_set_results = x;
    SET character_set_connection = x;
    
  • そしてSET CHARACTER SET x

    SET character_set_client = x;
    SET character_set_results = x;
    SET collation_connection = @@collation_database;
    

SET collation_connection = xも内部でSET character_set_connection = <<character_set_of_collation_x>>を実行し、SET character_set_connection = xは内部でSET collation_connection = <<default_collation_of_character_set_xも実行します。

つまり、基本的にはcharacter_set_connection@@character_set_databaseに、collation_connection@@collation_databaseにリセットしています。このマニュアルでは、これらの変数の使用法について説明しています。

ステートメントを受け取った後、サーバーはステートメントをどの文字セットに変換する必要がありますか?

このために、サーバーはcharacter_set_connectionおよびcollat​​ion_connectionシステム変数を使用します。クライアントが送信したステートメントをcharacter_set_clientからcharacter_set_connectionに変換します(_latin1や_utf8などのイントロデューサーを持つ文字列リテラルを除く)。 collat​​ion_connectionは、リテラル文字列の比較にとって重要です。文字列と列の値を比較する場合、列には独自の照合順序があるため、照合の優先順位が高いため、collat​​ion_connectionは重要ではありません。

これを要約すると、MySQLがクエリを処理するために使用するエンコーディング/トランスコーディング手順とその結果は、複数のステップで構成されています。

  1. MySQLは着信クエリをcharacter_set_clientでエンコードされているものとして扱います。
  2. MySQLはステートメントをcharacter_set_clientからcharacter_set_connectionにトランスコードします
  3. 文字列値を列値と比較する場合、MySQLは文字列値をcharacter_set_connectionから指定されたデータベース列の文字セットにトランスコードし、列照合を使用してソートと比較を行います。
  4. MySQLはcharacter_set_resultsでエンコードされた結果セットを構築します(これには、結果データと、列名などの結果メタデータが含まれます)

したがって、SET CHARACTER SET utf8は、完全なUTF-8サポートを提供するには十分ではない場合があります。 latin1のデフォルトのデータベース文字セットとutf8- charsetで定義された列を考えて、上記の手順を実行してください。 latin1は、UTF-8がカバーできるすべての文字をカバーできないため、ステップ3で文字情報を失う可能性があります。

  • Step3クエリがUTF-8でエンコードされており、表現できない文字が含まれている場合latin1を使用すると、これらの文字はutf8からlatin1(デフォルトのデータベース文字セット)へのトランスコーディング時に失われ、クエリが失敗します。

したがって、SET NAMES ...が文字セットの問題を処理する正しい方法であると言っても安全だと思います。 MySQLサーバー変数を正しく設定することを追加したとしても(必要なすべての変数はmy.cnfで静的に設定できます)、すべての接続で必要な追加クエリのパフォーマンスオーバーヘッドから解放されます。

86
Stefan Gehrig

mysqlマニュアル から:

SET CHARACTER SETはSET NAMESに似ていますが、character_set_connectionおよびcollation_connectionからcharacter_set_databaseおよびcollation_databaseSET CHARACTER SET xステートメントは、次の3つのステートメントと同等です。

SET character_set_client = x;
SET character_set_results = x;
SET collation_connection = @@collation_database;
2
soulmerge

国際文字セットをサポートする必要があるので、私は常にデータベース作成時にテキストタイプフィールドの文字セットを設定するだけでした。

また、私は常にUTF-8を使用してきました。

PHP内で同じ設定:

mb_internal_encoding( 'UTF-8' );
0
Daren Schwenke