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

后端 未结 16 917
有刺的猬
有刺的猬 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:54

    Another approach using command line, based on @david's without the 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
    

    prettified

      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
    
    0 讨论(0)
  • 2020-12-04 06:54

    Here's an easy way to do this with just phpmyadmin if you don't have command line access or access to edit INFORMATION_SCHEMA.

    First, listen to the advice of many of the other answers here - you can really screw things up here, so make a backup. Now make a backup of your backup. Also this is unlikely to work if your data is encoded differently than what you are changing it to.

    Note that you will need to find the exact names of the offending schema and character encoding that you need to change from before starting.

    1. Export the database as SQL; Make a copy; Open it in a text editor of your choice
    2. Find and Replace the schema first, for example - find: latin1_swedish_ci, replace: utf8_general_ci
    3. Find and Replace the character encodings if you need to, for example - find: latin1, replace: utf8
    4. Create a new test database and upload your new SQL file into phpmyadmin

    This is a super easy way to do it, but again, this will not change the encoding of your data, so it will only work in certain circumstances.

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

    This PHP snippet will change the collation on all tables in a db. (It's taken from 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 />";
        }
    }
    ?> 
    
    0 讨论(0)
  • 2020-12-04 06:57

    Charset and collation are not the same thing. A collation is a set of rules about how to sort strings. A charset is a set of rules about how to represent characters. A collation depends on the charset.

    0 讨论(0)
  • 2020-12-04 07:03

    Thanks @nlaq for the code, that got me started on the below solution.

    I released a WordPress plugin without realising that WordPress doesn't set the collate automatically. So a lot of people using the plugin ended up with latin1_swedish_ci when it should have been utf8_general_ci.

    Here's the code I added to the plugin to detect the latin1_swedish_ci collate and change it to utf8_general_ci.

    Test this code before using it in your own plugin!

    // 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();
    
    0 讨论(0)
  • 2020-12-04 07:03

    A simple (dumb? :) solution, using multi-select feature of Your IDE:

    1. run "SHOW TABLES;" query and copy results column (table names).
    2. multi-select beginnings and add "ALTER TABLE ".
    3. multi-select endings and add " CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;"
    4. run created queries.
    0 讨论(0)
提交回复
热议问题