Вероятно няма уебмастър в България, койото поне веднъж да не е успял да превърне съдържанието
на база данни във въпросителни знаци при експорт / импорт на бакъп дъмп файл с phpmyadmin или през shell.
Ето няколко насоки за mysql енкодинг (информацията е базирана на mysql сървър 4.1+ и PhpMyAdmin 2.6.4+).
Термини
Енкодинг (encoding, character encoding), чарсет (charset, character set)
- Тези понятия описван начина по който се съхраняват символите във вид на някакъв цифров
код. Примери за енкодинги са windows-1251 (в mysql е cp1251), utf-8 (в mysql е utf8), ISO-8859-1 кодировка и т.н.
Колация (collation)
- Това е начина по който се интерпретира енкодинга. За всеки енкодинг
може да има няколко колации и ако сортирате текстовите полета от някоя
mysql таблица с различни колации, вероятно ще се подредят по различен
начин. Една колация може да работи с един енкодинг само. В mysql не е
нужно да задавате изрично колацията. Когато зададете енкодинг cp1251
примерно, mysql ще използва по подразбиране cp1251_general_ci collation
(това важи за таблици, конекции и т.н.).
Първоначално създаване на база данни
При създаване на база данни, в която ще има текст на кирилица, най-добре е да се използва
енкодинг (и колация) cp1251 или utf8 (unicode). Същото важи и за таблиците и полетата вътре.
CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name
[DEFAULT] CHARACTER SET charset_name
| [DEFAULT] COLLATE collation_name
Ако не бъде изрично зададен character set, ще се използва този, който е по подразбиране в съответния mysql сървър.
В момента нашите хостинг сървъри
са настроени за чарсет по подразбиране latin1.
Енкодинга (чарсета) на базата данни в действителност
не служи за нищо друго освен да зададе какъв енкодинг да се ползва за
при създаването на таблиците. Table character set, table collation,
както и енкодинга и колациите за самите текстови полета определят в
какъв вид ще се съхранява текста. Mysql 4.1 и по-новите версии
поддържат възможността да се зададе различен енкодинг и колация за
всяка таблица или поле. Тези настройки можете лесно да променяте с
PhpMyAdmin. Ако сменяте енкодинга на таблица или поле, трябва да се
внимава да не се преминава към енкодинг, който липсват някои от
символите в оригиналния енкодинг. Например няма проблем да смените от
cp1251 към utf8, koi8r или binary. Ако в базата има само латиница и
кирилица, можете да смените от utf8 към cp1251. Ще загубите всичката
кирилица обаче, ако смените от utf8 или cp1251 към latin1 или latin2.
Добро правило е винаги да правите бекъп преди да се заигравате базата
си данни. Друго добро правило е, при смяна на кодировката, да
преминавате през binary (utf8 → binary → cp1251). Дори когато правите
бекъп, има опасност дъмпа да е неизползваем ако примерно базата е
latin1, а данните вътре са на кирилица (по-долу е обяснено какво да
правите в такъв случай), затова най-добрия бекъп е да спрете mysql и да
копирате самите бази в data директорията.
Изпълнение на заявки към база данни с кирилица
Правилно е да изберете един енкодинг за всички компоненти на вашия
сайт. Например, ако изберете windows-1251 (cp1251), трябва или в http
хедъра или с мета таг да укажете това за вашите php, cgi, aspx или
други файлове. Освен това самия файл е ноебходимо да се запази със
съответната кодировка. Например, опцията на Visual Studio (Express
Edition е безплатен от сайта на Майкрософт) 'Save File As' има малка
стрелкичка до бутона Save, където можете да изберете с какъв енкодинг
да е файла. Вероятно вашият любим текстов редактор също поддържа такава
опция. Проверете и настройките на вашия сървър скрипт. Примерно за PHP
- default_charset в php.ini е най-добре да се остави коментирано, но
може и default_charset = "windows-1251". Следващата стъпка е да
настроите вашето приложение и mysql да обменят данни в един и същ
енкодинг. Обикновено причината за въпросителни знаци по вашия сайт е
именно заради факта, че двете си говорят на различни езици. Във
конфигурационния файл на mysql може да бъде зададен енкодинг по
подразбиране посредством character-set-server = cp1251 (default-character-set = cp1251) или init_connect = 'SET NAMES cp1251'.
Вероятно обаче няма да имате възможност да редактирате конфигурацията
на mysql сървъра ако ползвате услугите на хостинг компания. Какво ще
стане ако на сървъра енкодинг по подразбиране е cp1251, а вашата база
данни е с utf8 и вашите php файлове са съответно utf-8? На пръв поглед
нищо няма да стане и ще работи (за съжаление)! Самите данни в базата ще
се съхраняват в напълно грешен вид и проблема ще се появи едва когато
се опитате да преместите базата данни на друг хостинг сървър или се
опитате да я възстановите от backup. Някои от символите няма да могат
вече да се четат ('ш', 'И', ...). Ако сте я докарали до тук, имайте
търпение - в края на тази статия ще намерите разрешение. А за да
избегенте подобни проблеми, винаги изрично уведомявайте mysql какъв
енкодинг да използва по време на всяка конекция (connection):
$link = mysql_connect('host', 'user', 'password');
mysql_query('set names utf8', $link);
По този начин, дори на сървъра character set по подразбиране да е cp1251, данните към и от сървъра за вашето php
приложение ще се обменят в utf8 encoding.
Експорт и импорт на база данни
За експортиране на база данни можете да ползвате phpmyadmin или
mysqldump, които ще генерират тескотов файл (dump), със структурата и
данните на вашата база. При големи бази данни е препоръчително да
ползвате mysqldump (необходим ви е ssh достъп до сървъра). По
подразбиране и двете програми ще генерират дъмп в utf-8 формат
независимо с какъв чарсет е базата. Това е нормално и не е проблем.
Енкодинга на файла е utf-8, но ако в базата таблиците са били с cp1251,
това ще бъде отбелязано в sql кода за създаване на таблицата в самия
дъмп файл.
/*!40101 SET NAMES utf8 */;
CREATE TABLE `mytable` (
`my_id` mediumint(8) unsigned NOT NULL auto_increment,
`my_text` varchar(100) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=cp1251;
Това е дъмп създаден от mysqldump. Файлът е в unicode формат и това е
отбелязано в самото начало. Така при импортиране на този файл след това
mysql ще интерпретира символите правилно. Когато mysql види, че трябва
да създаде таблицата в cp1251 чарсет и колация, той автоматично ще
преведе чарсета от utf към cp1251. PhpMyAdmin ще направи подобен dump,
но за съжаление ще пропусне 'SET NAMES' указанието. Това може да доведе
до проблем, при импорт и е добре да го добавите. Ако не сте сигурни
какъв точно е файловия енкодинг на вашия дъмп, можете да проверите по
следния начин - дъмпа се отваря в Firefox (или друг браузър) и от View
→ Character Encoding се сменя докато кирилицата стане читаема. Запомня
се при какъв чарсет се чете и това се записва в реда /*!40101 SET NAMES utf8 */;.
Не забравяйте, че когато в браузъра е utf-8, трябва в дъмп файла да го запишете utf8, а windows-1251 като cp1251.
Също така може да се ползва опцията за чарсет при ъплоуд в phpmyadmin.
Възстановяване на данни, въведени в mysql с неправилен енкодинг
Когато базата данни е с един енкодинг, а сайта ви работи с друг
енкодинг, на пръв поглед всичко работи ок, но в действителност данните
в базата са объркани и ако решите да направите дъмп има голяма
вероятност да загубите кирилицата. Алгоритъма за оправяне на кашата е
следния (приложимо за mysql 4.1 и нагоре - при по-ниски версии
бекъп-нете самите файлове на базите, направете ъпгрейд):
Приемаме, че в момента базата данни ползва character
set x, а сайта character set y. Също така може да изпълните командата
"mysqladmin variables" за да разберете и какви са стойностите по
подразбиране за character_set_client и character_set_connection. Ако са
различни от тези за базата ви, може да пробвате за x техните стойности.
1. Правим дъмп като задаваме на mysqldump следния
параметър: --default-character-set=x. На този етап може да се провери в
браузър да се отвори дъмп-а и да се види с какъв енкодинг се чете
кирилицата. Ако го четете примерно с utf8, значи в следващата стъпка за
начален encoding ще зададете utf8 (iconv -f utf8 -t utf8 ...)
2. С помощта на iconv (под linux) променяме енкодинг-а на файла, като за начален енкодинг задаваме y,
а за краен задаваме utf8 (при засечка пробвайте опцията -c).
3. Редактираме новополучения файл и заменяме в дефинициите на таблиците DEFAULT CHARSET=x със
DEFAULT CHARSET=y. Също заменяме в началото на дъмпа SET NAMES x със SET NAMES utf8.
4. Импортираме дъмпа обратно в mysql. Ако все още не виждаме кирилица на сайта си, редактираме PHP кода
и добавяме едно query, което да изъплни 'SET NAMES y' веднага след конект-ването към базата.
Ако и вие като мен не можете да разберете нищо без да видите конкретни примери, ето:
Ще разгледаме случая когато базата данни и default connection
(default-character-set = latin1) са с кодировка latin1, а самия сайт
ползва windows-1251.
mysqldump --default-character-set=latin1 my_database > db1.sql
iconv -f cp1251 -t utf8 db1.sql > db2.sql
Ако получите грешка: iconv: illegal input sequence at position ..., добавете опцията -c
iconv -c -f cp1251 -t utf8 db1.sql > db2.sql
perl -pi -e "s/SET NAMES latin1/SET NAMES utf8/" db2.sql
perl -pi -e "s/latin1/cp1251/g" db2.sql
mysql my_database < db2.sql
Ако нямате linux под ръка за стъпка 2, по-долу е описан метод с помощта
на Visual Studio (при голяма база данни ще е много бавно).
Отваряте дъмпа в Firefox (ако е по-голям, чакате да
спре да зарежда и дано имате повече рам). От View → Character Encoding
сменяте на windows-1251 и би трябвало да вдите кирилицата нормално. Не
скролвайте по възможност много надолу, тъй като дългите редове убиват
всеки текстoв редактор. С Ctrl + A селектвате всичко, копирате го и го
paste-вате в Visual Studio. Тъй като сайта ви е настроен за
windows-1251, ще приемем, че желаете да уеднаквите всичко с него. Това
означава, че базата данни и конекцията към нея трябва да станат cp1251.
Заменяте всички latin1 с cp1251, като използвате Replace All, а не едно
по-едно за да не чакате дълго. Заменяте в началото на файла SET NAMES
latin1 със SET NAMES utf8. Давате му Save As, и в появилия се прозорец
кликате на стрелкичката до бутона Save и изберате Unicode (UTF-8
without signature).
Не забравяйте да добавите в php кода след всяка конекция към базата:
$link = mysql_connect('host', 'user', 'password');
mysql_query('set names cp1251', $link);
Друг пример - когато базата данни и default connection (default-character-set = cp1251) са с кодировка cp1251, а
самия сайт ползва utf8.
mysqldump --default-character-set=cp1251 my_database > db1.sql
iconv -f utf8 -t utf8 db1.sql > db2.sql
Ако получите грешка: iconv: illegal input sequence at position ..., добавете опцията -c
iconv -c -f utf8 -t utf8 db1.sql > db2.sql
perl -pi -e "s/cp1251/utf8/g" db2.sql
mysql my_database < db2.sql
happy coding
------
Информацията в този tutorial е валидна само за версии на MySQL Database Server 4.1 +. Ако не сте намерили
разрешение на вашия проблем в статията или имате предложения за подобрения, моля пишете ни и ще се постараем
да я обогатим.
Източник: www.hostbulgaria.com
|