Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

MySQL Campuran ilegal dari collation

Sangat membantu untuk memahami definisi berikut:

  • Pengkodean karakter merinci bagaimana setiap simbol direpresentasikan dalam biner (dan karenanya disimpan di komputer). Misalnya, simbol é (U+00E9, huruf latin kecil E dengan akut) dikodekan sebagai 0xc3a9 di UTF-8 (yang disebut MySQL utf8 ) dan 0xe9 di Windows-1252 (yang disebut MySQL latin1 ).

  • kumpulan karakter adalah alfabet simbol yang dapat direpresentasikan menggunakan pengkodean karakter yang diberikan. Yang membingungkan, istilah ini juga digunakan untuk arti yang sama dengan pengkodean karakter.

  • kumpulan adalah pemesanan pada set karakter, sehingga string dapat dibandingkan. Misalnya:MySQL latin1_swedish_ci collation memperlakukan variasi karakter yang paling beraksen setara dengan karakter dasar, sedangkan latin1_general_ci collation akan mengurutkannya sebelum karakter dasar berikutnya tetapi tidak setara (ada perbedaan lain yang lebih signifikan juga:seperti urutan karakter seperti å , ä , ö dan ß ).

MySQL akan memutuskan susunan mana yang harus diterapkan ke ekspresi tertentu seperti yang didokumentasikan di bawah Kumpulan Ekspresi :khususnya, susunan kolom lebih diutamakan daripada string literal.

WHERE klausa kueri Anda membandingkan string berikut:

  1. nilai dalam fos_user.username , dikodekan dalam rangkaian karakter kolom (Windows-1252) dan menyatakan preferensi untuk susunannya latin1_swedish_ci (dengan nilai koersibilitas 2); dengan

  2. string literal 'Nrv⧧Kasi' , dikodekan dalam rangkaian karakter koneksi (UTF-8, sebagaimana dikonfigurasi oleh Doctrine) dan menyatakan preferensi untuk susunan koneksi utf8_general_ci (dengan nilai koersibilitas 4).

Karena string pertama memiliki nilai koersibilitas yang lebih rendah daripada string kedua, MySQL mencoba melakukan perbandingan menggunakan susunan string tersebut:latin1_swedish_ci . Untuk melakukannya, MySQL mencoba mengonversi string kedua menjadi latin1 —tetapi karena karakter tidak ada di set karakter itu, perbandingan gagal.

Peringatan

Seseorang harus berhenti sejenak untuk mempertimbangkan bagaimana kolom dikodekan saat ini:Anda mencoba memfilter catatan di mana fos_user.username sama dengan string yang berisi karakter yang tidak bisa ada di kolom itu !

Jika Anda yakin bahwa kolom ya mengandung karakter seperti itu, maka Anda mungkin menulis ke kolom sementara penyandian karakter koneksi disetel ke sesuatu (mis. latin1 ) yang menyebabkan MySQL menafsirkan urutan byte yang diterima sebagai karakter yang semuanya ada dalam rangkaian karakter Windows-1252.

Jika demikian, sebelum melanjutkan lebih jauh sebaiknya perbaiki data Anda!

  1. mengkonversi kolom tersebut ke pengkodean karakter yang digunakan pada penyisipan data, jika berbeda dengan pengkodean incumbent:

    ALTER TABLE fos_users MODIFY username VARCHAR(123) CHARACTER SET foo;
    
  2. lepaskan informasi penyandian yang terkait dengan kolom tersebut dengan mengonversinya ke binary kumpulan karakter:

    ALTER TABLE fos_users MODIFY username VARCHAR(123) CHARACTER SET binary;
    
  3. kaitkan dengan kolom tersebut pengkodean di mana data sebenarnya dikirimkan dengan mengubahnya menjadi rangkaian karakter yang relevan.

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

Perhatikan bahwa, jika mengonversi dari pengkodean multi-byte, Anda mungkin perlu menambah ukuran kolom (atau bahkan mengubah jenisnya) untuk mengakomodasi panjang maksimum string yang dikonversi.

Setelah seseorang yakin bahwa kolom dikodekan dengan benar, seseorang dapat memaksa perbandingan dilakukan menggunakan susunan Unicode dengan baik—

  • secara eksplisit mengonversi nilai fos_user.username ke set karakter Unicode:

    WHERE CONVERT(fos_user.username USING utf8) = ?
    
  • memaksa literal string memiliki nilai koersibilitas yang lebih rendah daripada kolom (akan menyebabkan konversi implisit nilai kolom ke UTF-8):

    WHERE fos_user.username = ? COLLATE utf8_general_ci
    

Atau seseorang dapat, seperti yang Anda katakan, secara permanen mengonversi kolom ke penyandian Unicode dan mengatur susunannya dengan tepat.

Pertimbangan prinsipnya adalah bahwa penyandian Unicode membutuhkan lebih banyak ruang daripada set karakter byte tunggal, jadi:

  • lebih banyak penyimpanan mungkin diperlukan;

  • perbandingan mungkin lebih lambat; dan

  • panjang awalan indeks mungkin perlu disesuaikan (perhatikan bahwa maksimum dalam byte, jadi mungkin mewakili lebih sedikit karakter dari sebelumnya).

Perlu diketahui juga bahwa, seperti yang didokumentasikan dalam ALTER TABLE Sintaks :



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bergabung dengan Tabel dari Database yang berbeda

  2. Cara mendapatkan semua data dari 2 tabel menggunakan kunci asing

  3. Cara memperbaiki grup kueri dengan only_full_group_by

  4. Laravel Eloquent membandingkan tanggal dari bidang datetime

  5. Kueri LEFT OUTER JOIN tidak mengembalikan baris yang diharapkan