Problema de acentuação no MySQL: Latin1 x UTF8

Um cliente me forneceu o backup de seu banco de dados MySQL, porém, ao importá-lo alguns caracteres estranhos substituíam os esperados acentos. Palavra com “Olá” estava escrita como “Olá”, “Termos de Serviço” estava como “Termos de Serviço”.

O Problema obviamente era de codificação (charset, collation) utilizada entre os dois bancos: o Banco original estava no padrão Latin 1 (latin_swedish_ci) enquanto o outro estava em UTF8 (utf8_general_ci). Caracteres como “ç”, “ã”, “á” e etc pertence ao padrão Latin 1 (ISO-8859-1); o padrão UTF8 por utilizar menos dados para armazenar cada caractere é obrigado a representar as letras acentuadas (e a cedilha) utilizando dois caracteres, o que vem a causar este problema.

A solução óbvia para esta falha seria modificar o charset do banco de dados e da tabela. Mas isto não solucionou o meu caso. Resolvi então utilizar uma abordagem menos rebuscada: criei um script PHP para atualizar cada linha na tabela do banco de dados convertendo-as para o padrão desejado.

Para isso utilizei a função mb_convert_encoding:

<br />
&lt;?php</p>
<p>	set_time_limit(0); // Tempo máximo de execução: sem limite (0).</p>
<p>	// ----------------------------------------------------------------------<br />
	// Configurações<br />
	// ----------------------------------------------------------------------</p>
<p>	define(&quot;SETTINGS_SGBD_HOST&quot;, &quot;localhost&quot;);<br />
	define(&quot;SETTINGS_SGBD_PORT&quot;, &quot;3306&quot;);<br />
	define(&quot;SETTINGS_SGBD_USER&quot;, &quot;&quot;);<br />
	define(&quot;SETTINGS_SGBD_PASSWORD&quot;, &quot;&quot;);<br />
	define(&quot;SETTINGS_SGBD_DATABASE&quot;, &quot;&quot;);</p>
<p>	define(&quot;SETTINGS_SGBD_FIX_TABLE&quot;, &quot;&quot;);<br />
	define(&quot;SETTINGS_SGBD_FIX_FIELD&quot;, &quot;&quot;);</p>
<p>	// ----------------------------------------------------------------------<br />
	// Conectar ao Banco de Dados<br />
	// ----------------------------------------------------------------------</p>
<p>	$lobj_databaseObject = mysql_connect(SETTINGS_SGBD_HOST.&quot;:&quot;.SETTINGS_SGBD_PORT, SETTINGS_SGBD_USER, SETTINGS_SGBD_PASSWORD);<br />
	mysql_select_db(SETTINGS_SGBD_DATABASE);<br />
	if ( $lobj_databaseObject == false ) exit;<br />
	mysql_set_charset('latin1', $lobj_databaseObject); </p>
<p>	// ----------------------------------------------------------------------<br />
	// Atualiza a tabela corrigindo a codificação<br />
	// ----------------------------------------------------------------------</p>
<p>	$lstr_SQLQuery = &quot;SELECT &quot;.SETTINGS_SGBD_FIX_FIELD.&quot; FROM &quot;.SETTINGS_SGBD_FIX_TABLE;</p>
<p>	$lobj_recordsetFields = mysql_query ($lstr_SQLQuery, $lobj_databaseObject);</p>
<p>	if ( mysql_num_rows($lobj_recordsetFields) &gt; 0 ) {<br />
		while ($lobj_rowTerm = mysql_fetch_object( $lobj_recordsetFields )) {</p>
<p>			$lstr_fixFieldContent = eval( &quot;return $lobj_rowTerm-&gt;&quot;.SETTINGS_SGBD_FIX_FIELD.&quot;;&quot;);<br />
			$lstr_SQLQuery = &quot;UPDATE &quot;.SETTINGS_SGBD_FIX_TABLE.&quot; SET &quot;.SETTINGS_SGBD_FIX_FIELD.&quot; = '&quot;.mb_convert_encoding($lstr_fixFieldContent, 'ISO-8859-1', 'UTF-8').&quot;' WHERE &quot;.SETTINGS_SGBD_FIX_FIELD.&quot; LIKE '$lstr_fixFieldContent'&quot;;<br />
			mysql_query ($lstr_SQLQuery, $lobj_databaseObject);</p>
<p>		}<br />
	}</p>
<p>	// ----------------------------------------------------------------------<br />
	// Desconectar do Banco de Dados<br />
	// ----------------------------------------------------------------------</p>
<p>	mysql_close ( $lobj_databaseObject );</p>
<p>?&gt;<br />

Para utilizar o script acima, modifique as constantes:

  • SETTINGS_SGBD_HOST: IP do servidor;
  • SETTINGS_SGBD_PORT: porta de conexão do servidor;
  • SETTINGS_SGBD_USER: nome do usuário;
  • SETTINGS_SGBD_PASSWORD: senha do usuário;
  • SETTINGS_SGBD_DATABASE: banco de dados onde se localiza o problema;
  • SETTINGS_SGBD_FIX_TABLE: tabela onde se localiza o problema;
  • SETTINGS_SGBD_FIX_FIELD: campo onde se localiza o problema.
  • Lembre-se: Este script deve ser executado apenas uma vez! Na segunda execução o script tentará converter novamente os textos para Latin1, removendo todas as letras que estão acentuadas.

    O que você achou? Tem alguma sugestão para resolver este problema ou algo a dizer que complemente este artigo. Deixe seu comentário!

    Até mais!

    4 ideias sobre “Problema de acentuação no MySQL: Latin1 x UTF8

    1. Adriano

      Seu script é excelente, mas tenho uma dúvida, como eu poderia fazer para aplicar geral no banco, sem eu ter que ficar preenchendo o nome da tabela mais o campo, ou seja, que ele verificasse em todas as tabelas e em todos os campos. Teria como você me ajudar ?

      Responder
    2. Jadiel Alves

      Para arrumar a base:

      UPDATE tabela SET coluna1 = CONVERT(CAST(coluna1 as BINARY) USING utf8), coluna2 = CONVERT(CAST(coluna2 as BINARY) USING utf8);
      ALTER TABLE `tabela` CHARACTER SET utf8 COLLATE utf8_general_ci ROW_FORMAT = DYNAMIC;

      Para os arquivos PHP:
      header(‘Content-Type: text/html; charset=utf-8’);
      mysql_query(“SET NAMES ‘utf8′”);
      mysql_query(‘SET character_set_connection=utf8’);
      mysql_query(‘SET character_set_client=utf8’);
      mysql_query(‘SET character_set_results=utf8’);

      NO HTML:

      Responder

    Deixe uma resposta

    O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *