A script to change all tables and fields to the utf-8-bin collation in MYSQL

后端 未结 16 916
有刺的猬
有刺的猬 2020-12-04 06:24

Is there a SQL or PHP script that I can run that will change the default collation in all tables and fields in a database?

I can write one

相关标签:
16条回答
  • 2020-12-04 06:46

    Can be done in a single command (rather than 148 of PHP):

    mysql --database=dbname -B -N -e "SHOW TABLES" \
    | awk '{print "SET foreign_key_checks = 0; ALTER TABLE", $1, "CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci; SET foreign_key_checks = 1; "}' \
    | mysql --database=dbname &
    

    You've got to love the commandline... (You might need to employ the --user and --password options for mysql).

    EDIT: to avoid foreign key problems, added SET foreign_key_checks = 0; and SET foreign_key_checks = 1;

    0 讨论(0)
  • 2020-12-04 06:46

    A more complete version of the script above can be found here:

    http://www.zen-cart.com/index.php?main_page=product_contrib_info&products_id=1937

    Please leave any feedback about this contribution here:http://www.zen-cart.com/forum/showthread.php?p=1034214

    0 讨论(0)
  • 2020-12-04 06:48

    OK, I wrote this up taking into account what was said in this thread. Thanks for the help, and I hope this script will help out others. I don't have any warranty for its use, so PLEASE BACKUP before running it. It should work with all databases; and it worked great on my own.

    EDIT: Added vars at the top for which charset/collate to convert to. EDIT2: Changes the database's and tables' default charset/collate

    <?php
    
    function MysqlError()
    {
        if (mysql_errno())
        {
            echo "<b>Mysql Error: " . mysql_error() . "</b>\n";
        }
    }
    
    $username = "root";
    $password = "";
    $db = "database";
    $host = "localhost";
    
    $target_charset = "utf8";
    $target_collate = "utf8_general_ci";
    
    echo "<pre>";
    
    $conn = mysql_connect($host, $username, $password);
    mysql_select_db($db, $conn);
    
    $tabs = array();
    $res = mysql_query("SHOW TABLES");
    MysqlError();
    while (($row = mysql_fetch_row($res)) != null)
    {
        $tabs[] = $row[0];
    }
    
    // now, fix tables
    foreach ($tabs as $tab)
    {
        $res = mysql_query("show index from {$tab}");
        MysqlError();
        $indicies = array();
    
        while (($row = mysql_fetch_array($res)) != null)
        {
            if ($row[2] != "PRIMARY")
            {
                $indicies[] = array("name" => $row[2], "unique" => !($row[1] == "1"), "col" => $row[4]);
                mysql_query("ALTER TABLE {$tab} DROP INDEX {$row[2]}");
                MysqlError();
                echo "Dropped index {$row[2]}. Unique: {$row[1]}\n";
            }
        }
    
        $res = mysql_query("DESCRIBE {$tab}");
        MysqlError();
        while (($row = mysql_fetch_array($res)) != null)
        {
            $name = $row[0];
            $type = $row[1];
            $set = false;
            if (preg_match("/^varchar\((\d+)\)$/i", $type, $mat))
            {
                $size = $mat[1];
                mysql_query("ALTER TABLE {$tab} MODIFY {$name} VARBINARY({$size})");
                MysqlError();
                mysql_query("ALTER TABLE {$tab} MODIFY {$name} VARCHAR({$size}) CHARACTER SET {$target_charset}");
                MysqlError();
                $set = true;
    
                echo "Altered field {$name} on {$tab} from type {$type}\n";
            }
            else if (!strcasecmp($type, "CHAR"))
            {
                mysql_query("ALTER TABLE {$tab} MODIFY {$name} BINARY(1)");
                MysqlError();
                mysql_query("ALTER TABLE {$tab} MODIFY {$name} VARCHAR(1) CHARACTER SET {$target_charset}");
                MysqlError();
                $set = true;
    
                echo "Altered field {$name} on {$tab} from type {$type}\n";
            }
            else if (!strcasecmp($type, "TINYTEXT"))
            {
                mysql_query("ALTER TABLE {$tab} MODIFY {$name} TINYBLOB");
                MysqlError();
                mysql_query("ALTER TABLE {$tab} MODIFY {$name} TINYTEXT CHARACTER SET {$target_charset}");
                MysqlError();
                $set = true;
    
                echo "Altered field {$name} on {$tab} from type {$type}\n";
            }
            else if (!strcasecmp($type, "MEDIUMTEXT"))
            {
                mysql_query("ALTER TABLE {$tab} MODIFY {$name} MEDIUMBLOB");
                MysqlError();
                mysql_query("ALTER TABLE {$tab} MODIFY {$name} MEDIUMTEXT CHARACTER SET {$target_charset}");
                MysqlError();
                $set = true;
    
                echo "Altered field {$name} on {$tab} from type {$type}\n";
            }
            else if (!strcasecmp($type, "LONGTEXT"))
            {
                mysql_query("ALTER TABLE {$tab} MODIFY {$name} LONGBLOB");
                MysqlError();
                mysql_query("ALTER TABLE {$tab} MODIFY {$name} LONGTEXT CHARACTER SET {$target_charset}");
                MysqlError();
                $set = true;
    
                echo "Altered field {$name} on {$tab} from type {$type}\n";
            }
            else if (!strcasecmp($type, "TEXT"))
            {
                mysql_query("ALTER TABLE {$tab} MODIFY {$name} BLOB");
                MysqlError();
                mysql_query("ALTER TABLE {$tab} MODIFY {$name} TEXT CHARACTER SET {$target_charset}");
                MysqlError();
                $set = true;
    
                echo "Altered field {$name} on {$tab} from type {$type}\n";
            }
    
            if ($set)
                mysql_query("ALTER TABLE {$tab} MODIFY {$name} COLLATE {$target_collate}");
        }
    
        // re-build indicies..
        foreach ($indicies as $index)
        {
            if ($index["unique"])
            {
                mysql_query("CREATE UNIQUE INDEX {$index["name"]} ON {$tab} ({$index["col"]})");
                MysqlError();
            }
            else
            {
                mysql_query("CREATE INDEX {$index["name"]} ON {$tab} ({$index["col"]})");
                MysqlError();
            }
    
            echo "Created index {$index["name"]} on {$tab}. Unique: {$index["unique"]}\n";
        }
    
        // set default collate
        mysql_query("ALTER TABLE {$tab}  DEFAULT CHARACTER SET {$target_charset} COLLATE {$target_collate}");
    }
    
    // set database charset
    mysql_query("ALTER DATABASE {$db} DEFAULT CHARACTER SET {$target_charset} COLLATE {$target_collate}");
    
    mysql_close($conn);
    echo "</pre>";
    
    ?>
    
    0 讨论(0)
  • 2020-12-04 06:49

    I think it's easy to do this in two steps runin PhpMyAdmin.
    Step 1:

    SELECT CONCAT('ALTER TABLE `', t.`TABLE_SCHEMA`, '`.`', t.`TABLE_NAME`,
     '` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;') as stmt 
    FROM `information_schema`.`TABLES` t
    WHERE 1
    AND t.`TABLE_SCHEMA` = 'database_name'
    ORDER BY 1
    

    Step 2:
    This query will output a list of queries, one for each table. You have to copy the list of queries, and paste them to the command line or to PhpMyAdmin's SQL tab for the changes to be made.

    0 讨论(0)
  • 2020-12-04 06:52

    In scripts above all tables selected for convertation (with SHOW TABLES), but a more convenient and portable way to check the table collation before converting a table. This query does it:

    SELECT table_name
         , table_collation 
    FROM information_schema.tables
    
    0 讨论(0)
  • 2020-12-04 06:53

    I updated nlaq's answer to work with PHP7 and to correctly handle multicolumn indices, binary collated data (e.g. latin1_bin), etc., and cleaned up the code a bit. This is the only code I found/tried that successfully migrated my database from latin1 to utf8.

    <?php
    
    /////////// BEGIN CONFIG ////////////////////
    
    $username = "";
    $password = "";
    $db = "";
    $host = "";
    
    $target_charset = "utf8";
    $target_collation = "utf8_unicode_ci";
    $target_bin_collation = "utf8_bin";
    
    ///////////  END CONFIG  ////////////////////
    
    function MySQLSafeQuery($conn, $query) {
        $res = mysqli_query($conn, $query);
        if (mysqli_errno($conn)) {
            echo "<b>Mysql Error: " . mysqli_error($conn) . "</b>\n";
            echo "<span>This query caused the above error: <i>" . $query . "</i></span>\n";
        }
        return $res;
    }
    
    function binary_typename($type) {
        $mysql_type_to_binary_type_map = array(
            "VARCHAR" => "VARBINARY",
            "CHAR" => "BINARY(1)",
            "TINYTEXT" => "TINYBLOB",
            "MEDIUMTEXT" => "MEDIUMBLOB",
            "LONGTEXT" => "LONGBLOB",
            "TEXT" => "BLOB"
        );
    
        $typename = "";
        if (preg_match("/^varchar\((\d+)\)$/i", $type, $mat))
            $typename = $mysql_type_to_binary_type_map["VARCHAR"] . "(" . (2*$mat[1]) . ")";
        else if (!strcasecmp($type, "CHAR"))
            $typename = $mysql_type_to_binary_type_map["CHAR"] . "(1)";
        else if (array_key_exists(strtoupper($type), $mysql_type_to_binary_type_map))
            $typename = $mysql_type_to_binary_type_map[strtoupper($type)];
        return $typename;
    }
    
    echo "<pre>";
    
    // Connect to database
    $conn = mysqli_connect($host, $username, $password);
    mysqli_select_db($conn, $db);
    
    // Get list of tables
    $tabs = array();
    $query = "SHOW TABLES";
    $res = MySQLSafeQuery($conn, $query);
    while (($row = mysqli_fetch_row($res)) != null)
        $tabs[] = $row[0];
    
    // Now fix tables
    foreach ($tabs as $tab) {
        $res = MySQLSafeQuery($conn, "SHOW INDEX FROM `{$tab}`");
        $indicies = array();
    
        while (($row = mysqli_fetch_array($res)) != null) {
            if ($row[2] != "PRIMARY") {
                $append = true;
                foreach ($indicies as $index) {
                    if ($index["name"] == $row[2]) {
                        $index["col"][] = $row[4];
                        $append = false;
                    }
                }
                if($append)
                    $indicies[] = array("name" => $row[2], "unique" => !($row[1] == "1"), "col" => array($row[4]));
            }
        }
    
        foreach ($indicies as $index) {
            MySQLSafeQuery($conn, "ALTER TABLE `{$tab}` DROP INDEX `{$index["name"]}`");
            echo "Dropped index {$index["name"]}. Unique: {$index["unique"]}\n";
        }
    
        $res = MySQLSafeQuery($conn, "SHOW FULL COLUMNS FROM `{$tab}`");
        while (($row = mysqli_fetch_array($res)) != null) {
            $name = $row[0];
            $type = $row[1];
            $current_collation = $row[2];
            $target_collation_bak = $target_collation;
            if(!strcasecmp($current_collation, "latin1_bin"))
                $target_collation = $target_bin_collation;
            $set = false;
            $binary_typename = binary_typename($type);
            if ($binary_typename != "") {
                MySQLSafeQuery($conn, "ALTER TABLE `{$tab}` MODIFY `{$name}` {$binary_typename}");
                MySQLSafeQuery($conn, "ALTER TABLE `{$tab}` MODIFY `{$name}` {$type} CHARACTER SET '{$target_charset}' COLLATE '{$target_collation}'");
                $set = true;
                echo "Altered field {$name} on {$tab} from type {$type}\n";
            }
            $target_collation = $target_collation_bak;
        }
    
        // Rebuild indicies
        foreach ($indicies as $index) {
             // Handle multi-column indices
             $joined_col_str = "";
             foreach ($index["col"] as $col)
                 $joined_col_str = $joined_col_str . ", `" . $col . "`";
             $joined_col_str = substr($joined_col_str, 2);
    
             $query = "";
             if ($index["unique"])
                 $query = "CREATE UNIQUE INDEX `{$index["name"]}` ON `{$tab}` ({$joined_col_str})";
             else
                 $query = "CREATE INDEX `{$index["name"]}` ON `{$tab}` ({$joined_col_str})";
             MySQLSafeQuery($conn, $query);
    
            echo "Created index {$index["name"]} on {$tab}. Unique: {$index["unique"]}\n";
        }
    
        // Set default character set and collation for table
        MySQLSafeQuery($conn, "ALTER TABLE `{$tab}`  DEFAULT CHARACTER SET '{$target_charset}' COLLATE '{$target_collation}'");
    }
    
    // Set default character set and collation for database
    MySQLSafeQuery($conn, "ALTER DATABASE `{$db}` DEFAULT CHARACTER SET '{$target_charset}' COLLATE '{$target_collation}'");
    
    mysqli_close($conn);
    echo "</pre>";
    
    ?>
    
    0 讨论(0)
提交回复
热议问题