Imaginons une base de donnée qui contient des données dans un encodage différent de celui de stockage… c'est le bordel.
Dans mon cas, j'avais une colonne (enfin, plus d'une…) en utf8, qui contenait la représentation latin1 d'une donnée utf8. #brainfuck.
À priori, je me suis retrouvé avec ça en forçant une communication utf8 à une BDD latin1 qui avait des colonnes utf8. J'imagine donc que naturellement mes données étaient interprétées en latin1 à l'arrivée, et converties en utf8 pour remplir la colonne. Je me retrouve donc avec ce bousin de double encodage.
Bref, je m'en sors avec une version alambiquée des idées de cette page :
UPDATE mytable SET mycolumn = CONVERT(CAST(CONVERT(mycolumn USING latin1) as BINARY) USING utf8);
La partie magique est bien sûr le CONVERT(CAST(CONVERT(mycolumn USING latin1) as BINARY) USING utf8)
: on demande une conversion de la valeur en latin1, puis on force une interprétation binaire pour oublier toute notion d'encodage, et on convertit le binaire en utf8. Le résultat est la suppression du "surencodage" latin1 au milieu. Mais évidemment ça ne marche qu'avec des données représentables en latin1 j'imagine, mais je ne sais même pas si avec mon setup j'aurais pu enregistrer des données incompatibles… je préfère ne pas y penser.
[edit]
Si on souhaite voir les lignes qui seraient affectées, ont peut utiliser SELECT mycolumn FROM mytable WHERE mycolumn <> CONVERT(CAST(CONVERT(mycolumn USING latin1) as BINARY) USING utf8);
: on sélectionne les lignes pour lesquelles la conversion a un effet.
PS : je suis une quiche en SQL (preuve en est la situation dans laquelle je me suis mis…), donc il y a peut-être d'autres solutions meilleures, une solution pour ne pas avoir à répéter le nom de colonne 2 à 3 fois (ce qui augmente fortement le risque de typo quand on fait ça à la main), etc.