Мне нужно использовать PHP для копирования данных из одной базы данных MySQL в другую.
Я могу построить и собрать все значения, чтобы перейти в другую базу данных, но сначала я хочу убедиться, что база данных имеет правильные поля перед вставкой.
Например, скажем, что я собираюсь копировать данные из tableA в tableB.
Я могу настроить tableB так же, как tableA, но в будущем я могу добавить столбцы в tableA и забыть добавить их в tableB, тогда мой PHP-скрипт попытается вставить данные в столбец, который не существует в tableB, и он будет потерпеть неудачу.
Поэтому я хочу сравнить таблицуA с таблицей B и любыми столбцами, которые tableA имеет, что tableB не добавляет их в tableB.
Может ли кто-нибудь сказать мне, как это сделать?
Спасибо всем, на основании всей вашей помощи я смог написать класс 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 */ }
SHOW COLUMNS FROM «table»
Я не на 100% уверен, что это то, что вы ищете, но я часто делал небольшое обслуживание базы данных. Нам нужен был способ убедиться, что devDB и prodDB были идентичны по своей структуре, и я отыскал этот отличный маленький инструмент. Инструмент создает sql-alter-script, который может быть запущен в базе данных, которую вы хотите исправлять. Это написано на perl, поэтому я думаю, что он должен работать на кросс-платформе, но я только пробовал это на linux.
Этот инструмент называется mySQLdiff, является бесплатным и может быть загружен на http://www.mysqldiff.org .
вы можете изучить некоторые phpclasses, которые сделают это для вас http://www.phpclasses.org/search.html?words=mysql+sync&x=0&y=0&go_search=1
Вы можете написать функцию, которая возвращает столбцы из таблицы, например:
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 () в свой сценарий передачи данных, каждый раз запуская его, чтобы убедиться, что таблицы одинаковы.
Конечно, вы можете сделать этого фаворита и сообщить ему, какие столбцы отличаются между двумя таблицами, что делает его более удобным для их синхронизации.
Это очень сложная задача, и, насколько я знаю, многие пытались ее решить до сих пор (к сожалению, я не знаю ни одного 100% -ного гарантированного решения).
Я бы сказал, что перед тем, как перейти к реализации собственного решения, вы должны взглянуть и узнать о проблемах, с которыми вам придется столкнуться, прочитав об эволюции Схемы, рефакторинге Схемы, управлении версиями схемы и т. Д.
Впоследствии вы можете взглянуть на PHP MDB2_Schema (некоторые другие документы в этой статье ).
Если вы не привязаны к PHP, тогда вы также можете взглянуть на Sundog, который предоставляет набор передовых рефакторингов схемы.
Как только вы получите надежный инструмент миграции схемы для своего приложения, перенос данных будет просто тривиальной задачей.
./alex
Вероятно, самый простой способ сделать это
$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.
Используйте инструмент сравнения TOAD для MySQL Schema, он будет смотреть на таблицы, визуально показывать различия и генерировать SQL-запросы для синхронизации структуры таблиц. Также он сравнивает данные.