porównywanie baz MySQL w PHP
Często przy pracy nad aplikacjami z bazą SQL zdarza się sytuacja, kiedy baza ‘deweloperska’ uległa nieudokumentowanym dokładnie zmianom, i wreszcie trzeba je wdrożyć w wersji produkcyjnej. Oczywiście lepiej byłoby prowadzić dziennik zmian :) Kiedy jednak już jest za późno, przydaje się poniższy skrypt do porównywania baz. Wychwytuje on różnice na poziomie definicji tabel i pól, proponując stosowne polecenia typu CREATE, ALTER, itp. Propozycje te nie są doskonałe, trzeba zwracać uwagę zwłaszcza na klucze i wartości domyślne, ale na pewno ułatwia synchronizację.
Skrypt napisany na podstawie MySQL Database Diff Script, ale znacznie rozszerzony i zmodyfikowany. Enjoy! :)
<html> <head> <style> .deleted{ text-decoration:line-through; color:red; } .added{ color:green; } </style> </head> <body> < ?php /** * original by Adam Young http://adamyoung.net/ * modified and extended 2009-09-26 by ptrk http://nobigwords.ntxt.net/ * */ $src_host = ''; $src_user = 'root'; $src_pass = ''; $src_db = 'baza32_superskl_emisja'; $dst_host = ''; $dst_user = 'root'; $dst_pass = ''; $dst_db = 'baza32_superskl'; $src = mysql_connect($src_host, $src_user, $src_pass); if (!mysql_select_db($src_db, $src)) die("Could not find/USE source database: {$src_db}\n"); $src_tables = getTables($src); $dst = mysql_connect($dst_host, $dst_user, $dst_pass); if (!mysql_select_db($dst_db, $dst)) die("Could not find/USE destination database: {$dst_db}\n"); $dst_tables = getTables($dst); foreach ($src_tables as $t => $table) { $i = 0; $found = false; if(isset($dst_tables[$t])){ $dst_table = $dst_tables[$t]; if ($dst_table->name == $table->name) { $diff = compareDefinitions($table->definition, $dst_table->definition); if (count($diff) == 0){ echo "{$table->name}<br />"; }else{ echo "<b>{$table->name} is different</b><br /><ul>"; $alters = ''; foreach($diff as $col => $info){ echo "<li>$col : " . $info['info'] . "</li>"; $alters .= "alter table `" . $dst_table->name . "` " . $info['alter'] . ";\n"; } echo '</ul>'; echo ">pre<" . $alters . " >/pre<"; } unset($dst_tables[$i]); $found = true; } }else{ echo "<span class='deleted'>{$table->name} </span><br />"; echo ">pre<{$table->create}>/pre<<br />"; } } function getTables($link) { $rsrc = mysql_query('SHOW TABLES', $link); $tables = array(); while ($row = mysql_fetch_row($rsrc)) { $table = new table( $row[0], getTableDef($link, $row[0]), getTableCreate($link, $row[0]) ); $tables[$row[0]] = $table; } return $tables; } function getTableDef($link, $table) { $rsrc = mysql_query("DESCRIBE `{$table}`"); $result = array(); while($row = mysql_fetch_row($rsrc)){ list($name, $type, $null, $key, $default, $extra) = $row; $result[$name] = array($type, $null, $key, $default, $extra); } return $result; } function getTableCreate($link, $table) { $rsrc = mysql_query("SHOW CREATE TABLE `{$table}`"); $row = mysql_fetch_row($rsrc); $result = $row[1]; return $result; } class table { var $name; var $definition; var $create; function table($name, $def, $create) { $this->name = $name; $this->definition = $def; $this->create = $create; } } function compareDefinitions($defA, $defB){ $result = array(); foreach($defA as $col => $colDefA){ if(!isset($defB[$col])){ $result[$col]['info'] = "<span class='deleted'>deleted </span>"; $result[$col]['alter'] = "drop column `" . $col . "`"; }else{ if(implode(',',$colDefA) != implode(',',$defB[$col])){ list($typeA, $nullA, $keyA, $defaultA, $extraA) = $colDefA; list($typeB, $nullB, $keyB, $defaultB, $extraB) = $defB[$col]; $info = ''; if($typeA != $typeB) $info .= "different type $typeA/$typeB, "; if($nullA != $nullB) $info .= "null $nullA/$nullB, "; if($keyA != $keyB) $info .= "key: $keyA/$keyB, "; if($defaultA != $defaultB) $info .= "default: $defaultA/$defaultB, "; if($extraA != $extraB) $info .= "extra: $extraA/$extraB, "; $result[$col]['info'] = trim($info,', '); $result[$col]['alter'] = "change `$col` `$col` $typeA "; $result[$col]['alter'] .= ($defaultA == '') ? '' : "default '$defaultA' "; $result[$col]['alter'] .= ($nullA == 'NO') ? 'NOT NULL ' : ''; $result[$col]['alter'] .= "$extraA "; } unset($defB[$col]); } } foreach($defB as $colB => $colDefB){ list($typeB, $nullB, $keyB, $defaultB, $extraB) = $colDefB; $result[$colB]['info'] = "<span class='added'>added</span>"; $result[$colB]['alter'] = "add `$colB` $typeB "; } return $result; } function errors($link){ return mysql_errno($link) . ": " . mysql_error($link) . "\n"; } ?> </body> </html>