Полезно е да се разберат следните дефиниции:
-
Кодиране на знаци подробности как всеки символ е представен в двоичен вид (и следователно се съхранява в компютъра). Например символът
é
(U+00E9, латинската малка буква E с остър знак) е кодирана като0xc3a9
в UTF-8 (който MySQL наричаutf8
) и0xe9
в Windows-1252 (който MySQL наричаlatin1
). -
набор от знаци е азбуката на символите, които могат да бъдат представени с помощта на дадено кодиране на знаци. Объркващо, терминът също се използва за означаване на същото като кодирането на знаци.
-
Аколекция е подреждане на набор от знаци, така че низовете да могат да се сравняват. Например:
latin1_swedish_ci
на MySQL съпоставянето третира повечето акцентирани вариации на символ като еквивалентни на основния знак, докато неговиятlatin1_general_ci
съпоставянето ще ги подреди преди следващия основен знак, но не е еквивалентно (има и други, по-значими разлики:като например реда на знаците катоå
,ä
,ö
иß
).
MySQL ще реши кое съпоставяне трябва да се приложи към даден израз, както е документирано под Колекция от изрази :по-специално, сортирането на колона има предимство пред това на низовия литерал.
WHERE
клауза на вашата заявка сравнява следните низове:
-
стойност в
fos_user.username
, кодиран в набора от знаци на колоната (Windows-1252) и изразяващ предпочитание за нейното съпоставянеlatin1_swedish_ci
(със стойност на принуждаемостта 2); с -
низовия литерал
'Nrv⧧Kasi'
, кодиран в набора от знаци на връзката (UTF-8, както е конфигуриран от Doctrine) и изразяващ предпочитание за съпоставянето на връзкатаutf8_general_ci
(със стойност на принуждаемостта 4).
Тъй като първият от тези низове има по-ниска стойност на коерцибилност от втория, MySQL се опитва да извърши сравнението, използвайки съпоставянето на този низ:latin1_swedish_ci
. За да направи това, MySQL се опитва да преобразува втория низ в latin1
— но тъй като ⧧
знак не съществува в този набор от знаци, сравнението е неуспешно.
Предупреждение
Човек трябва да спре за момент, за да помисли как колоната е кодирана в момента:опитвате се да филтрирате за записи, където fos_user.username
е равно на низ, който съдържа знак, който не може съществуват в тази колона !
Ако смятате, че колоната прави съдържат такива знаци, тогава вероятно сте писали в колоната, докато кодирането на символите за връзка е било зададено на нещо (напр. latin1
), което накара MySQL да интерпретира получената последователност от байтове като знаци, които всички са в набора от символи на Windows-1252.
Ако случаят е такъв, преди да продължите, трябва да коригирате данните си!
-
преобразувайте такива колони в кодирането на знаци, което е било използвано при вмъкване на данни, ако е различно от съществуващото кодиране:
ALTER TABLE fos_users MODIFY username VARCHAR(123) CHARACTER SET foo;
-
махнете информацията за кодиране, свързана с такива колони, като ги преобразувате в
binary
набор от символи:ALTER TABLE fos_users MODIFY username VARCHAR(123) CHARACTER SET binary;
-
асоциирайте с такива колони кодирането, в което действително са били предадени данните, като ги преобразувате в съответния набор от знаци.
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
Синтаксис
: