Поиск и замена по всей базе данных MySQL

Увидел в сообществе вопросы по поводу изменения путей в базе данных при переезде. Для замены путей в дампе можно воспользоваться скриптом 1d10t : livestreet.ru/blog/tips_and_tricks/12689.html

Для тех, у кого нет доступа к консоли сервера или есть желание сделать замену на рабочей БД — есть нижеприведенный скрипт, который поможет найти и заменить пути на рабочей базе данных простым вызовом файла через браузер.

Для этого нужно сделать следующие шаги:
  1. Сохранить код, размещенный ниже, в файл. Например: mysql-replace-all.php
  2. Изменить в файле значения, набранные заглавными русскими буквами (строку поиска, строку замены, имя базы данных, имя пользователя базы данных, пароль пользователя базы данных) на ваши.
  3. Забэкапить базу данных (либо через консоль, либо через экспорт в PHPMyAdmin) — обязательно.
  4. Проверить восстановление базы данных из бэкапа.
  5. Скопировать файл скрипта (mysql-replace-all.php) на сервер, где расположен сайт.
  6. Запустить скрипт из браузера: ВАШ-САЙТ.RU/mysql-replace-all.php
  7. Увидеть в браузере результат работы.

Перед заменой настоятельно рекомендую сделать поиск изменив значение переменной $queryType на 'search' для того, чтобы убедиться в правильности настройки скрипта и его работоспособности. При поиске скрипт ничего не меняет в БД и выводит в браузере только результат поиска.


<?php
// Written by Mark Jackson @ MJDIGITAL
// http://www.mjdigital.co.uk/blog

// Ищем...
$search        = 'ЧТО_НУЖНО_ЗАМЕНИТЬ'; // Например: 'www.old-site.ru'

// Меняем на... Используется при $queryType = 'replace'
$replace    = 'НА_ЧТО_ЗАМЕНЯЕМ'; // Например: 'www.new-site.ru'

// Настройки базы данных
$hostname = "localhost";
$database = "ИМЯ_БАЗЫ_ДАННЫХ";
$username = "ИМЯ_ПОЛЬЗОВАТЕЛЯ_БАЗЫ_ДАННЫХ";
$password = "ПАРОЛЬ_ПОЛЬЗОВАТЕЛЯ_БАЗЫ_ДАННЫХ";

// Варианты значения переменной $queryType 'search' (вывод результатов поиска) или 'replace' (поиск с заменой)
$queryType = 'replace';

// Показывать ошибки или нет (true/false)
$showErrors = true;

//////////////////////////////////////////////////////
//
//        Код ниже не редактировать
//
//////////////////////////////////////////////////////

if($showErrors) {
    error_reporting(E_ALL);
    ini_set('error_reporting', E_ALL);
    ini_set('display_errors',1);
}
$MJCONN = mysql_pconnect($hostname, $username, $password) or trigger_error(mysql_error(),E_USER_ERROR);
mysql_select_db($database,$MJCONN);
$table_sql = 'SHOW TABLES';
$table_q = mysql_query($table_sql,$MJCONN) or die("Cannot Query DB: ".mysql_error());
$tables_r = mysql_fetch_assoc($table_q);
$tables = array();
do{
    $tables[] = $tables_r['Tables_in_'.strtolower($database)];
}while($tables_r = mysql_fetch_assoc($table_q));
$use_sql = array();
$rowHeading = ($queryType=='replace') ? 
        'Replacing \''.$search.'\' with \''.$replace.'\' in \''.$database."'\n\nSTATUS    |    ROWS AFFECTED    |    TABLE/FIELD    (+ERROR)\n"
      : 'Searching for \''.$search.'\' in \''.$database."'\n\nSTATUS    |    ROWS CONTAINING    |    TABLE/FIELD    (+ERROR)\n";
$output = $rowHeading;
$summary = '';
foreach($tables as $table) {
    $field_sql = 'SHOW FIELDS FROM '.$table;
    $field_q = mysql_query($field_sql,$MJCONN);
    $field_r = mysql_fetch_assoc($field_q);
    do {
        $field = $field_r['Field'];
        $type = $field_r['Type'];

        switch(true) {
            case stristr(strtolower($type),'char'): $typeOK = true; break;
            case stristr(strtolower($type),'text'): $typeOK = true; break;
            case stristr(strtolower($type),'blob'): $typeOK = true; break;
            case stristr(strtolower($field_r['Key']),'pri'): $typeOK = false; break;
            default: $typeOK = false; break;
        }
        if($typeOK) {
            $handle = $table.'_'.$field;
            if($queryType=='replace') {
                $sql[$handle]['sql'] = 'UPDATE '.$table.' SET '.$field.' = REPLACE('.$field.',\''.$search.'\',\''.$replace.'\')';
            } else {
                $sql[$handle]['sql'] = 'SELECT * FROM '.$table.' WHERE '.$field.' REGEXP(\''.$search.'\')';
            }
            $error = false;
            $query = @mysql_query($sql[$handle]['sql'],$MJCONN) or $error = mysql_error();
            $row_count = @mysql_affected_rows() or $row_count = 0;
            $sql[$handle]['result'] = $query;
            $sql[$handle]['affected'] = $row_count;
            $sql[$handle]['error'] = $error;
            $output .= ($query) ? 'OK        ' : '--        ';
            $output .= ($row_count>0) ? '<strong>'.$row_count.'</strong>            ' : '<span style="color:#CCC">'.$row_count.'</span>            ';
            $fieldName = '`'.$table.'`.`'.$field.'`';
            $output .= $fieldName;
            $erTab = str_repeat(' ', (60-strlen($fieldName)) );
            $output .= ($error) ? $erTab.'(ERROR: '.$error.')' : '';
            $output .= "\n";
        }
    }while($field_r = mysql_fetch_assoc($field_q));
}
echo '<pre>';
echo $output."\n";
echo '<pre>';
?>


ps.
Еще раз настоятельно рекомендую делать бэкап базы данных. Или экспериментировать на локальной копии сайта.

pps.
Скрипт лично проверен. Использовался не раз и не только на сайтах LiveStreet.

2 комментария

avatar
Буду рад, если администраторы посчитают полезным разместить данный топик в блоге Tips & tricks.
avatar
скрипт ломает сериализированные строки. Используйте это решение. Charset устанавливать в utf8.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.