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

后端 未结 16 1022
有刺的猬
有刺的猬 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 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();
    

提交回复
热议问题