Из dbf в MySQL и обратно. Производственная драма с прологом, но без эпилога

Евгений Чайкин aka StraNNik

2008-12-24

На новой работе большая часть времени уходит на работу с базой данных. База большая, хаотичная и в целом — внушает ужас. Увы, отнюдь не объёмами, но скорее качеством данных.

Дабы вы поняли всю прелесть и пикантность ситуации, добавлю — база мало того, что неиндексированная, так ещё и с отсутствующим ключевым полем.

Хранится всё это Щастье в dbf. Разного рода вспомогательные базы, базочки, базюшечки и просто обновления — в том же dbf.

Поскольку с dbf я дружу слабо, а с MySQL — средне, было принято решение — "загнать эту ... базу в мускуль, а там видно будет". Как это ни смешно, решение оказалось правильным. С другой стороны, есть подозрение, что правильным было бы любое решение, потому что один из принятых в этой конторе методов обработки информации заключался в "распечатать всё, а потом силами нескольких человек найти нужное в распечатках, а потом вручную вбить обратно".

Заканчивая лирическое отступление, расскажу — как я загоняю dbf-ки в MySQL и потом выковыриваю их обратно.

aptitude search навёл меня на утилиту dbf2mysql

Я не буду пересказывать здесь ман, вскользь отмечу только, что ключ "перевести имена полей в нижний регистр" работает, а вот "перевести значения полей в нижний/верхний регистр" — не работает.

У утилиты этой есть один, но существенный на мой взгляд недостаток. Автор её и слыхом не слыхивал о существовании кодировок, отличных от latin1. В результате имеем таблицу в кодировке latin1, набитую данными в кодировке CP866.

Но нас таким не напугаешь. Возможно кто-то применит секретное заклинание alter table, сменит тип данных с текстового на blob, выправит кодировку, а потом сменит тип данных обратно, но это не мой путь. Этих самых полей у меня — неисчислимое множество (ну вру. Исчислимое, что уж там. Но всё равно — много).

Выручает старый-добрый mysqldump с принудительным выставлением кодировки в latin1.

Обрабатываем полученный файл напильником iconv'ом, перегоняя из CP866 в юникод, меняем в нём кодировку с latin1 на utf8, drop-аем таблицу, загоняем дамп обратно в мускуль — et voila!

Дабы работать было удобнее, добавляю отдельное поле типа int, заполняю его автоинкрементом и индексирую по нему. Иначе — совсем грустно. Но это уже сугубо моя локальная специфика.

Самое интересное начинается, когда приходит время загнать данные из MySQL обратно в dbf. Вот тут уже — чистое шаманство. Вышеупомянутая утилита dbf2mysql имеет и оборотную сторону mysql2dbf. И даже вроде как работает, но... Но о кодировках, отличных от latin1 можно забыть.

Но настоящего джедая не напугать такими мелочами. Берём, делаем выборку из MySQL, посредством INTO OUTFILE формируем csv, открываем готовую dbf-ку с нужной структурой редактором dbf от pssoft.ru (спасибо автору), удаляем все данные и импортируем туда данные из csv. Одно уточнение — данные в csv должны быть в CP1251, но это такие мелочи...

От счастливого финала нас отделяет только N-ное количество щелчков мышью. Каждое поле dbf-а нужно сопоставить полю csv-шки. Автоматизировать — никак. У меня таких полей — 70.

Клик-клик-клик...
Клик-клик-клик...
Клик-клик-клик...

ДААА! Экспорт в dbf и вожделенный файлик на диске, будь он неладен.

К чему всё это? К тому, что если кто знает способ лучше — я просто изнемогаю от желания его узнать. А пока тихо радуюсь, что результаты обработки в 90% случаев нужны не в dbf, а в xls, получить который из csv — дело пары минут.

Занавес.