sql >> データベース >  >> RDS >> Mysql

MySQLの照合の違法な組み合わせ

    次の定義を理解しておくと役立ちます。

    • 文字エンコード 各シンボルがバイナリでどのように表されるか(したがって、コンピュータに保存されるか)について詳しく説明します。たとえば、記号é (U + 00E9、急性のラテン小文字E)はエンコードされています 0xc3a9として UTF-8 で (MySQLは utf8と呼んでいます )および 0xe9 Windows-1252 (MySQLは latin1と呼んでいます 。

    • 文字セット 特定の文字エンコードを使用して表すことができる記号のアルファベットです。紛らわしいことに、この用語は文字エンコードと同じ意味でも使用されます。

    • 照合 文字列を比較できるように、文字セットの順序です。例:MySQLの latin1_swedish_ci 照合では、文字の最もアクセントのあるバリエーションを基本文字と同等に扱いますが、その latin1_general_ci 照合では、次の基本文字の前にそれらを並べ替えますが、同等ではありません(åのような文字の順序など、他のより重要な違いもあります 、äö およびß

    MySQLは、に記載されているように、特定の式に適用する照合を決定します。式の照合 :特に、列の照合は文字列リテラルの照合よりも優先されます。

    WHERE クエリの句は、次の文字列を比較します:

    1. fos_user.usernameの値 、列の文字セット(Windows-1252)でエンコードされ、その照合の設定を表現します latin1_swedish_ci (強制力の値は2)。と

    2. 文字列リテラル'Nrv⧧Kasi' 、接続の文字セット(UTF-8、Doctrineによって構成されている)でエンコードされ、接続の照合の設定を表現します utf8_general_ci (強制力の値は4)。

    これらの文字列の最初の文字列は2番目の文字列よりも強制力の値が低いため、MySQLはその文字列の照合を使用して比較を実行しようとします: latin1_swedish_ci 。そのために、MySQLは2番目の文字列を latin1に変換しようとします —ただし、以降 その文字セットに文字が存在しない場合、比較は失敗します。

    警告

    列が現在どのようにエンコードされているかを検討するために、少し一時停止する必要があります。 fos_user.usernameが存在するレコードをフィルタリングしようとしています。 できない文字を含む文字列と同じです その列に存在する

    コラムがあると思われる場合 そのような文字が含まれている場合は、接続文字エンコードが何かに設定されているときに列に書き込んだ可能性があります(例: latin1 )これにより、MySQLは受信したバイトシーケンスをすべてWindows-1252文字セットに含まれる文字として解釈しました。

    この場合、先に進む前に、データを修正する必要があります!

    1. 現在のエンコーディングと異なる場合は、そのような列をデータ挿入で使用された文字エンコーディングに変換します。

      ALTER TABLE fos_users MODIFY username VARCHAR(123) CHARACTER SET foo;
      
    2. それらをbinaryに変換することにより、そのような列に関連付けられたエンコーディング情報を削除します 文字セット:

      ALTER TABLE fos_users MODIFY username VARCHAR(123) CHARACTER SET binary;
      
    3. それらを関連する文字セットに変換することにより、データが実際に送信されたエンコーディングをそのような列に関連付けます。

      ALTER TABLE fos_users MODIFY username VARCHAR(123) CHARACTER SET bar;
      

    マルチバイトエンコーディングから変換する場合、変換された文字列の可能な最大長に対応するために、列のサイズを大きくする(またはタイプを変更する)必要がある場合があることに注意してください。

    列が正しくエンコードされていることが確認できたら、Unicode照合を使用して比較を強制することができます—

    • 値を明示的に変換するfos_user.username Unicode文字セットへ:

      WHERE CONVERT(fos_user.username USING utf8) = ?
      
    • 文字列リテラルの強制力の値を列よりも低くするように強制します(列の値がUTF-8に暗黙的に変換されます):

      WHERE fos_user.username = ? COLLATE utf8_general_ci
      

    または、あなたが言うように、列をUnicodeエンコーディングに永続的に変換し、その照合を適切に設定することもできます。

    主な考慮事項は、Unicodeエンコーディングはシングルバイト文字セットよりも多くのスペースを占めるため、次のようになります。

    • より多くのストレージが必要になる場合があります;

    • 比較は遅くなる可能性があります。および

    • インデックスプレフィックスの長さを調整する必要がある場合があります(最大値はバイト単位であるため、以前よりも少ない文字を表す場合があることに注意してください)。

    また、 ALTER TABLE > 構文



    1. AWSGlueでMySQLテーブルを上書きする

    2. 行あたり8060バイト、(varchar、nvarchar)値あたり8000バイトの制限にどのように到達しますか?

    3. PHPを使用してMySQLで作成されたばかりの行のIDを返す方法はありますか?

    4. com.mchange.v2.resourcepool.CannotAcquireResourceException:ResourcePoolは、プライマリファクトリまたはソースからリソースを取得できませんでした