PHP: Скрипт смены кодировки базы данных

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

Почему боль? Да потому что база данных выглядит вот так:


Работать с такими данными крайне проблематично. Поэтому рано или поздно эту проблему придется решать. Иногда она решается достаточно просто, но в большинстве случаев произвести простую конвертацию данных в читаемый вид не предоставляется возможным.
Единственным решением в данном случае будет постепенная обработка всей базы скриптом. Общий смысл данного скрипта следующий:

1) снимаем дамп структуры базы (для наглядности пусть старая база называется «old») и сохраняем его в файл;
2) заменяем в текстовом редакторе кодировку текстовых полей на нужную (например все вхождения «cp1251_general_ci» на «utf8_general_ci»);
3) создаем новую базу (например «new») и загружаем в нее дамп структуры;
4) порциями по 500 строк переносим данные из всех таблиц базы «old» в соответсвующие таблицы базы «new» .

Ниже приведен пример PHP скрипта (convert_db.php), который поможет Вам проделать пункт 4. Стоит заметить что конвертирование в нем производится из кодировки windows-1251 в utf-8.
Вы же должны будете указать свои кодировки!

Данный скрипт выполнит постепенный перенос всех данных из всех таблиц старой базы в новую.

set_time_limit(600);

$oldDb = mysqli_connect("OLD_DB_HOST", "OLD_DB_USER", "OLD_DB_USER", "old") or die('Can not connect OLD DB');

$newDb = mysqli_connect("NEW_DB_HOST", "NEW_DB_USER", "NEW_DB_USER", "new") or die('Can not connect NEW DB');
$newDb->query("SET NAMES 'utf8'"); 
$newDb->query("SET CHARACTER SET 'utf8'");
$newDb->query("SET SESSION collation_connection = 'utf8_general_ci'");

$resultTables = $oldDb->query('SHOW TABLES');
$page = empty($_GET['p']) ? 0 : (int)$_GET['p']; 
$onPage = 500;
$countDone = 0;
$tableName = empty($_GET['t']) ? '' : $_GET['t'];

while($table = $resultTables->fetch_array()) {
    echo '=> '.$table[0].'
'; if($tableName != '' && $tableName != $table[0]) { continue; } $tableName = $table[0]; $dataRows = $oldDb->query('SELECT * FROM '.$tableName.' LIMIT '.($page * $onPage).', '.$onPage); $sql = ''; while($row = $dataRows->fetch_assoc()) { $fs = $vs = ''; foreach($row as $f => $v) { if(!is_numeric($f)) { $fs .= ($fs == '' ? '' : ', ').'`'.$f.'`'; $vs .= ($vs == '' ? '' : ', ').'"'.str_replace('"', '\"', iconv('windows-1251', 'utf-8', $v)).'"'; } } if($sql == '') { $sql = 'INSERT INTO '.$tableName.' ('.$fs.') VALUES '; } $sqlSub = '('.$vs.'), '; $sql .= $sqlSub; ++$countDone; } if($countDone > 0) { $newDb->query(preg_replace('/,\s*$/isu', '', $sql)); break; } else { $page = 0; $tableName = ''; } } $newDb->close(); $oldDb->close(); if($countDone > 0) { ?> <script> setTimeout(function() { window.location = 'convert_db.php?t=<?php echo $tableName; ?>&p=<?php echo ($page + 1); ?>'; }, 1000); </script> <?php } echo $tableName.': Done '.(($page * $onPage) + $countDone);

После отработки скрипт с помощью JavaScript перенаправит вас на самого себя с доп. параметрами t и p. Они нужны для отслеживания текущей таблицы для перекидывания данных а так же смещения в рамках этой таблицы.

Запись опубликована в рубрике PHP с метками , , , , , , . Добавьте в закладки постоянную ссылку.