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 sebagai0xc3a9
di UTF-8 (yang disebut MySQLutf8
) dan0xe9
di Windows-1252 (yang disebut MySQLlatin1
). -
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, sedangkanlatin1_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:
-
nilai dalam
fos_user.username
, dikodekan dalam rangkaian karakter kolom (Windows-1252) dan menyatakan preferensi untuk susunannyalatin1_swedish_ci
(dengan nilai koersibilitas 2); dengan -
string literal
'Nrv⧧Kasi'
, dikodekan dalam rangkaian karakter koneksi (UTF-8, sebagaimana dikonfigurasi oleh Doctrine) dan menyatakan preferensi untuk susunan koneksiutf8_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!
-
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;
-
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;
-
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
: