Problembeschreibung

Viele CMS wie Joomla, Wordpress, Drupal oder auch andere Framework, Webshops, Foren usw. nutzen für die Benennung Ihrer Datenbank-Tabellen Präfixe. Oft wird der Wunschpräfix schon bei der Installation abgefragt und alle Tabellen entsprechend benannt. In früheren Joomla-Installationen (z.B. bis 2.5) wurde ein Präfix jos_ vorgeschlagen. Wenn man diesen so verwendet, birgt das jedoch ein Sicherheitsrisiko. Jeder potentielle Hacker kenn so schon die Namen der Datenbanktabellen. Verwendet man hingegen eigenen Präfixe für die Tabellen, schafft man höhere Sicherheit. Seit Joomla 3 wird der Präfix genau aus diesem Grund zufällig erzeugt und vorgeschlagen. Wurde dieser Sicherheitsaspekt bei der Installation nicht berücksichtigt sollte man die Umbenennung nachträglich machen - Aber wie?

Außerdem kann es in der Administration und Pflege der Datenbank weitere Gründe für eine Umbenennung der Tabellen-Präfixe geben, z.B. wenn man mal eben vor einem Datenrestore schnell noch die alten Tabellen umbenennen will, ändert man einfach mal den Präfix.

Nun können in einem Projekt schnell man 100 und mehr Tabellen liegen. Diese manuell umzubenennen nervt einfach. Über MySQL und auch PhpMyAdmin oder Adminer gibt es keine Möglichkeiten dies elegant und schnell zu erledigen. Man müsste wirklich Tabelle für Tabelle einzeln umbenennen.

Das machen Programmierer natürlich nicht, deshalb ist nachfolgendes Script entstanden.

 

Präfix aller Tabellen mit gleichem Präfix über ein PHP-Script ändern

Das Script basiert auf einem Script von Robert Dunham. Dieses ist recht gut, hat aber zwei kleine Nachteile:

  1. Es sucht nach dem für den Präfix üblichen Unterstrich _ und trennt dort prinzipiell Präfix und Restname. In meinen Tabellen verwende ich weiter _ als Gruppierung der Tabellenname und auch der Präfixe. Z.B. jos_v31_ für Joomla-Projekte der Version 3.1.
  2. Datenbanken können auch mehrere unterschiedliche Präfixe enthalten, z.B: wenn ich wie oben beschrieben zunächst ein Kopie vor einem Restore oder einer Migration machen will. Dann kann man natürlich nicht mit dem pauschalen Suchen nach _ vorgehen.



Aus genannten Gründen habe ich das Script modifiziert so dass man nun einen alten Such-Präfix und einen neuen Ersetzen-Präfix eingeben kann. Bei der Gelegenheit habe ich es auf msqli umgestellt, alles in eine einzige Schleife gepackt und einige Kontrollausgaben eingefügt.

Das Ergebnis sieht nun so aus:

 

<html>
<head>
<title>MySQL Table Prefix Changer</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css">
.renamed { color: green; }
.skipped { color: #F93; }
.failed { color: #C00; }
</style>
</head>

<body>
<?php
// Check for POST data
$action = isset($_REQUEST['action'])? $_REQUEST['action'] : false;

if (!$action) :
?>
<form name="form1" method="post" action="<?php echo basename($_SERVER['PHP_SELF']); ?>">
    <table width="75%" border="0" cellspacing="2" cellpadding="2">
        <tr>
        <td>Enter database name:</td><td><input name="d" type="text" id="d" size="50"></td>
        </tr><tr>
            <td>Enter database user</td><td><input name="u" type="text" id="u" size="50"></td>
        </tr><tr>
            <td>Enter database password:</td><td><input name="p" type="password" id="p" size="50"></td>
        </tr><tr>
            <td>Enter Old Prefix:</td><td><input name="o" type="text" id="o" size="50" value="(Do include the trailing last underscore)"></td>
        </tr><tr>
            <td>Enter New Prefix:</td><td><input name="n" type="text" id="n" size="50" value="(Do include the trailing last underscore)"></td>
        </tr><tr>
        <td>&nbsp;</td><td>&nbsp;</td>
    </tr><tr>
            <td colspan="2" align="center"><input name="action" type="hidden" id="action" value="data"><input type="submit" name="Submit" value="Change Table Prefixes"></td>
    </tr>
    </table>
</form>
<?php
else :

$mysql_db = (string)$_REQUEST['d'];
$mysql_user = (string)$_REQUEST['u'];
$mysql_pass = (string)$_REQUEST['p'];
$oldPrefix = (string)$_REQUEST['o'];
$newPrefix = (string)$_REQUEST['n'];
$count = $renamed = $skipped = $failed = 0;

// Open MySQL link
$mysqli = new mysqli("localhost", $mysql_user, $mysql_pass, $mysql_db);
if ($mysqli->connect_errno) echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;

$tableList = array();
$tables = $mysqli->query("SHOW TABLES");
for ($row_no = 0; $row_no <= $tables->num_rows - 1; $row_no++) {
    $tables->data_seek($row_no);
    $row = $tables->fetch_assoc();
    $value = $row['Tables_in_'.$mysql_db];

echo "<br>$value ";
    $count++;
    if (strpos($value, $oldPrefix) === 0) {
        $newTbl = preg_replace('/^'.$oldPrefix.'/',$newPrefix, $value);
        $mysqli->query(sprintf('RENAME TABLE %s TO %s', $value, $newTbl));
        if ($mysqli->errno) {
            printf(" <span class=\"failed\">failed %s</span>\n", $mysqli->connect_error);
            $failed++;
        } else {
            echo " ++ renamed in <span class=\"renamed\">$newTbl</span>\n";
            $renamed++;
        }
    } else {
        $skipped++;
        echo " --  <span class=\"skipped\">skipped</span>";
    }
}

echo "<hr>tables find: $count";
echo "<br>tables <span class=\"skipped\">skipped: $skipped </span>";
echo "<br>tables <span class=\"renamed\">renamed: $renamed </span>";
echo "<br>tables <span class=\"failed\">failed: $failed </span>";

endif;
?>

 

 



Wer zu faul zum Tippen ist und das Script benötigt, kann es hier herunterladen.

{attachments} 

 

Wenn Ihnen dieser Beitrag geholfen und viel Zeit gespart hat, zeigen Sie sich erkenntlich: Über einen Klick auf Google+1 oder Rückmeldungen freue ich mich. Zeigen Sie mir, dass sich die Mühe für die Beitragerstellung gelohnt hat. Schenken Sie auch den Produktwerbungen Ihre Beachtung, denn damit wird mein Aufwand für diese Beiträge refinanziert.