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.

Faire un mysqldump, dire par table, de le convertir (native2ascii -verso), remplacer éventuellement un peu de SQL concernant les codages et de recharger la table.
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