«Кракозябры» в БД или когда «Думать надо было раньше»

от автора

На днях столкнулся с глупейшей ситуацией. Запустили один веб-проект, все работает, код пишется и дополняется, базы данных наполняются. Разработка идет на тестовом хосте, затем изменения заливаются на сервер, вся проверка сводится к заходу на сам сайт и тесту всего и всея. Вдруг, выясняется, что буква «ш» не отображается на сайте, а вместо неё два ничего не значащих символа.

Та же история оказалась с буквой «И». Тут же заходим в СУБД на сервере и видим… сплошные «кракозябры», вместо кириллицы. Но латиница записывается нормально.

Конечно все подумали на проблемы с кодировками и естественно это так. Смотрим подробнее… Кодировка таблицы — UTF-8, кодировка нужных столбцов — UTF-8, кодировка в заголовках страницы — UTF-8, кодировка в браузере — UTF-8. Ну и конечно подвело промежуточное звено, кодировка соединения — cp1251. А все лишь потому, что не проверили идентичность настроек тестового и рабочего сервера БД. Глупая ошибка, но данных в БД уже полно и надо как-то их вернуть. Прогуглив все, что можно, было найдено несколько интересных sql-запросов, способы с шаманством кодировок в дампах, с помощью блокнота, и один php-скрипт, который отработав безошибочно, просто выдал те же иероглифы. Что то не помогло, что то просто не подходит.

Моё решение банальное, но я не нашел подобного на просторах сети.
Пишем маленький php скрипт перегона нужных таблиц в нужный формат.

<?php define('BD_HOST','localhost'); define('BD_PASS','password'); define('BD_LOGIN','login');   //доступ к БД define('BD_FROM','bd1');   //исходная БД define('BD_IN','bd2');   //конечная БД  $tables = array (	'table1', 					'table2', 					'table3', 					'table4', 					'table5');   //список  нужных таблиц для конвертирования, эти таблицы должны быть как в исходной, так и в конечной БД(в конечной, должны быть пустыми)  foreach ($tables as $table) { 	mysql_connect(BD_HOST,BD_LOGIN,BD_PASS); 	mysql_select_db(BD_FROM);  	$query_select_from = "SELECT * FROM $table;"; 	$result = mysql_query($query_select_from);  	mysql_close();   //запросили все косячные данные и закрыли соединение  	mysql_connect(BD_HOST,BD_LOGIN,BD_PASS); 	mysql_select_db(BD_IN); 	mysql_query('set character_set_client="utf8"'); 	mysql_query('set character_set_results="utf8"'); 	mysql_query('set collation_connection="utf8_general_ci"'); 	mysql_query("set names utf8");   //открыли новое соединение, но уже указав все недостающие настройки, из за которых произошло такое недопущение   	while ($t = mysql_fetch_assoc($result)) { 		$values = ''; 		$f = false; 		foreach($t as $val) { 			$p = ($f)?',':''; 			$f = true; 			$add = (is_int($val))?"$val":"'$val'"; 			$values.= "$p $add"; 		}; 		$insert_in = "INSERT $table VALUES($values)"; 		mysql_query($insert_in);   //запись прочтенной строки, уже в нормальном соединении 	}; 	mysql_close();   //закрываем соединение, что бы открыть его уже для другой таблицы. };  ?> 

Вот и все. Скрипт сделал именно то, что было нужно и писался за пару минут, поэтому могут быть удивления, что это же можно сделать более гибким и оптимизированным, а еще и ООП неплохо прикрутить бы.

Надеюсь, что данный скрипт пригодится кому-либо.
Спасибо за внимание.

ссылка на оригинал статьи http://habrahabr.ru/post/201802/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *