Het is handig om de volgende definities te begrijpen:
-
Een tekencodering geeft aan hoe elk symbool binair wordt weergegeven (en dus op de computer wordt opgeslagen). Bijvoorbeeld het symbool
é
(U+00E9, Latijnse kleine letter E met acute) is gecodeerd als0xc3a9
in UTF-8 (die MySQLutf8
aanroept) ) en0xe9
in Windows-1252 (die MySQLlatin1
noemt ). -
Een tekenset is het alfabet van symbolen die kunnen worden weergegeven met een bepaalde tekencodering. Verwarrend genoeg wordt de term ook gebruikt om hetzelfde te betekenen als tekencodering.
-
Een verzameling is een volgorde op een tekenset, zodat strings vergeleken kunnen worden. Bijvoorbeeld:MySQL's
latin1_swedish_ci
collatie behandelt de meeste variaties met accenten van een teken als equivalent aan het basisteken, terwijl delatin1_general_ci
sortering plaatst ze vóór het volgende basisteken, maar niet equivalent (er zijn ook andere, meer significante verschillen:zoals de volgorde van tekens zoalså
,ä
,ö
enß
).
MySQL zal beslissen welke sortering moet worden toegepast op een bepaalde uitdrukking, zoals beschreven onder Verzameling van uitdrukkingen :in het bijzonder heeft de sortering van een kolom voorrang op die van een letterlijke tekenreeks.
De WHERE
clausule van uw zoekopdracht vergelijkt de volgende tekenreeksen:
-
een waarde in
fos_user.username
, gecodeerd in de tekenset van de kolom (Windows-1252) en een voorkeur voor de sortering ervan uitdrukkenlatin1_swedish_ci
(met een coërcibiliteitswaarde van 2); met -
de letterlijke tekenreeks
'Nrv⧧Kasi'
, gecodeerd in de tekenset van de verbinding (UTF-8, zoals geconfigureerd door Doctrine) en die een voorkeur uitdrukt voor de sortering van de verbindingutf8_general_ci
(met een dwangwaarde van 4).
Aangezien de eerste van deze strings een lagere coercibility-waarde heeft dan de tweede, probeert MySQL de vergelijking uit te voeren met behulp van de sortering van die string:latin1_swedish_ci
. Om dit te doen, probeert MySQL de tweede string te converteren naar latin1
—maar sinds de ⧧
teken bestaat niet in die tekenset, de vergelijking mislukt.
Waarschuwing
Men moet even pauzeren om na te gaan hoe de kolom momenteel is gecodeerd:u probeert te filteren op records waar fos_user.username
is gelijk aan een tekenreeks die een teken bevat dat niet bestaan in die kolom !
Als u van mening bent dat de kolom dat wel dergelijke tekens bevatten, hebt u waarschijnlijk naar de kolom geschreven terwijl de tekencodering van de verbinding op iets was ingesteld (bijv. latin1
) waardoor MySQL de ontvangen bytereeks interpreteerde als tekens die allemaal in de tekenset van Windows-1252 staan.
Als dit het geval is, moet u uw gegevens herstellen voordat u verder gaat!
-
converteer dergelijke kolommen naar de tekencodering die werd gebruikt bij het invoegen van gegevens, indien verschillend van de bestaande codering:
ALTER TABLE fos_users MODIFY username VARCHAR(123) CHARACTER SET foo;
-
verwijder de coderingsinformatie die aan dergelijke kolommen is gekoppeld door ze te converteren naar de
binary
tekenset:ALTER TABLE fos_users MODIFY username VARCHAR(123) CHARACTER SET binary;
-
koppel aan dergelijke kolommen de codering waarin de gegevens daadwerkelijk werden verzonden door ze om te zetten in de relevante tekenset.
ALTER TABLE fos_users MODIFY username VARCHAR(123) CHARACTER SET bar;
Houd er rekening mee dat, als u converteert vanuit een multi-byte-codering, u mogelijk de grootte van de kolom moet vergroten (of zelfs het type ervan moet wijzigen) om de maximaal mogelijke lengte van de geconverteerde tekenreeks aan te passen.
Als men er eenmaal zeker van is dat de kolommen correct zijn gecodeerd, kan men de vergelijking afdwingen met behulp van een Unicode-sortering door ofwel—
-
expliciet converteren van de waarde
fos_user.username
naar een Unicode-tekenset:WHERE CONVERT(fos_user.username USING utf8) = ?
-
forceren dat de letterlijke tekenreeks een lagere coërcibility-waarde heeft dan de kolom (zal een impliciete conversie van de waarde van de kolom naar UTF-8 veroorzaken):
WHERE fos_user.username = ? COLLATE utf8_general_ci
Of je kunt, zoals je zegt, de kolom(men) permanent converteren naar een Unicode-codering en de sortering op de juiste manier instellen.
De belangrijkste overweging is dat Unicode-coderingen meer ruimte innemen dan enkelbyte-tekensets, dus:
-
meer opslagruimte kan nodig zijn;
-
vergelijkingen kunnen langzamer zijn; en
-
De lengte van het indexvoorvoegsel moet mogelijk worden aangepast (merk op dat het maximum in bytes is, dus mogelijk minder tekens dan voorheen).
Houd er ook rekening mee dat, zoals gedocumenteerd onder ALTER TABLE
Syntaxis
: