Как исправить строки с двойным кодированием UTF-8, находящиеся в полях MySQL utf8_general_ci?

Я должен перепроектировать класс, где (между прочим) строки UTF-8 ошибочно закодированы:

$string = iconv('ISO-8859-1', 'UTF-8', $string); : $string = utf8_encode($string); 

Эти ошибочные строки были сохранены в несколько табличных полей по всей базе данных MySQL. Во всех затронутых областях используется collation utf8_general_ci .

Обычно я настраивал небольшой скрипт PHP-патча, зацикливая по затронутым таблицам, выбирая записи, исправляя ошибочные записи, используя utf8_decode() в двойных кодированных полях и ОБНОВЛЯЕТ их.

Поскольку на этот раз у меня много и огромных таблиц, и ошибка затрагивает только немецкие умляуты (äöüßÄÖÜ), мне интересно, есть ли решение умнее / быстрее, чем это.

Являются ли чистые решения MySQL безопасными и рекомендуемыми?

  UPDATE `table` SET `col` = REPLACE(`col`, 'ä', 'ä'); 

Любые другие решения / лучшие практики?

Измените таблицу, чтобы изменить набор символов столбца на Latin-1. Теперь у вас будут одиночные кодированные строки UTF-8, но они сидят в поле, для которого сопоставление должно быть латинским-1.

Затем вы меняете символ символа столбца на UTF-8 через двоичный набор символов – таким образом MySQL не преобразует символы в какой-либо точке.

 ALTER TABLE MyTable MODIFY MyColumn ... CHARACTER SET latin1 ALTER TABLE MyTable MODIFY MyColumn ... CHARACTER SET binary ALTER TABLE MyTable MODIFY MyColumn ... CHARACTER SET utf8 

(это правильный синтаксис iirc; поместите соответствующий тип столбца, где ... is)

Я попробовал опубликованные решения, но моя БД продолжала выплевывать ошибки. В конце концов я наткнулся на следующее решение (на форуме, я думаю, но не могу вспомнить, где):

 UPDATE table_name SET col_name = CONVERT(CONVERT(CONVERT(col_name USING latin1) USING binary) USING utf8); 

и это сработало. Надеюсь, это поможет любому, кто споткнулся здесь от отчаянного поиска в Google, как я.

ПРИМЕЧАНИЕ. Это, конечно, предполагает, что ваши проблемы с двойным кодированным символом исходят из чрезмерно полезного преобразования MySQL с latin1 на utf8, но я считаю, что именно там происходит большинство этих «поврежденных символов». Это в основном делает то же самое преобразование, что и упомянутое выше, на latin1, затем двоичное, затем на utf8 (используя двоичный шаг как способ предотвратить повторное кодирование уже закодированных объектов latin1)

Я нашел следующий подход более простым:

 mysqldump -h DB_HOST -u DB_USER -p --skip-set-charset --default-character-set=latin1 DB_NAME > DB_NAME-dump.sql 

Затем отпустите все таблицы и повторите импорт следующей командой:

 mysql -h DB_HOST -u DB_USER -p --default-character-set=utf8 DB_NAME < DB_NAME-dump.sql 

Совет был найден по этому URL-адресу: http://blog.hno3.org/2010/04/22/fixing-double-encoded-utf-8-data-in-mysql/

MySql – это кодировка, поэтому вы можете конвертировать в SQL. Но для этого случая я, вероятно, предпочел бы просто сценарий на PHP, так как это одноразовая задача.

Имейте в виду, что столбцы в MySql имеют свойство charset. Сопоставление (теоретически) ортогонально к кодировке. Хотя сопоставление utf8_general_ci подразумевает, что кодировка – utf8 , это не заданный. Вы могли бы теоретически смешать настройку utf8 с кодировкой latin1 (и получить мусор в результате).

Если вы решите сделать это в SQL, посмотрите здесь:

http://dev.mysql.com/doc/refman/5.0/en/charset-convert.html

MySQL предоставляет регулярное выражение, но не заменяет regexp, поэтому вам обычно лучше выполнять итерацию по каждой строке в php, преобразовывать по мере необходимости и обновлять строку, если она была изменена.

Создайте дамп с помощью mysqldump, измените объявление кодировки (оно находится в первых командах) и перезагрузите в другую базу данных.

Вы также можете использовать iconv на своем дампе, чтобы перекодировать его.

Вы можете ВЫБРАТЬ ВХОДЬ, ПРОСМОТРИТЕ файл, используя php или iconv, затем LOAD DATA INFILE.