Trabalhar com definições de charset na web é um problema para quem vive entre projetos com codificação ISO-8859-1 (latin) e UTF-8. Quem não tem muito conhecimento sobre isso começa trabalhando apenas com ISO-8859-1 mas na primeira interação com webservices ou primeira conexão com banco de dados de um sistema um pouco mais elaborado (preocupado com questões de internacionalização) a dor de cabeça pode aparecer, parecendo com um cóo
.
Note que um problema com a exibição de caracteres em uma página pode ocorrer não só pela configuração do charset do banco de dados, mas também por arquivos de aplicação com o charset errado, uma configuração de conexão com banco de dados incoerente com o resto do projeto e até uma meta tag HTML ou resposta com um cabeçalho HTTP incorreto.
Charset e collation não são palavras diferentes que significam a mesma coisa, um charset é um conjunto de caracteres e suas respectivas representações binárias, enquanto um collation é um conjunto de regras para comparação dos caracteres representados, para exemplificar: é o collation que determina que o "A" é igual ao "a" em um collation case insensitive.
Exemplos de charset: latin1, utf8, ascii, cp1250, koi8r (descubra outros com SHOW CHARACTER SET
)
Exemplos de collation: latin1_general_ci, latin1_spanish_ci, utf8_unicode_ci, utf8_general_ci (descubra outros com SHOW COLLATION
)
Se você observar problemas com caracteres aparecendo incorretamente no meio de sua página, o problema é o charset. Se suas comparações em suas queryes estiverem se comportando "estranhamente" verifique se o collation da sua tabela (e campos, sim, no MySQL é possível definir um collation apenas para um campo da sua tabela).
Collations normalmente finalizam com
_ci
quando case insensitive,_cs
quando case sensitive e_bin
quando binário.
Para definir o charset após a conexão use SET NAMES 'utf8';
, neste exemplo utilizado para definir UTF-8.
Para definir o charset e o collation no momento da criação da base de dados utilize CREATE DATABASE minhabase DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;
. Note que qualquer tabela criada dentro dessa base de dados que não possuir definição do charset e/ou I{collation}i irá assumir o padrão da base de dados.
Se você criar uma base de dados com as definições incorretas a conversão é bem simples: ALTER TABLE tabela CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
. Todo conteúdo dessa tabela ficará com o charset escolhido. Outros comandos para alterar estas definições você pode encontrar no site do MySQL
Se durante uma query você se deparar com algo como Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE)
você com certeza estará tentando comparar duas colunas com collations diferentes, que o MySQL não consegue comparar. Isso é muito comum acontecer em views que utilizam tabelas em bases de dados diferentes.
Para resolver isso você pode tentar converter o campo em sua query adicionando o COLLATE
desejado, por exemplo: SELECT * FROM campo1 COLLATE latin1_swedish_ci = campo2
. É importante lembrar que isso só ajusta o collation se o charset for compatível, você não pode converter para latin1_swedish_ci
se o i{charset}i do campo1
for UTF-8.
Para ajustar o charset de um campo podemos utilizar a função CONVERT
no com a codificação desejada: SELECT * FROM CONVERT(campo1 USING utf8) COLLATE utf8_bin = campo2
.
As soluções acima são válidas apenas para ajustes pequenos e emergenciais pois podem afetar a velocidade de resposta de sua i{query}i e a "bagunça" continuará lá, escondida.
A melhor coisa que você pode fazer é uniformizar sua base de dados e evitar que qualquer tabela/campo fique com o i{charset}i ou i{collation}i diferente do restante do sistema. Note que isso é uma boa prática, não uma regra.