代码之家  ›  专栏  ›  技术社区  ›  nlaq

将MYSQL中的所有表和字段更改为utf-8-bin排序规则的脚本

  •  55
  • nlaq  · 技术社区  · 17 年前

    有没有 SQL PHP 我可以运行的脚本,它将更改数据库中所有表和字段的默认排序规则?

    16 回复  |  直到 11 年前
        1
  •  86
  •   BenMorel Manish Pradhan    12 年前

    只需一个命令即可完成(而不是148个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 &
    

    你必须热爱命令行。。。 --user --password 选择 mysql ).

    SET foreign_key_checks = 0; SET foreign_key_checks = 1;

        2
  •  40
  •   Mateng    12 年前

    我认为在PhpMyAdmin中运行两个步骤很容易做到这一点。
    步骤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
    

    步骤2:

        3
  •  27
  •   Adam Nofsinger imBollaveni    9 年前

    好的,我写这篇文章时考虑到了这篇文章中的内容。谢谢你的帮助,我希望这个脚本能帮助其他人。我对它的使用没有任何保证,所以请在运行它之前备份。信息技术 应该 与所有数据库合作;这对我来说非常有效。

    EDIT2:更改数据库和表的默认字符集/比较

    <?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>";
    
    ?>
    
        4
  •  23
  •   Buzz    17 年前

    小心!如果您实际将utf存储为另一种编码,那么您的手上可能会有一团乱麻。先退后。然后尝试一些标准方法:

    http://www.cesspit.net/drupal/node/898 http://www.hackszine.com/blog/archive/2007/05/mysql_database_migration_latin.html

    我不得不求助于将所有文本字段转换为二进制,然后再转换回varchar/text。这救了我的命。

    将字段转换为二进制。 转换为utf8通用ci

    如果您的指示灯亮起,不要忘记在和db交互之前添加set NAMES命令,并确保设置了字符编码头。

        5
  •  13
  •   Rich Adams    17 年前

    this site .)

    <?php
    // your connection
    mysql_connect("localhost","root","***");
    mysql_select_db("db1");
    
    // convert code
    $res = mysql_query("SHOW TABLES");
    while ($row = mysql_fetch_array($res))
    {
        foreach ($row as $key => $table)
        {
            mysql_query("ALTER TABLE " . $table . " CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci");
            echo $key . " =&gt; " . $table . " CONVERTED<br />";
        }
    }
    ?> 
    
        6
  •  4
  •   RameshVel    13 年前

    另一种使用命令行的方法,基于@david的,没有 awk

    for t in $(mysql --user=root --password=admin  --database=DBNAME -e "show tables";);do echo "Altering" $t;mysql --user=root --password=admin --database=DBNAME -e "ALTER TABLE $t CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;";done
    

      for t in $(mysql --user=root --password=admin  --database=DBNAME -e "show tables";);
        do 
           echo "Altering" $t;
           mysql --user=root --password=admin --database=DBNAME -e "ALTER TABLE $t CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;";
        done
    
        7
  •  2
  •   Dustin    15 年前

    可以在此处找到上述脚本的更完整版本:

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

    请在此处留下有关此贡献的任何反馈: http://www.zen-cart.com/forum/showthread.php?p=1034214

        8
  •  1
  •   troelskn    17 年前

        9
  •  1
  •   Pete Carter    13 年前

    在上面的脚本中,选择要转换的所有表(带 SHOW TABLES ),但这是在转换表之前检查表排序规则的更方便、更便携的方法。此查询执行以下操作:

    SELECT table_name
         , table_collation 
    FROM information_schema.tables
    
        10
  •  0
  •   Abdennour TOUMI    12 年前

    collatedb ,它应该起作用:

    collatedb <username> <password> <database> <collation>
    

    例子:

    collatedb root 0000 myDatabase utf8_bin
    
        11
  •  0
  •   dtbaker    12 年前

    感谢@nlaq提供的代码,这让我开始使用下面的解决方案。

    我发布了一个WordPress插件,但没有意识到WordPress不会自动设置校对。所以很多使用插件的人最终都会 latin1_swedish_ci utf8_general_ci

    下面是我添加到插件中的代码,用于检测 拉丁语和瑞典语 utf8\u概述\u ci

    在您自己的插件中使用此代码之前,请先对其进行测试!

    // list the names of your wordpress plugin database tables (without db prefix)
    $tables_to_check = array(
        'social_message',
        'social_facebook',
        'social_facebook_message',
        'social_facebook_page',
        'social_google',
        'social_google_mesage',
        'social_twitter',
        'social_twitter_message',
    );
    // choose the collate to search for and replace:
    $convert_fields_collate_from = 'latin1_swedish_ci';
    $convert_fields_collate_to = 'utf8_general_ci';
    $convert_tables_character_set_to = 'utf8';
    $show_debug_messages = false;
    global $wpdb;
    $wpdb->show_errors();
    foreach($tables_to_check as $table) {
        $table = $wpdb->prefix . $table;
        $indicies = $wpdb->get_results(  "SHOW INDEX FROM `$table`", ARRAY_A );
        $results = $wpdb->get_results( "SHOW FULL COLUMNS FROM `$table`" , ARRAY_A );
        foreach($results as $result){
            if($show_debug_messages)echo "Checking field ".$result['Field'] ." with collat: ".$result['Collation']."\n";
            if(isset($result['Field']) && $result['Field'] && isset($result['Collation']) && $result['Collation'] == $convert_fields_collate_from){
                if($show_debug_messages)echo "Table: $table - Converting field " .$result['Field'] ." - " .$result['Type']." - from $convert_fields_collate_from to $convert_fields_collate_to \n";
                // found a field to convert. check if there's an index on this field.
                // we have to remove index before converting field to binary.
                $is_there_an_index = false;
                foreach($indicies as $index){
                    if ( isset($index['Column_name']) && $index['Column_name'] == $result['Field']){
                        // there's an index on this column! store it for adding later on.
                        $is_there_an_index = $index;
                        $wpdb->query( $wpdb->prepare( "ALTER TABLE `%s` DROP INDEX %s", $table, $index['Key_name']) );
                        if($show_debug_messages)echo "Dropped index ".$index['Key_name']." before converting field.. \n";
                        break;
                    }
                }
                $set = false;
    
                if ( preg_match( "/^varchar\((\d+)\)$/i", $result['Type'], $mat ) ) {
                    $wpdb->query( "ALTER TABLE `{$table}` MODIFY `{$result['Field']}` VARBINARY({$mat[1]})" );
                    $wpdb->query( "ALTER TABLE `{$table}` MODIFY `{$result['Field']}` VARCHAR({$mat[1]}) CHARACTER SET {$convert_tables_character_set_to} COLLATE {$convert_fields_collate_to}" );
                    $set = true;
                } else if ( !strcasecmp( $result['Type'], "CHAR" ) ) {
                    $wpdb->query( "ALTER TABLE `{$table}` MODIFY `{$result['Field']}` BINARY(1)" );
                    $wpdb->query( "ALTER TABLE `{$table}` MODIFY `{$result['Field']}` VARCHAR(1) CHARACTER SET {$convert_tables_character_set_to} COLLATE {$convert_fields_collate_to}" );
                    $set = true;
                } else if ( !strcasecmp( $result['Type'], "TINYTEXT" ) ) {
                    $wpdb->query( "ALTER TABLE `{$table}` MODIFY `{$result['Field']}` TINYBLOB" );
                    $wpdb->query( "ALTER TABLE `{$table}` MODIFY `{$result['Field']}` TINYTEXT CHARACTER SET {$convert_tables_character_set_to} COLLATE {$convert_fields_collate_to}" );
                    $set = true;
                } else if ( !strcasecmp( $result['Type'], "MEDIUMTEXT" ) ) {
                    $wpdb->query( "ALTER TABLE `{$table}` MODIFY `{$result['Field']}` MEDIUMBLOB" );
                    $wpdb->query( "ALTER TABLE `{$table}` MODIFY `{$result['Field']}` MEDIUMTEXT CHARACTER SET {$convert_tables_character_set_to} COLLATE {$convert_fields_collate_to}" );
                    $set = true;
                } else if ( !strcasecmp( $result['Type'], "LONGTEXT" ) ) {
                    $wpdb->query( "ALTER TABLE `{$table}` MODIFY `{$result['Field']}` LONGBLOB" );
                    $wpdb->query( "ALTER TABLE `{$table}` MODIFY `{$result['Field']}` LONGTEXT CHARACTER SET {$convert_tables_character_set_to} COLLATE {$convert_fields_collate_to}" );
                    $set = true;
                } else if ( !strcasecmp( $result['Type'], "TEXT" ) ) {
                    $wpdb->query( "ALTER TABLE `{$table}` MODIFY `{$result['Field']}` BLOB" );
                    $wpdb->query( "ALTER TABLE `{$table}` MODIFY `{$result['Field']}` TEXT CHARACTER SET {$convert_tables_character_set_to} COLLATE {$convert_fields_collate_to}" );
                    $set = true;
                }else{
                    if($show_debug_messages)echo "Failed to change field - unsupported type: ".$result['Type']."\n";
                }
                if($set){
                    if($show_debug_messages)echo "Altered field success! \n";
                    $wpdb->query( "ALTER TABLE `$table` MODIFY {$result['Field']} COLLATE $convert_fields_collate_to" );
                }
                if($is_there_an_index !== false){
                    // add the index back.
                    if ( !$is_there_an_index["Non_unique"] ) {
                        $wpdb->query( "CREATE UNIQUE INDEX `{$is_there_an_index['Key_name']}` ON `{$table}` ({$is_there_an_index['Column_name']})", $is_there_an_index['Key_name'], $table, $is_there_an_index['Column_name'] );
                    } else {
                        $wpdb->query( "CREATE UNIQUE INDEX `{$is_there_an_index['Key_name']}` ON `{$table}` ({$is_there_an_index['Column_name']})", $is_there_an_index['Key_name'], $table, $is_there_an_index['Column_name'] );
                    }
                }
            }
        }
        // set default collate
        $wpdb->query( "ALTER TABLE `{$table}` DEFAULT CHARACTER SET {$convert_tables_character_set_to} COLLATE {$convert_fields_collate_to}" );
        if($show_debug_messages)echo "Finished with table $table \n";
    }
    $wpdb->hide_errors();
    
        12
  •  0
  •   snp0k    11 年前

    使用IDE的多选功能的简单(哑?:)解决方案:

    1. 多选起始点并添加“ALTER TABLE”。
    2. 多选结尾并添加“转换为字符集utf8校对utf8\U常规\U ci;”
        13
  •  0
  •   squarecandy    10 年前

    如果您没有命令行访问权限或编辑信息的权限,那么这里有一个简单的方法,只需使用phpmyadmin就可以做到这一点。

    请注意,在开始之前,您需要找到需要更改的有问题架构和字符编码的确切名称。

    1. 将数据库导出为SQL;复印;在您选择的文本编辑器中打开它
    2. 首先查找并替换架构,例如-Find: 拉丁语和瑞典语
    3. 如果需要,请查找并替换字符编码,例如-查找: 拉丁语1 ,取代: utf8
    4. 创建新的测试数据库并将新的SQL文件上载到phpmyadmin中

        14
  •  0
  •   marc_s MisterSmith    10 年前

    我认为最快的方法是使用phpmyadmin和控制台上的一些jQuery。

    转到表的结构并打开chrome/firefox开发者控制台(通常键盘上为F12):

    1. var elems = $('dfn'); var lastID = elems.length - 1;
      elems.each(function(i) {
          if ($(this).html() != 'utf8_general_ci') { 
             $('input:checkbox', $('td', $(this).parent().parent()).first()).attr('checked','checked');
          }       
      
          if (i == lastID) {
              $("button[name='submit_mult'][value='change']").click();
          }
      });
      
    2. 加载页面时,在控制台上使用此代码选择正确的编码:

      $("select[name*='field_collation']" ).val('utf8_general_ci');
      

    在phpMyAdmin4.0和4.4上测试,但我认为在所有4.x版本上都可以

        15
  •  0
  •   davewy    9 年前

    我更新了nlaq的答案,以使用PHP7并正确处理多列索引、二进制整理数据(例如。 latin1_bin ),并对代码进行了一些清理。这是我找到/尝试的唯一一个成功将我的数据库从latin1迁移到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>";
    
    ?>
    
        16
  •  0
  •   Lost Koder    9 年前

    windows用户可以使用以下命令:

    mysql.exe --database=[database] -u [user] -p[password] -B -N -e "SHOW TABLES" \
    | awk.exe '{print "SET foreign_key_checks = 0; ALTER TABLE", $1, "CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci; SET foreign_key_checks = 1; "}' \
    | mysql.exe -u [user] -p[password] --database=[database] &
    

    Git bash 用户可以下载这个 bash script