J'ai une solution qui convertira les bases de données et les tables en exécutant quelques commandes. Il convertit également toutes les colonnes du type varchar
, text
, tinytext
, mediumtext
, longtext
, char
. Vous devriez également sauvegarder votre base de données au cas où quelque chose se briserait.
Copiez le code suivant dans un fichier appelé preAlterTables.sql:
use information_schema;
SELECT concat("ALTER DATABASE `",table_schema,"` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;") as _sql
FROM `TABLES` where table_schema like "yourDbName" group by table_schema;
SELECT concat("ALTER TABLE `",table_schema,"`.`",table_name,"` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;") as _sql
FROM `TABLES` where table_schema like "yourDbName" group by table_schema, table_name;
SELECT concat("ALTER TABLE `",table_schema,"`.`",table_name, "` CHANGE `",column_name,"` `",column_name,"` ",data_type,"(",character_maximum_length,") CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci",IF(is_nullable="YES"," NULL"," NOT NULL"),";") as _sql
FROM `COLUMNS` where table_schema like "yourDbName" and data_type in ('varchar','char');
SELECT concat("ALTER TABLE `",table_schema,"`.`",table_name, "` CHANGE `",column_name,"` `",column_name,"` ",data_type," CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci",IF(is_nullable="YES"," NULL"," NOT NULL"),";") as _sql
FROM `COLUMNS` where table_schema like "yourDbName" and data_type in ('text','tinytext','mediumtext','longtext');
Remplacez toutes les occurrences de "yourDbName" par la base de données que vous souhaitez convertir. Puis lancez:
mysql -uroot < preAlterTables.sql | egrep '^ALTER' > alterTables.sql
Cela générera un nouveau fichier alterTables.sql, avec toutes les requêtes dont vous avez besoin pour convertir la base de données. Exécutez la commande suivante pour démarrer la conversion:
mysql -uroot < alterTables.sql
Vous pouvez également l'adapter pour exécuter plusieurs bases de données en modifiant la condition pour la table_schema. Par exemple table_schema like "wiki_%"
, toutes les bases de données portant le préfixe seront converties wiki_
. Pour convertir toutes les bases de données, remplacez la condition par table_type!='SYSTEM VIEW'
.
Un problème qui pourrait survenir. J'ai eu quelques varchar (255) colonnes dans les clés mysql. Cela provoque une erreur:
ERROR 1071 (42000) at line 2229: Specified key was too long; max key length is 767 bytes
Si cela se produit, vous pouvez simplement changer la colonne pour qu'elle soit plus petite, comme varchar (150), et réexécuter la commande.
S'il vous plaît noter : Cette réponse convertit la base de données au utf8mb4_unicode_ci
lieu de utf8mb4_bin
, a demandé à la question. Mais vous pouvez simplement remplacer ceci.
mysql -uroot -pThatrootPassWord < alterTables.sql
fonctionne. Et comme vous l'avez déjà noté, utf8mb4_bin est ce que recommande, notamment, nextcloud.J'ai utilisé le script shell suivant. Il prend le nom de base de données en tant que paramètre et convertit toutes les tables en un autre jeu de caractères et en un autre classement (donné par un autre paramètre ou la valeur par défaut définie dans le script).
la source
J'écrirais un script (en Perl, ou autre) qui utiliserait information_schema (TABLES et COLUMNS) pour parcourir toutes les tables et modifier MODIFY COLUMN sur chaque champ CHAR / VARCHAR / TEXT. Je voudrais rassembler toutes les MODIFY dans un seul ALTER pour chaque table; ce sera plus efficace.
Je pense (mais je ne suis pas sûr) que la suggestion de Raihan ne change que la valeur par défaut pour la table.
la source
Couru dans cette situation; voici l'approche que j'ai utilisée pour convertir ma base de données:
Commencez par éditer
my.cnf
pour rendre la connexion utf8mb4_unicode_ci conforme à la base de données par défaut (entre les applications et MYSQL). Sans cela, les caractères tels que emojis et similaires soumis par vos applications ne parviendront pas à vos tables en octets / encodages droits (sauf si les paramètres DB CNN de votre application spécifient une connexion utf8mb4).Instructions données ici .
Exécutez le SQL suivant (inutile de préparer le SQL pour modifier des colonnes individuelles, les
ALTER TABLE
instructions le feront).Avant d'exécuter ci-dessous, remplacez "DbName" par votre nom de base de données actuel.
Rassemblez et enregistrez la sortie de SQL ci-dessus dans un fichier point SQL et exécutez-le
Si vous obtenez une erreur comme
#1071 - Specified key was too long; max key length is 1000 bytes.
avec le nom de la table problématique, cela signifie que la clé d'index sur une colonne de cette table (qui était supposée être convertie en chaîne de caractères MB4) sera très grosse, de sorte que la colonne Varchar doit être <= 250, de sorte que sa clé d'index sera max 1000 octets. Vérifiez les colonnes sur lesquelles vous avez des index et si l’un d’eux est un varchar> 250 (probablement 255), puisÉtape 1: vérifiez les données dans cette colonne pour vous assurer que la taille maximale de la chaîne dans cette colonne est <= 250.
Exemple de requête:
Etape 2: si max charlength des données de colonne indexée <= 250, remplacez la longueur de la colonne par 250. Si cela n’est pas possible, supprimez l’index de cette colonne.
Étape 3: exécutez à nouveau la requête alter table pour cette table et celle-ci devrait maintenant être convertie en utf8mb4 avec succès.
À votre santé!
la source
J'ai écrit ce guide: http://hanoian.com/content/index.php/24-automate-the-converting-a-mysql-database-character-set-to-utf8mb4
D'après mon travail, j'ai vu qu'ALTER la base de données et les tables ne suffisait pas. Je devais aller dans chaque table et modifier chaque colonne text / mediumtext / varchar.
Heureusement, j'ai pu écrire un script pour détecter les métadonnées des bases de données MySQL, afin qu'il puisse parcourir les tables et les colonnes et les modifier automatiquement.
Index long pour MySQL 5.6:
Vous devez disposer du privilège DBA / SUPER USER: Définissez les paramètres de la base de données:
Les réponses à cette question expliquent comment définir les paramètres ci-dessus: https://stackoverflow.com/questions/35847015/mysql-change-innodb-large-prefix
Bien sûr, dans mon article, il existe des instructions pour le faire aussi.
Pour MySQL version 5.7 ou ultérieure, innodb_large_prefix est activé par défaut et innodb_file_format est également Barracuda par défaut.
la source
Pour les personnes qui pourraient avoir ce problème, la meilleure solution consiste à modifier d'abord les colonnes en un type binaire, en fonction de ce tableau:
Et après cela, modifiez la colonne à son type précédent et avec votre jeu de caractères souhaité.
Par exemple.:
J'ai essayé dans plusieurs tables latin1 et cela a gardé tous les signes diacritiques.
Vous pouvez extraire cette requête pour toutes les colonnes en procédant comme suit:
la source
J'ai fait un script qui le fait plus ou moins automatiquement:
la source