2011-05-06 24 views
124

Nuestro programador anterior estableció la intercalación incorrecta en una tabla (Mysql). Lo configuró con colación latina, cuando debería ser UTF8, y ahora tengo problemas. Todos los registros con caracteres chinos y japoneses se convierten en ??? personaje.¿Cómo cambiar la intercalación predeterminada de una base de datos?

¿Es posible cambiar la intercalación y recuperar el detalle del personaje?

+0

posible duplicado de [MySql alter table Collation] (http://stackoverflow.com/questions/742205/mysql-alter-table-collation) – kenorb

Respuesta

285

cambio de base de datos de colación:

ALTER DATABASE <database_name> CHARACTER SET utf8 COLLATE utf8_unicode_ci; 

cambio tabla de clasificación por:

ALTER TABLE <table_name> CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci; 

cambio columna de colación:

ALTER TABLE <table_name> MODIFY <column_name> VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci; 

Más información:

+4

Tenga cuidado 'CHARACTER SET utf8' se ajustará a' utf8_general_ci' pero también puede defina la intercalación como esta 'ALTER DATABASE CHARACTER SET utf8 COLLATE utf8_unicode_ci; 'si es necesario – KCD

+0

... y le recomiendo que lo pruebe' create table testit (a varchar (1)); mostrar create table testit \ G drop table testit; ' – KCD

+0

Gracias @Timo Huovinen, los comandos funcionan como encanto: D –

3

here describe bien el proceso. Sin embargo, algunos de los personajes que no encajaban en el espacio latino se han ido para siempre. UTF-8 es un SUPERSET de latin1. No al revés. La mayoría caben en el espacio de un solo byte, pero ninguna los indefinidos no será (marque una lista de latin1 - no se definen los 256 caracteres, dependiendo de la definición latin1 de MySQL)

14

Mira que en MySQL, el conjunto utf8 carácter es sólo un subconjunto del conjunto de caracteres UTF-8 reales. Para guardar un byte de almacenamiento, el equipo Mysql decidió almacenar solo tres bytes de caracteres UTF8 en lugar de los cuatro bytes completos. Eso significa que algunos idiomas asiáticos y emojis no son totalmente compatibles. Para asegurarse de que puede almacenar todos los caracteres UTF8, use el tipo de datos utf8mb4 y utf8mb4_bin o utf8mb4_general_ci en Mysql.

+1

Esto fue muy útil :) – Raz0rwire

+1

Lea también http://stackoverflow.com/questions/367711/what-is-the-best-collation-to-use-for-mysql-with-php?rq=1 –

29

Heres cómo cambiar todas las bases de datos/tablas/columnas. Ejecute estas consultas y generarán todas las consultas posteriores necesarias para convertir su esquema completo a utf8. ¡Espero que esto ayude!

- Cambio de intercalación base de datos predeterminada

SELECT DISTINCT concat('ALTER DATABASE `', TABLE_SCHEMA, '` CHARACTER SET utf8 COLLATE utf8_unicode_ci;') 
from information_schema.tables 
where TABLE_SCHEMA like 'database_name'; 

- Cambio TABLA Clasificación/Juego de caracteres

SELECT concat('ALTER TABLE `', TABLE_SCHEMA, '`.`', table_name, '` CHARACTER SET utf8 COLLATE utf8_unicode_ci;') 
from information_schema.tables 
where TABLE_SCHEMA like 'database_name'; 

- cambie la columna Clasificación/Juego de caracteres

SELECT concat('ALTER TABLE `', t1.TABLE_SCHEMA, '`.`', t1.table_name, '` MODIFY `', t1.column_name, '` ', t1.data_type , '(' , t1.CHARACTER_MAXIMUM_LENGTH , ')' , ' CHARACTER SET utf8 COLLATE utf8_unicode_ci;') 
from information_schema.columns t1 
where t1.TABLE_SCHEMA like 'database_name' and t1.COLLATION_NAME = 'old_charset_name'; 
+0

Bueno. ! Es alrededor de una hora que estoy tratando de resolver el mismo problema. Utilizo estos 3 comandos, y vi que el juego de caracteres había cambiado. Pero el problema principal sigue siendo para mí. Si escribí directamente en la base de datos, todo se muestra bien en mi navegador. Pero si agregué algún contenido del formulario del sitio web, el resultado en la base de datos es solo ??????. ¿Hay algo que deba considerar? Mi aplicación web es una aplicación .NET MVC. – Tchaps

+0

Guardando en consultas útiles para proyectos futuros. – Manatax

+0

He sugerido algunas ediciones debido a que estas consultas automáticas aún no eran seguras de usar. Todavía hay un problema con el CHARACTER_MAXIMUM_LENGTH: el original puede ser demasiado alto cuando cambia de, por ejemplo, latin1_swedish_ci a utf8_unicode_ci. – Ruben

4

Agregando a lo David Whittaker publicó, he creado una consulta que genera la tabla completa y las columnas alteran la afirmación de que w convertiré cada tabla. Puede ser una buena idea ejecutar

SET SESSION group_concat_max_len = 100000;

primero para asegurarse de que su grupo concat no sobrepase el límite muy pequeño como se ve here.

 SELECT a.table_name, concat('ALTER TABLE ', a.table_schema, '.', a.table_name, ' DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci, ', 
     group_concat(distinct(concat(' MODIFY ', column_name, ' ', column_type, ' CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ', if (is_nullable = 'NO', ' NOT', ''), ' NULL ', 
     if (COLUMN_DEFAULT is not null, CONCAT(' DEFAULT \'', COLUMN_DEFAULT, '\''), ''), if (EXTRA != '', CONCAT(' ', EXTRA), '')))), ';') as alter_statement 
    FROM information_schema.columns a 
    INNER JOIN INFORMATION_SCHEMA.TABLES b ON a.TABLE_CATALOG = b.TABLE_CATALOG 
     AND a.TABLE_SCHEMA = b.TABLE_SCHEMA 
     AND a.TABLE_NAME = b.TABLE_NAME 
     AND b.table_type != 'view' 
    WHERE a.table_schema = ? and (collation_name = 'latin1_swedish_ci' or collation_name = 'utf8mb4_general_ci') 
    GROUP BY table_name; 

A diferencia aquí entre la respuesta anterior es que fue el uso de UTF-8 en lugar de ut8mb4 y el uso de t1.data_type con t1.CHARACTER_MAXIMUM_LENGTH no funcionó para enumeraciones. Además, mi consulta excluye las vistas, ya que deberán modificarse por separado.

Simplemente utilicé una secuencia de comandos de Perl para devolver todas estas alteraciones como una matriz y las repetí, corrigió las columnas que eran demasiado largas (generalmente eran varchar (256) cuando los datos generalmente solo tenían 20 caracteres, de modo que fue una solución fácil).

Encontré que algunos datos estaban dañados al alterar desde latin1 -> utf8mb4. Parecía que los caracteres latin1 codificados en utf8 en las columnas serían ridículos en la conversión. Simplemente mantuve los datos de las columnas que sabía que iban a ser un problema en la memoria de antes y después del alter y los comparé y generé declaraciones de actualización para corregir los datos.

Cuestiones relacionadas