2009-03-09 2 views
3

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

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

Например, скажем, что я собираюсь копировать данные из tableA в tableB.

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

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

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

ответ

5

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

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 
    */ 
} 
0

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

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() в свой сценарий передачи данных, каждый раз запуская его, чтобы убедиться, что таблицы одинаковы.

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

0

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

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

Далее , вы можете посмотреть на PHP MDB2_Schema (дополнительная документация в этом article).

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

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

./alex

1

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

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

0

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

$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 
} 

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

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

0

Использование ЖАБА для MySQL схемы инструмента для сравнения, это будет выглядеть на столах, показать вам различие визуально и генерировать запросы SQL для синхронизации структуры таблиц. Также он сравнивает данные.

Смежные вопросы