Быстрый способ преобразования charset базы данных MySQL
Недавно мне пришлось столкнуться с задачей перевода базы данных из одного charset в другой. Исходная база была в iso-8859-1, предстояло перевести её в utf-8. Задача усложнялась тем, что в исходной базе присутствовали символы из других языков (русский, испанский и, возможно, китайский).
Погуляв по Интернету и поискав в Google, я нашёл несколько решений.
- Способ, который мне очень понравился — TIP: Convert latin1 to UTF-8 in MySQL
Вкратце (я немного изменил команды для повышения эффективности работы скрипта):[-]View Code Bashmysqldump -uuser -ppassword --default-character-set=latin1 -n -K --skip-set-charset --skip-create-options --skip-extended-insert --compatible=mysql40 --max_allowed_packet=64K dbname > latin_dump.sql
iconv -f ISO-8859-1 -t UTF-8 latin_dump.sql > utf8_dump.sql
mysql --max_allowed_packet=1M -uuser -ppassword --default-character-set=utf8 database_utf8 < utf8_dump.sql
rm -f *.sqlИдея состоит в том, что мы просто создаём дамп исходной базы, при этом указывая mysqldump, что никаких деклараций
CHARSET
и иже с ними указывать не надо, затем скармливаем полученный дамп iconv, который преобразует весь latin1 в utf8, а затем преобразованный файл отдаём mysql (при этом указываем, чтоcharset
по умолчанию у нас utf8).
Из неприятного: не сработало Как оказалось, из-за того, что cPanel создал базу (которая database_utf8) сDEFAULT CHARSET latin1
. К счастью, лечится просто:[-]View Code MySQLALTER DATABASE `database_utf8` CHARACTER SET 'utf8';
ALTER DATABASE `database_utf8` COLLATE 'utf8_general_ci'; - Экзотика (ссылку, к сожалению, потерял): идея состоит в том, что каждый столбец (CHAR, VARCHAR, TEXT etc) преобразуется сначала в BLOB (при этом меняется только тип столбца и ничего более), а затем BLOB преобразуется в исходный тип, но уже с новым charset. Я как представлю себе, сколько там менять…
- Супер экзотика: Turning MySQL data in latin1 to utf8 utf-8. Без комментариев Видимо, человеку очень надо было преобразовать базу
И на закуску самый простой метод:
ALTER TABLE `table_name` CONVERT TO CHARACTER SET 'utf8';
Ибо как сказано в официальной документации:
If you want to change the table default character set and all character columns (CHAR, VARCHAR, TEXT) to a new character set, use a statement like this:ALTER TABLE tbl_name CONVERT TO CHARACTER SET charset_name;For a column that has a data type of VARCHAR or one of the TEXT types, CONVERT TO CHARACTER SET will change the data type as necessary to ensure that the new column is long enough to store as many characters as the original column. For example, a TEXT column has two length bytes, which store the byte-length of values in the column, up to a maximum of 65,535. For a latin1 TEXT column, each character requires a single byte, so the column can store up to 65,535 characters. If the column is converted to utf8, each character might require up to 3 bytes, for a maximum possible length of 3 × 65,535 = 196,605 bytes. That length will not fit in a TEXT column's length bytes, so MySQL will convert the data type to MEDIUMTEXT, which is the smallest string type for which the length bytes can record a value of 196,605. Similarly, a VARCHAR column might be converted to MEDIUMTEXT.
А мораль такова: если ничего не получается, прочтите, наконец, документацию!
В меморис!
Вот спасибо тебе мил человек. Очень пригодилась твоя “заметка”.
Пиши еще!
Метод из документации будет работать ТОЛЬКО есть данные в базе лежат в той же кодировке, которая объявлена для поля БД.
Старые версии Вордпресса хранят данные в кодировке UTF8 в таблицах с кодировкой latin1 (при обновлении версии даже запрещается добавлять в старый конфиг константы CHARSET и COLLATION, как в новых версиях).
Поэтому простой ALTER .. CONVERT не будет работать (он преобразует двухбайтовые символы в два разных символа). В этом случае сработает только конвертирование с использованием BLOB (2 пункт). При этом данные представляются просто как битовый поток, а потом к ним применяется перекодирование в UTF. А так как они до этого были записаны в UTF, то все закончится удачно. (К стати есть для этого скрипт, который находит текстовые поля и конвертирует их через BLOB в UTF, да и самому такой написать не большая проблема). Iconv по идее тоже не сработает (будет то же самое, как с CONVERT), но я не проверял…
Alex, на самом деле вариантов здесь гораздо больше: всё зависит от charset’а базы, таблицы и соединения.
Моя ошибка в том, что я описывал решение под свой конкретный случай, но не указал, какой из восьми возможных случаев был моим.
Сейчас я пишу подробный обзор на эту тему.
первый способ прокатил, но без шага с iconv и без ALTER DATABASE `database_utf8` COLLATE ‘utf8_general_ci’
в любом случае, спасибо за подсказку.