2008-09-19 21 views
55

¿Hay un script SQL o PHP que pueda ejecutar que cambie la intercalación predeterminada en todas las tablas y campos en una base de datos?Una secuencia de comandos para cambiar todas las tablas y campos a la intercalación utf-8-bin en MYSQL

Puedo escribir uno yo mismo, pero creo que esto debería ser algo fácilmente disponible en un sitio como este. Si puedo encontrar uno antes de que alguien publique uno, lo publicaré yo mismo.

+0

[Haga clic aquí para ver el script y siga los pasos] (http://stackoverflow.com/a/37049697/5737771) –

Respuesta

24

¡Cuidado! Si realmente tienes utf almacenado como otra codificación, podrías tener un verdadero lío en tus manos. Copia de seguridad primero. A continuación, probar algunos de los métodos estándar:

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

que he tenido que recurrir a la conversión de todos los campos de texto a binario, luego de vuelta a varchar/texto. Esto me ha salvado el culo.

Tenía datos UTF8, almacenados como latin1. Lo que hice:

Caída de los índices. Convierta los campos a binarios. Convierte a utf8-general ci

Si tienes LAMP, no olvides agregar el comando set NAMES antes de interactuar con el db, y asegúrate de configurar los encabezados de codificación de caracteres.

14

Este fragmento de PHP cambiará la intercalación en todas las tablas en una base de datos. (Se toma desde 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

Después de ejecutarlo en mi db, cuando trato de ver la estructura de cada una de mis tablas, ver: # 126 - Archivo de clave incorrecto para la tabla '/tmp/#sql_321_0.MYI'; intente repararlo – YankeeWhiskey

1

juego de caracteres y la colación no son la misma cosa. Una intercalación es un conjunto de reglas sobre cómo ordenar cadenas. Un juego de caracteres es un conjunto de reglas sobre cómo representar personajes. Una intercalación depende del juego de caracteres.

27

OK, escribí esto teniendo en cuenta lo que se dijo en este hilo. Gracias por la ayuda, y espero que este script ayude a otros. No tengo ninguna garantía para su uso, así que FAVOR DE RESPALDAR antes de ejecutarlo. Es debería trabajar con todas las bases de datos; y funcionó muy bien por mi cuenta.

EDITAR: Se han agregado vars en la parte superior para la cual se ha establecido el juego de caracteres/compilación para convertir. Edit2: Cambia juego de caracteres por defecto las tablas de base de datos y/cotejar

<?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

Yup; Hasta aquí todo bien. Lo he estado aplicando uno por uno a mis bases de datos y hasta ahora no hay pérdida de datos. – nlaq

+4

Atención: Al observar el código fuente, me parece que este script no vuelve a crear índices únicos de varias columnas, simplemente los descarta. – knb

+0

¡Excelente publicación! ¿Alguien ha alterado este script para manejar "índices únicos multicolumna"? Es así, por favor publíqueme o envíeme un correo electrónico a gmail - jjwdesign. Gracias, Jeff – jjwdesign

85

se puede realizar en un solo comando (en lugar de 148 de 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 & 

Tienes que amar a la línea de comandos ... (Es posible que necesite emplear las opciones --user y --password para mysql).

EDIT: para evitar problemas de clave externa, agregó SET foreign_key_checks = 0; y SET foreign_key_checks = 1;

+0

genial, funcionó para mí ... algún problema con las codificaciones de caracteres con valores en los campos, por suerte mi base de datos es pequeña por ahora – arod

+0

@david Funciona muy bien, pero ¿es posible registrar la consulta en línea de comando o simplemente notificar cuando el proceso por lotes termina. Actualmente, cuando ejecuto esto, comienza un proceso en segundo plano y no estoy seguro de cuándo termina. Intenté poner echo dentro de awk, pero nada funciona – RameshVel

+0

Cuando uso este comando, no obtengo ninguna respuesta. El mensaje simplemente "cuelga". No estoy seguro si realmente se ejecutó, correctamente o en absoluto – Marc

39

Creo que es fácil de hacer esto en dos pasos runin PhpMyAdmin.
Paso 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 

Paso 2:
Esta consulta dará salida a una lista de consultas, uno para cada tabla. Debe copiar la lista de consultas y pegarlas en la línea de comando o en la pestaña SQL de PhpMyAdmin para que se realicen los cambios.

+0

por favor proporcione enlaces a sitios en idioma inglés o mejor, proporcione una respuesta completa y ¡solo use enlaces como referencia! – sra

+0

Tenga en cuenta que esta consulta NO realizará ningún cambio en su base de datos. Saldrá una lista de consultas, una para cada tabla. Por lo tanto, debe COPETAR la lista de consultas y pegarlas en la línea de comando o en la pestaña SQL de PHPMyAdmin para que se realicen los cambios. – Costa

+0

¡Funciona perfecto! Gracias, es una forma muy inteligente y astuta de realizar un cambio por lotes de colaciones con solo mysql o phpMyAdmin. Es muy útil en la instalación de redmine, donde la intercalación predeterminada es latin1 en lugar de utf8. – 18augst

3

Una versión más completa de la secuencia de comandos se puede encontrar aquí:

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

favor de dejar cualquier comentario acerca de esta contribución aquí: http://www.zen-cart.com/forum/showthread.php?p=1034214

+0

Gracias Dustin! El script de Zen-Cart (versión) es exactamente lo que estaba buscando. Maneja el índice multicampo/índices únicos correctamente. Impresionante, me ahorra mucho tiempo y esfuerzo. – jjwdesign

1

En los scripts anteriores todas las tablas seleccionadas para convertation (con SHOW TABLES), pero es una forma más conveniente y portátil de verificar la intercalación de tablas antes de convertir una tabla. Esta consulta hace:

SELECT table_name 
    , table_collation 
FROM information_schema.tables 
4

Otro enfoque utilizando la línea de comandos, en base a @ David sin la 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

Debería agregar '--silent' al primer comando' mysql' para evitar tener un error para la primera línea, que es 'Tables_in_xxx'. Además, al evitar los nombres de las tablas se evitará un error en las tablas que usen un nombre reservado (como 'Order'). – Benjamin

0

Usar mi shell personalizado collatedb, que debería funcionar:

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

Ejemplo:

collatedb root 0000 myDatabase utf8_bin 
0

Gracias @nlaq para el código, que me inició en la solución a continuación.

Lancé un plugin de WordPress sin darme cuenta de que WordPress no establece el cotejo automáticamente. Así que mucha gente que usa el complemento terminó con latin1_swedish_ci cuando debería haber sido utf8_general_ci.

Aquí está el código que agregué al complemento para detectar el cotejo latin1_swedish_ci y cambiarlo a utf8_general_ci.

¡Pruebe este código antes de usarlo en su propio complemento!

// 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

Una sencilla solución :) (mudo, utilizando multi-función de selección de su IDE:?

  1. run "VER TABLAS;" columna de consulta y copia de resultados (nombres de tablas).
  2. inicios multiselección y agregue "ALTER TABLE".
  3. terminaciones multiselección y agregue "CONVERTIR AL CONJURTO DE CARACTERES utf8 COLLATE utf8_general_ci;"
  4. ejecutar consultas creadas.
0

Creo que la manera más rápida es con phpmyadmin y algo de jQuery en la consola.

Ir a la estructura de la tabla y cromo abierta/firefox consola del programador (normalmente F12 en el teclado):

  1. ejecuta este código para seleccionar todos los campos con juego de caracteres incorrectos y empezar a modificar:

    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. cuando se carga la página, use este código en la consola para seleccionar la codificación correcta:

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

  4. cambio de juego de caracteres de la tabla en el campo "intercalación" en la "operación" pestaña

Probado en phpmyadmin 4.0 y 4.4, pero creo que el trabajo en todas las versiones 4.x

0

Aquí hay una manera fácil de hacerlo con solo phpmyadmin si no tiene acceso a la línea de comando o acceso para editar INFORMATION_SCHEMA.

Primero, escuche el consejo de muchas de las otras respuestas aquí - realmente puede arruinar las cosas aquí, así que haga una copia de seguridad. Ahora haga una copia de seguridad de su copia de seguridad. Además, es poco probable que esto funcione si sus datos están codificados de manera diferente a lo que lo está cambiando.

Tenga en cuenta que tendrá que encontrar los nombres exactos del esquema ofensivo y la codificación de caracteres que necesita cambiar antes de comenzar.

  1. Exportar la base de datos como SQL; Hacer una copia; Abrirlo en un editor de texto de su elección
  2. Buscar y reemplazar el esquema primero, por ejemplo - encontrar: latin1_swedish_ci, reemplace: utf8_general_ci
  3. Buscar y reemplazar las codificaciones de caracteres si es necesario, por ejemplo - encontrar: latin1, reemplace: utf8
  4. Crear una nueva base de datos de prueba y subir su archivo nuevo SQL en phpMyAdmin

Este es un super fácil forma de hacerlo, pero una vez más, esto no cambiará la codificación de sus datos, por lo que solo funcionará en determinadas circunstancias.

0

Actualicé la respuesta de nlaq para trabajar con PHP7 y para manejar correctamente índices de múltiples columnas, datos intercalados binarios (por ejemplo, latin1_bin), etc., y limpié un poco el código. Este es el único código que encontré/intenté que migró mi base de datos de latin1 a 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

Para usuarios de Windows

Además de @davidwinterbottom respuesta, ventanas los usuarios pueden utilizar el comando a continuación:

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] & 

Reemplazar [base de datos], [usuario] y [Contraseña] con marcadores de posición valores actuales.

Git-bash los usuarios pueden descargar este bash script y ejecutarlo fácilmente.

Cuestiones relacionadas