Default Characterset DB + Tabellen und Collation Felder

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Default Characterset DB + Tabellen und Collation Felder

    Das leidliche Problem der Character Sets und Kollationen in MySQL (>4)Datenbanken hat mir wie schon vielen zuvor richtig Probleme bereitet. Ein Projekt, dass auf zwei verschiedenen MySQL Servern arbeitet und jeweils mehrere Datenbanken dabei nutzt verursachte ständig Fehler (Illegal Mix of ... naja ihr wisst schon). Betroffen davon waren vor allem JOINS oder WHERE a=b Bedingungen mit Tabellenefeldern verschiedener Kollation. Mal latin1_swedish mal latin1_general und mal latin1_spanish... Kurzum: es musste alles auf einen Charset umgestellt werden. Das Default Character Set der DB, das Default Character Set der Tabellen und lbnl jedes einzelne Feld mit einer Kollation (char, varchar, enum, text)...

    Bei meiner Suche nach einer bequemen Abhilfe für dieses Problem bin ich nur auf ähnliche Requests gestossen, jedoch ohne nenneswerte Abhilfe. Als "nennenswerte Abhilfe" hätte ich zBsp. ein Skript gefunden, dass mir diese mühselige Arbeit alle Charsets und Kollationen anzupassen automatisch macht, denn sowas von Hand zu machen ist - wie ihr wisst - mühselige Arbeit .
    ... und deshalb habe ich ein Skript geschrieben, dass
    1. Den Default Charset der DB umstellt
    2. Alle Tabellen Default Charsets umstellt
    3. Alle Felder einer Tabelle durchläuft und die Kollation ändert.

    Das Skript ist sehr simpel und ich benutze es zum umstellen von latin1_swedisch auf latin1_spanish (wegen sortierung und synchronizität).
    Für alle, die mit dem ähnlichen Umstand konfrontiert sind will ich es hier mal veröffentlichen. Vielleicht findet es weiter Verwendung. Und ausserdem wünsche ich , dass alle gefeiten Proggis hier helfen evtl. Schwachstellen und Kompatibilitäts-probleme zu finden oder das Skript weiterzuentwickeln. Was ich zBsp noch nicht weiss, ob es problemlos nach utf8 ändert (jedenfalls nicht die Feldinhalte mit Sonderzeichen, aber da gibts ja scripts...)

    Unten an das Skript (bisher spärlich dokumentiert, aber für php-crakcs durchschaubar
    Ich freu mich auf Feedback und Anregungen. Bei Fragen könnt ihr mir eine PN hinterlassen oder hier posten.

    PHP-Code:
    <?
    // -------------------------------------------------
    /* CONFIGURATION */
    // -------------------------------------------------
    $conf = array();
        // database definition
    $conf["db_user"] = "mysqluser"; 
    $conf["db_pass"] = "password"; 
    $conf["db_host"] = "mysqhost"; 
    $conf["db_dbname"] = "mydatabase"; 
        // collation settings
    $conf["set_charset"] = "latin1";     
    $conf["set_collation"] = "latin1_general_ci";
        // program options
    $conf["set_dbdefault"] = true;     
    $conf["show_queries"] = true; 
    $conf["show_undosql"] = true; 
    $conf["execute_sql"] = true; 
    //
    // -------------------------------------------------
    /* ALTER TABLE QUERY CREATION */
    // -------------------------------------------------
    function cambioBdD($dbName,$tablename) 
    {
    global $conf, $DBA; 
    if($res = $DBA->db_query("SHOW CREATE TABLE " . $dbName . "." . $tablename,"ONE"))
    $query_out = "";
    $query_bck = "";
    $tempres = explode("<br />",nl2br($res[1]));
    //$tempres = explode(",",$res[1]);
    for($a=1;$a<count($tempres)-1;$a++)
    {     // lines in creation query except first and last
        if( (eregi("char",$tempres[$a]) || eregi(" text ",$tempres[$a]) ) && !ereg("KEY",$tempres[$a]) ) 
            {     // only when char type
            $tempres2 = explode(" ",trim($tempres[$a]));
            $query_out2 = $query_bck2 = "CHANGE ".$tempres2[0]." ".$tempres2[0];
            for($b=1;$b<count($tempres2);$b++)
                {
                if(!eregi("collat",strtolower($tempres2[$b])) && 
                   !eregi("latin",strtolower($tempres2[$b])) && 
                   !eregi("character",strtolower($tempres2[$b])) && 
                   !eregi("set",strtolower($tempres2[$b])) &&    
                   !eregi("utf8",strtolower($tempres2[$b]))  )
                    {
                    if( eregi(")",$tempres2[$b]) || eregi("text",trim($tempres2[$b]) ) )
                        $query_out2 .= " ".$tempres2[$b]." CHARACTER SET ".$conf["set_charset"].
                        " COLLATE ".$conf["set_collation"];    
                    else
                        $query_out2 .= " ".$tempres2[$b];
                    }
                $query_bck2.= " ".$tempres2[$b];
                }
            $query_out .= "\r\n".$query_out2."";
            $query_bck .= "\r\n".$query_bck2."";
            }
        }
    if($query_out != "") $query_out = "ALTER TABLE ".$tablename." ".$query_out.";";
    if($query_bck != "") $query_bck = "ALTER TABLE ".$tablename." ".substr(trim($query_bck),0,strlen($query_bck)-1).";";
    if($conf["set_dbdefault"]) $query_out = "ALTER TABLE ".$tablename." DEFAULT CHARACTER SET ".$conf["set_charset"].
    " COLLATE ".$conf["set_collation"].";\r\n".$query_out;
    return array( str_replace(",;",";",$query_bck), str_replace(",;",";",$query_out));
    }
    //
    // -------------------------------------------------
    /* SIMPLE MYSQL ABSTRACTION CLASS */
    // -------------------------------------------------
    class dba 
    {
    var $db_result = false;
    var $db_num_rows = 0;
    var $db_fetch_result_one = array();
    var $db_fetch_result_all = array();
    var $db_user;
    var $db_pass;
    var $db_host;
    var $db_dbname;
    var $db_link= false;
    function dba($conf){
        $this->db_user = $conf[db_user];
        $this->db_pass = $conf[db_pass];
        $this->db_host = $conf[db_host];
        $this->db_dbname = $conf[db_dbname];
        $this->db_connect($this->db_host,$this->db_user,$this->db_pass,$this->db_dbname); }
    function db_connect($HOST,$USER,$PASS,$DB){
        $this->db_link = mysql_connect($HOST,$USER,$PASS);
        $this->db_choose($DB);}
    function db_choose($DB){
        $erg = mysql_select_db($DB);}
    function db_list_tables($DB){
        $this->db_result = mysql_list_tables($DB);
        while($row = mysql_fetch_array($this->db_result)) $tables[] = $row[0];
        return $tables;    }
    function db_query($QUERY,$PARA2 = ""){
        $this->db_result = false;
        $this->db_result = mysql_query($QUERY);
        switch($PARA2){
            case "ONE":    $this->db_num_rows(); return $this->db_fetch_result_one(); break;
            case "ALL":    $this->db_num_rows(); return $this->db_fetch_result_all(); break;
            default:    break;}}
    function db_num_rows(){
        $this->db_num_rows = 0;
        $this->db_num_rows = @mysql_num_rows($this->db_result);}
    function db_fetch_result_one(){
        $this->db_num_rows();
        $this->db_fetch_result_one = array();
        $this->db_fetch_result_one = mysql_fetch_array($this->db_result);
        return $this->db_fetch_result_one;}
    function db_fetch_result_all(){
        $this->db_num_rows();
        $this->db_fetch_result_all = array();
        for ( $i = 0; $i < $this->db_num_rows; $i++){
            $this->db_fetch_result_all[$i] = mysql_fetch_array($this->db_result);}
        return $this->db_fetch_result_all;}
    function db_close_con(){
        mysql_close($this->db_link);}
    }     // end of class
    //
    // -------------------------------------------------
    /* -- EXECUTION --  ALTER COLLATION */
    // -------------------------------------------------
    $DBA = new dba($conf);
    echo "<pre>###\r\n# --- ALTER CHARSET COLATION OF TABLES IN DATABASE 
    '".$conf["db_host"].".".$conf["db_dbname"]."'\r\n# --- ".date("Y-m-d").", 
    '".$_SERVER["SCRIPT_NAME"]."'\r\n###\r\n" ;
    $UNDO = "";
    // ALTER DATABASE `remitel_dimt` DEFAULT CHARACTER SET latin1 COLLATE latin1_spanish_ci
    foreach($DBA->db_list_tables($conf["db_dbname"]) as $tablename)
        {
        if($QUERY = cambioBdD($cambio_db,$tablename))
            {
            if($conf["execute_sql"])    $DBA->db_query($QUERY[1]);
            if($conf["show_undosql"])    $UNDO .= $QUERY[0]."\r\n";
            if($conf["show_queries"])    echo $QUERY[1]."\r\n\r\n"; 
            }
        }
    $DBA->db_close_con();
    echo "<font color=#800000>###\r\n# --- COLLATIONS BEFORE CHANGE - UNDO QUERY \r\n###\r\n".$UNDO."</font>";
    echo "\r\n### done </pre>";
    ?>
Lädt...
X