Как я могу синхронизировать две таблицы базы данных с PHP? - PullRequest
3 голосов
/ 09 марта 2009

Мне нужно использовать PHP для копирования данных из одной базы данных MySQL в другую.

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

Например, скажем, я собираюсь копировать данные из таблицы A в таблицу B.

Я могу настроить tableB так, чтобы она выглядела как tableA, но в будущем я могу добавить столбцы в tableA и забыть добавить их в tableB, тогда мой PHP-скрипт попытается вставить данные в столбец, который не существует в tableB и это не удастся.

Итак, я хочу сравнить tableA с tableB и любые столбцы, которые в tableA имеют эту tableB, не добавляют их в tableB.

Может кто-нибудь сказать мне, как это сделать?

Ответы [ 8 ]

5 голосов
/ 17 марта 2009

Спасибо всем, благодаря всей вашей помощи я смог написать класс PHP, который копирует любые столбцы из таблицы A в таблицу B, если их еще нет:

class MatchTable 
{
    var $_table_one_name;
    var $_table_two_name;

    var $_table_one_db_user;
    var $_table_one_db_pass;
    var $_table_one_db_host;
    var $_table_one_db_name;

    var $_table_two_db_user;
    var $_table_two_db_pass;
    var $_table_two_db_host;
    var $_table_two_db_name;

    var $_table_one_columns = array();
    var $_table_two_columns = array();
    var $_table_one_types = array();
    var $_table_two_types = array();

    var $_table_one_link;
    var $_table_two_link;

    var $_isTest;


    function MatchTable($isLive = true)
    {
        $this->_isTest = !$isLive;
    }

    function matchTables($table1, $table2)
    {
        $this->_table_one_name = $table1;
        $this->_table_two_name = $table2;

        if(isset($this->_table_one_db_pass))
        {
            $this->db_connect('ONE');
        }
        list($this->_table_one_columns,$this->_table_one_types) = $this->getColumns($this->_table_one_name);

        if(isset($this->_table_two_db_pass))
        {
            $this->db_connect('TWO');
        }
        list($this->_table_two_columns,$this->_table_two_types) = $this->getColumns($this->_table_two_name);

        $this->addAdditionalColumns($this->getAdditionalColumns());
    }

    function setTableOneConnection($host, $user, $pass, $name)
    {
        $this->_table_one_db_host = $host;
        $this->_table_one_db_user = $user;
        $this->_table_one_db_pass = $pass;
        $this->_table_one_db_name = $name;
    }

    function setTableTwoConnection($host, $user, $pass, $name)
    {
        $this->_table_two_db_host = $host;
        $this->_table_two_db_user = $user;
        $this->_table_two_db_pass = $pass;
        $this->_table_two_db_name = $name;
    }

    function db_connect($table)
    {
        switch(strtoupper($table))
        {
            case 'ONE':
                $host = $this->_table_one_db_host;
                $user = $this->_table_one_db_user;
                $pass = $this->_table_one_db_pass;
                $name = $this->_table_one_db_name;
                $link = $this->_table_one_link = mysql_connect($host, $user, $pass, true);
                mysql_select_db($name) or die(mysql_error());
            break;
            case 'TWO';
                $host = $this->_table_two_db_host;
                $user = $this->_table_two_db_user;
                $pass = $this->_table_two_db_pass;
                $name = $this->_table_two_db_name;
                $link = $this->_table_two_link = mysql_connect($host, $user, $pass, true);
                mysql_select_db($name) or die(mysql_error());
            break;
            default:
                die('Improper parameter in MatchTable->db_connect() expecting "one" or "two".');
            break;
        }
        if (!$link) {
            die('Could not connect: ' . mysql_error());
        }
    }

    function getColumns($table_name)
    {
        $columns = array();
        $types = array();
        $qry = 'SHOW COLUMNS FROM '.$table_name;
        $result = mysql_query($qry) or die(mysql_error());
        while($row = mysql_fetch_assoc($result))
        {
            $field = $row['Field'];
            $type = $row['Type'];
            /*
            $column = array('Field' => $field, 'Type' => $type);
            array_push($columns, $column);
            */
            $types[$field] = $type;
            array_push($columns, $field);
        }
        $arr = array($columns, $types);
        return $arr;
    }

    function getAdditionalColumns()
    {
        $additional = array_diff($this->_table_one_columns,$this->_table_two_columns);
        return $additional;
    }

    function addAdditionalColumns($additional)
    {
        $qry = '';
        foreach($additional as $field)
        {
            $qry = 'ALTER TABLE '.$this->_table_two_name.' ADD '.$field.' '.$this->_table_one_types[$field].'; ';

            if($this->_isTest)
            {
                echo $qry.'<br><br>';
            }
            else
            {
                mysql_query($qry) or die(mysql_error());
            }
        }
    }

    /**
     * End of Class
     */
}
1 голос
/ 10 марта 2009

вы можете посмотреть на некоторые phpclasses, которые делают это для вас http://www.phpclasses.org/search.html?words=mysql+sync&x=0&y=0&go_search=1

1 голос
/ 09 марта 2009

Я не на 100% уверен, что это то, что вы ищете, но некоторое время назад я занимался небольшим обслуживанием баз данных. Нам нужен был способ убедиться, что devDB и prodDB идентичны по структуре, и я разыскал этот изящный маленький инструмент. Инструмент создает sql-alter-script, который можно запустить в базе данных, которую вы бы хотели исправить. Он написан на Perl, поэтому я думаю, что он должен работать кроссплатформенно, но я только попробовал это на Linux.

Инструмент называется mySQLdiff, является бесплатным и может быть загружен по адресу www.mysqldiff.org .

1 голос
/ 09 марта 2009
SHOW COLUMNS FROM «table»
0 голосов
/ 09 июля 2012

Используйте инструмент сравнения TOAD for MySQL Schema, он будет просматривать таблицы, визуально показывать различия и генерировать SQL-запросы для синхронизации структуры таблиц. И это делает сравнение данных.

0 голосов
/ 09 марта 2009

Вероятно, самый простой способ сделать это будет

$sql = "SELECT * FROM tableA WHERE 1"

$results = mysql_fetch_assoc($sql);

$sql = "truncate table tableB";

// run truncate

foreach($result as $update){

   $sql = "Insert into table b VALUES(....)"

   // run insert
}

Но здесь нужно быть предельно осторожным. Убедитесь, что единственный процесс, который может записать в таблицу B, - это тот, который выполняет копирование из таблицы А, иначе вы потеряете данные. Также убедитесь, что ничто не может записать в таблицу А после начала этого процесса.

Лучшей практикой для этого было бы делать это не в php, а через репликацию mysql.

0 голосов
/ 09 марта 2009

Это очень сложная задача, и, насколько я знаю, многие пытались решить ее до сих пор (к сожалению, я не знаю ни одного 100% гарантированного решения).

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

После этого вы можете взглянуть на PHP MDB2_Schema (еще немного документации в этой статье ).

Если вы не привязаны к PHP, вы также можете взглянуть на Sundog , который предоставляет набор расширенных возможностей рефакторинга схемы.

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

. / Alex

0 голосов
/ 09 марта 2009

Вы можете написать функцию, которая возвращает столбцы из таблицы, например:

function columns($table) {

    $columns = array();
    $sql = "desc $table";
    $q = mysql_query($sql);

    while ($r = mysql_fetch_array($q)) {

       $columns[] = $r[0];

    }

    return $columns;

}

Далее вы можете сравнить столбцы из двух таблиц:

function tables_different($table1, $table2) {

  $cols1 = columns($table1);
  $cols2 = columns($table2);

  return count(array_diff($cols1, $cols2)) ? true : false;

}

Теперь вы можете интегрировать функцию tables_different () в свой скрипт передачи данных, каждый раз запуская его, чтобы убедиться, что таблицы совпадают.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...