web-dev-qa-db-fra.com

Comment changer le classement par défaut d'une base de données?

Notre programmeur précédent a placé le mauvais classement dans une table (Mysql). Il l'a mis en place avec une collation en latin, alors que ça devrait être UTF8, et maintenant j'ai des problèmes. Tous les disques avec des caractères chinois et japonais se tournent vers ??? personnage.

Est-il possible de changer de classement et de récupérer les détails du personnage?

155
Jeg Bagus

modifier le classement de la base de données:

ALTER DATABASE <database_name> CHARACTER SET utf8 COLLATE utf8_unicode_ci;

classement des tables de changement:

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

changer le classement des colonnes:

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

Plus d'informations:

339
Timo Huovinen

Heres comment changer toutes les bases de données/tables/colonnes. Exécutez ces requêtes et elles généreront toutes les requêtes suivantes nécessaires pour convertir votre schéma entier en utf8. J'espère que cela t'aides!

- Modifier le classement par défaut de DATABASE

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

- Modifier le classement/le jeu de caractères TABLE

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';

- Modifier le classement COLUMN/le jeu de caractères

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';
43
David Whittaker

Attention, dans Mysql, le jeu de caractères utf8 n'est qu'un sous-ensemble du jeu de caractères UTF8 réel. Afin de sauvegarder un octet de stockage, l'équipe de Mysql a décidé de ne stocker que trois octets de caractères UTF8 au lieu des quatre octets complets. Cela signifie que certaines langues asiatiques et emoji ne sont pas totalement pris en charge. Pour vous assurer que vous pouvez stocker tous les caractères UTF8, utilisez le type de données utf8mb4 et utf8mb4_bin ou utf8mb4_general_ci dans Mysql.

23
bluecollarcoder

Ajoutant à ce que David Whittaker a posté, j'ai créé une requête qui génère la table complète et les colonnes modifient l'instruction qui convertira chaque table. Ce peut être une bonne idée de courir

SET SESSION group_concat_max_len = 100000;

d'abord pour vous assurer que votre groupe ne dépasse pas la très petite limite telle que vue ici .

     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;

La différence ici entre la réponse précédente est qu’elle utilisait utf8 au lieu de ut8mb4 et que t1.data_type avec t1.CHARACTER_MAXIMUM_LENGTH ne fonctionnait pas pour les énumérations. De plus, ma requête exclut les vues car celles-ci devront être modifiées séparément.

J'ai simplement utilisé un script Perl pour renvoyer toutes ces modifications sous forme de tableau et les itérer sur celles-ci, en corrigeant les colonnes trop longues (généralement elles étaient varchar (256) alors que les données ne contenaient généralement que 20 caractères, ce qui était une solution facile ).

J'ai trouvé des données corrompues lors de la modification de latin1 -> utf8mb4. Il semblait que les caractères latin1 codés en utf8 soient codés dans la conversion. J'ai simplement stocké les données des colonnes dont je savais qu'elles allaient poser un problème en mémoire avant et après la modification, les ai comparées et généré des instructions de mise à jour pour corriger les données.

6
Jacob Hundley

ici décrit bien le processus. Cependant, certains des personnages qui ne correspondaient pas à l'espace latin ont disparu pour toujours. UTF-8 est un SUPERSET en latin1. Pas l'inverse. La plupart vont tenir dans un seul octet, mais pas les indéfinis (vérifiez la liste de latin1 - tous les 256 caractères ne sont pas définis, cela dépend de la définition de mysql en latin1)

4
MJB