Начало arrow Въпроси arrow MySQL енкодинг и колация с кирилица arrow MySQL и база данни с кирилица

MySQL и база данни с кирилица
28 януари 2008
Вероятно няма уебмастър в България, койото поне веднъж да не е успял да превърне съдържанието на база данни във въпросителни знаци при експорт / импорт на бакъп дъмп файл с 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 Smile

------
Информацията в този tutorial е валидна само за версии на MySQL Database Server 4.1 +. Ако не сте намерили разрешение на вашия проблем в статията или имате предложения за подобрения, моля пишете ни и ще се постараем да я обогатим.

 

Източник: www.hostbulgaria.com  

 

ФОРУМ

Анкета

Намерихте ли отговор на своя въпрос?
 

Хостинг

Про Хостинг
Про Хостинг
4.00 лв.
Купи

Риселър Хостинг
Риселър Хостинг
25.00 лв.
Купи

Личен Хостинг
Личен Хостинг
2.00 лв.
Купи

Безплатен Хостинг
Безплатен Хостинг
0.00 лв.
Купи