La conversion de la table MySQL avec incorrectement les données encodées en UTF-8
J'ai un grand ol' MySQL 5.1 base de données, et pour une variété de raisons stupides, j'ai été le stockage, je crois, les caractères UTF8 codé comme LATIN1 en UTF8 table. C'est... étrange. Et je voudrais corriger.
La MySQL - Convertir latin1 caractères en UTF8 table en UTF8 question semble fonctionner -- une colonne à la fois. Mais j'ai 24 tables et des dizaines de colonnes à convertir. Je suis vraiment à la recherche d'une solution qui permet de convertir au moins une table à la fois.
Pour référence, la colonne unique solution qui fonctionne pour moi est:
UPDATE foo SET col1 = CONVERT(CAST(CONVERT(col1 USING latin1) AS binary) USING utf8);
Pour les tables, je peux le faire:
ALTER TABLE foo CONVERT TO CHARACTER SET latin1;
ALTER TABLE foo CONVERT TO CHARACTER SET binary;
ALTER TABLE foo CHARACTER SET utf8 COLLATE utf8_unicode_ci;
ce qui me fait très proche -- toutefois, la CONVERT TO CHARACTER SET binary
étape transforme tous mes colonnes VARCHAR dans VARBINARY et mes colonnes de TEXTE dans des Gouttes d'un seul coup. Je peux aller à travers et de les changer en arrière et tout semble s'être bien... mais je suis de retour dans la "nous allons modifier toutes les colonnes individuellement" monde-dans ce cas, je peut tout aussi bien
J'ai essayé sur 50 variations sur ces instructions SQL, mais je ne peux pas en trouver un qui à la fois les feuilles de mes colonnes dans le caractère des types de données et de code les données correctement.
Des suggestions?
Mise à jour: Décider de juste corriger les colonnes plutôt que d'attendre une base de données ou d'une table-sage solution, je suis venu avec:
#!/usr/bin/env ruby
require 'rubygems'
require 'mysql2'
CONNECT_OPTS = {} # whatever you want
Mysql2::Client.default_query_options.merge!(:as => :array)
conn = Mysql2::Client.new(CONNECT_OPTS)
tables = conn.query("SHOW TABLES").map {|row| row[0] }
# See http://dev.mysql.com/doc/refman/5.0/en/charset-column.html
# One might want to include enum and set columns; I don't have them
TYPES_TO_CONVERT = %w(char varchar text)
tables.each do |table|
puts "converting #{table}"
# Get all the columns and we'll filter for the ones we want
columns = conn.query("DESCRIBE #{table}")
columns_to_convert = columns.find_all {|row|
TYPES_TO_CONVERT.include? row[1].gsub(/\(\d+\)/, '')
}.map {|row| row[0]}
next if columns_to_convert.empty?
query = "UPDATE `#{table}` SET "
query += columns_to_convert.map {|col|
"`#{col}` = convert(cast(convert(`#{col}` using latin1) as binary) using utf8)"
}.join ", "
puts query
conn.query query
end
... qui fait le travail. De manière amusante, cela fonctionne sur ma base de données en 36 secondes, plutôt que de l'instruction ALTER TABLE chemin qui a pris 13 minutes (et le VARBINARY problème) ou la commande mysqldump des solutions qui permettrait de prendre plus de vingt en supposant que je puisse les amener à exécuter.
Je vais encore accepter une réponse si quelqu'un connaît un moyen élégant pour ce faire, pour l'ensemble de la base de données ou d'une table en une seule étape.
Je n'ai pas eu la chance que ce soit d'essayer de convertir le dump des fichiers avec iconv ou native2ascii -- mysqldump est sa propre conversion de caractères, je pense. Je suis sûr que j'ai besoin de convertir le contenu des colonnes. Aussi: c'est un 1,5 GO de vidage de base de données et le dumping et le chargement il prend comme 45 minutes.
Je l'ai porté sous une même taille de la base de données du Latin 1 à UTF-8 par personne table de décharges et aussi le fractionnement de la totalité d'un dump il y a deux ans. Je alsol fait quelques remplacements de texte pour modifier le jeu de caractères. J'ai pris cette solution pour avoir une sauvegarde trop - mais oui, ça a pris du temps.
OriginalL'auteur Nate | 2013-06-11
Vous devez vous connecter pour publier un commentaire.
Cette méthode ci-dessous a l'air vraiment prometteur & mieux encore, belle dans sa simplicité. L'idée est que vous le dump l'ensemble de votre base de données comme latin1, & puis de l'importer ré-encodées en utf-8.
À l'exportation:
D'importation:
Je ne vais pas prendre le crédit pour cette solution, il est complètement à partir de Gareth Prix du blog. Il a travaillé pour tout le monde qui lui a laissé un commentaire à ce jour: "Wow homme que vous venez de m'a sauvé la vie. Je n'ai pas passé 2 heures sur ce projet, mais 2 jours" a attiré mon attention.
Mise à jour #1: Ressemble Gareth n'était pas la première à la découverte de cette.
Mise à jour #2: j'ai juste essayé ce & il a fonctionné à merveille pour mon UTF8-stockées sur-comme-latin1 base de données. Assurez-vous simplement de basculer le jeu de caractères par défaut sur votre base de données en utf8 avant l'importation, sinon vous vous retrouverez avec de la plaine des points d'interrogation à où les caractères spéciaux ont été. Bien sûr, cela peut avoir beaucoup d'autres ramifications donc, comme le test d'enfer en premier.
Et si vous avez des tables qui ne sont pas définies sur le schéma par défaut:
(même idée si vous avez n'importe quelle colonne-jeux de caractères spécifique de paramètres, vous devrez faire un ALTER TABLE [table] MODIFIER la COLONNE [paramètres] sans spécifier le JEU de CARACTÈRES de sorte qu'il va revenir à la table par défaut)
Nous avons couru sur nos apparemment-pas-que-grosse base de données (plusieurs dizaines de millions d'enregistrements, de plusieurs GO sous-évaluées) & il a fait correct.. a fallu un certain temps mais les minutes, pas heures.
OriginalL'auteur Wick