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:
[php]
<?php
set_time_limit(0); // Tempo máximo de execução: sem limite (0).
// ———————————————————————-
// Configurações
// ———————————————————————-
define("SETTINGS_SGBD_HOST", "localhost");
define("SETTINGS_SGBD_PORT", "3306");
define("SETTINGS_SGBD_USER", "");
define("SETTINGS_SGBD_PASSWORD", "");
define("SETTINGS_SGBD_DATABASE", "");
define("SETTINGS_SGBD_FIX_TABLE", "");
define("SETTINGS_SGBD_FIX_FIELD", "");
// ———————————————————————-
// Conectar ao Banco de Dados
// ———————————————————————-
$lobj_databaseObject = mysql_connect(SETTINGS_SGBD_HOST.":".SETTINGS_SGBD_PORT, SETTINGS_SGBD_USER, SETTINGS_SGBD_PASSWORD);
mysql_select_db(SETTINGS_SGBD_DATABASE);
if ( $lobj_databaseObject == false ) exit;
mysql_set_charset(‘latin1’, $lobj_databaseObject);
// ———————————————————————-
// Atualiza a tabela corrigindo a codificação
// ———————————————————————-
$lstr_SQLQuery = "SELECT ".SETTINGS_SGBD_FIX_FIELD." FROM ".SETTINGS_SGBD_FIX_TABLE;
$lobj_recordsetFields = mysql_query ($lstr_SQLQuery, $lobj_databaseObject);
if ( mysql_num_rows($lobj_recordsetFields) > 0 ) {
while ($lobj_rowTerm = mysql_fetch_object( $lobj_recordsetFields )) {
$lstr_fixFieldContent = eval( "return $lobj_rowTerm->".SETTINGS_SGBD_FIX_FIELD.";");
$lstr_SQLQuery = "UPDATE ".SETTINGS_SGBD_FIX_TABLE." SET ".SETTINGS_SGBD_FIX_FIELD." = ‘".mb_convert_encoding($lstr_fixFieldContent, ‘ISO-8859-1’, ‘UTF-8′)."’ WHERE ".SETTINGS_SGBD_FIX_FIELD." LIKE ‘$lstr_fixFieldContent’";
mysql_query ($lstr_SQLQuery, $lobj_databaseObject);
}
}
// ———————————————————————-
// Desconectar do Banco de Dados
// ———————————————————————-
mysql_close ( $lobj_databaseObject );
?>
[/php]
Para utilizar o script acima, modifique as constantes:
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!
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:
e como saber qual campo da tabela e a propria tabela está em látin1?
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 ?
Muito bom cara! Resolveu meu problema