Не сте регистриран! Регистрирайте се БЕЗПЛАТНО, за да използвате услугите на сайта!

   Рубрики
 
 
 
 

 Форуми
» SEO и оптимизация
» Всичко за PHP и Perl
» Всичко за C, C++ и .NET
» Всичко за Java и JSP
» Всичко за SQL и MySQL
» Всичко за XHTML и CSS
» Презентация на сайтове
 Енкодинги в MySql - Как да си прекодирам базата?
  1. Енкодинги в MySql
  2. Как да си прекодирам базата?
Bibi
     
Автор  Bibi (09.12.2007 12:12)  съобщение до автора
Погледнат  4083 пъти  добави към любими
Оценка  добави коментар
Гласове  1  изпрати на приятел
Коментари  (1)  абонирай се за MySQL
    Страница 1 / 2

 



Защо базата има нужда от енкодинг?
Не може ли просто да съхранява байтове и да ни ги подава непроменени, когато ни потрябват?

Би могло. Но тя има амбицията, освен съхраняването на данните, да ни предостави и функции, с които да я караме да ни връща по-сложни резултати. Сортиране, групиране, преобразуване на малки в главни букви, търсене с маска, дати, всякакви неща...

За правилната работа на част от тези функции базата трябва да знае дали байтовете, които сме записали в нея, за нас имат смисъл на стринг, или пък са число, дата или друго.
Примерно за да ни подаде 5-тата буква от даден текст, тя трябва да знае с колко байта се записва 1 буква.
Как ще получи от малко "щ" главно "Щ", ако не знае с кои байтове се изписва то?
Поради разликите в разположението на буквите в различните кодови таблици, тази задача (капитализацията) се решава различно.

За да може да служи еднакво добре и на шведи, и на българи, базата има не едно, а цяла серия от различни поведения: AllCaps_кирилица(), AllCaps_шведица(), AllCaps_патагоница...
И от нас очаква да й кажем кое от тях искаме да ползва, когато напишем AllCaps().
Това ние правим като задаваме енкодинги.
Така възприемам ролята им - като "параметър на стринговите функции".


Кога?

Кога базата прекодира нашите данни и как ги съхранява вътрешно?

Указвайки енкодинга на поле от някоя таблица, ние сигнализираме кои конкретни версии на стринговите функции важат за това поле.
От този момент нататък базата започва да ПРЕКОДИРА байтовете, които й вкарваме, преди да си ги запише в полето.

Тя върши тази промяна ако:

  • има разлика в енкодинга на входните данни и тоя, на полето, вкоето ги слагаме;
  • конвертирането е възможно, т.е. дадената буква може да се запише и в двете кодови таблици.

Сега малко по-подробно:

В MySQL 4.1+, освен енкодинга на полетата, ние трябва да укажем и енкодинг на връзката ни с базата.

Ако кажем, че връзката е "utf8", това означава, че нещата, които й пращаме, са смислени символи в тази кодова таблица.
Това ни задължава от този момент нататък да й подаваме само поредици от байтове, които са валидни в utf8.
Опитаме ли да подадем "грешен" байт, ще получим съобщение, че "полето е прекалено късо за тези данни" или нещо подобно, но истинското съобщение би трябвало да гласи "сега що ме лъжеш?".
Ако пък наистина й подаваме utf8 данни, тя ще ги запише 1:1, стига да са били предназначени за поле, чийто енкодинг също е utf8.
Ако нашите utf8 данни обаче трябва да попаднат в колонка с 1251, базата ще опита да ги конвертира, преди да ги запише.

Грубо казано тя гледа графично какво "ченгелче" е изобразено с този utf8-байт и търси с кой байт същото ченгелче участва в 1251.
Ако го намери - записва намерения байт. Ако не - казва, че "част от данните ще бъдат изгубени" и записва нещо си, което после виждаме като "???".

Така че базата НЕ ПРЕКОДИРА данни само в случаите, или когато колоната е била в някой от binary-типовете (това е тяхното предназначение - имат табелка "не пипай, не прекодирай!"), или когато двата енкодинга са съвпадали.
Прекодирането се случва бързо и почти неусетно.
При тази технология, в една MySQL 5 таблица имаме колони, на всяка от които пише в какъв енкодинг са данните в нея и тази информация й служи за преценката:

  • дали и как да се прекодират новопостъпващите данни;
  • коя версия на стринговите си функции да използва.

Възможността да има различни енкодинги за всяка таблица и дори за всяко нейно поле е особеност на MySQL 4.1+.
Това отсъства в предните версии на тая СУБД, няма го в Оракъл, Access, а вероятно и другаде липсва.

Доколкото ми е известно същото важи и за енкодинга на връзката.
При останалите бази предварително избираме какви данни ще подаваме, и заковаваме завинаги енгодинга на връзката да е същия, като оня, който сме указали за цялата база.

Това я спасява от нуждата да прекодира постъпващите данни.
Подозирам, че причината е в скоростта на прекодирането - по някое време в MySQL са разработили скорострелен начин да го вършат и чак тогава е станало разумно да ни "отвържат ръцете".
Но опреледено е удобно да можеш да смениш енкодинга на сайта си, без да се грижиш да променяш и базата - сменяш само 1 дума за връзката с нея и си готов.
Лично аз се възползвах от това положение в сайт, който получава част от данните си в 1251 (през браузер), а друга част идват в utf8 (през чужд сървис).

Със старата версия на базата ми се налагаше да прекодирам всяко стрингче, преди да й го подам, което обезобрази сорса, а сега само времено в движение сменям енкодинга на връзката и после го връщам на 1251.

Всичко, казано по процеса на вкарване да данни в MySQL5, важи също и за изваждането им.
Клиента (да кажем сайта), обявявайки енкодинга на връзката, също така принуждава базата да му конвертира обратно данните, преди да му ги даде.
Това прави двете системи напълно независими откъм енкодинг.
Клиента вече може да си позволи дори да не знае какви енкодинги имат полетата в таблиците.
Той й казва "давам ти 1251", айде сега ми го върни в "латин1" и изобщо каквото си пожелае, и тя изпълнява.

Обичайните клиенти на нашата база са:

  • сайтът;
  • dump-файлът, който я караме да създаде;
  • dump-файлът, от който я пълним;
  • phpMyAdmin;
  • външни скриптове...

За всеки от тези клиенти е важно да можем да сетваме правилно енкодинг на връзката (и да не забравяме да го правим).
За мен най-трудно се оказва дирижирането на енкодинга на създавания от нея dump.

Ако имаме достъп до базата през конзола, там можем да го зададем в явен вид в командата.
Ако го правим през phpMyAdmin мисля, че също е възможно, но все още не съм успяла да го направя.

Тук накратко може да се каже нещичко и за понятието "Колация".
Тя не е нищо повече от "азбучен ред".
Свързана е с кодовата таблица - вътре в един енкодинг може да има повече от една колации.
Например в латин1 има буква, която се изобразява като "О" с две точки отгоре.

Тя е назад в таблицата, след "Z", но в някои езици се намира на различни места в азбучния ред.
Примерно при шведите трябва да е веднага след обикновеното "O", а при финландците се редяла по-назад.

Колацията показва коя версия на функцията Order() да се ползва.
За щастие, всички езици, ползващи кирилица, имат еднакви азбучни подредби и проблеми с колации няма да имаме често (освен евентуално при македонците - не знам те къде си подреждат буквата j).
Така или иначе смяната на колацията не причинява прекодиране или каквото и да е друго допълнително действие вътре в базата.



  Следваща страница >> 


Ключови думи: mysql encoding прекодирам база данни таблица енкодинг колация charset BLOB dump binary SET NAMES


Още уроци от тази рубрика


 
  • Подобни теми от myLinks
 

 1 посетител чете този урок (0 потребители и 1 гост)  
Активни потребители: ---
   
  

Еmail  
 

Който няма средство за прекодиране, може да си напише php-скрипт, ползвайки тамошната функция iconv(), но цялата работа изглежда бавна и тромава.
Да дипълня че тази функция се подържа от версия 4.0.5 на горе.

Урока е полезен и много добре написан според мен.
Поздрави

  iwanov на 09.12.2007 15:33

 

 
  • Интересно от Софтуер
 



IT-PLACE.NET © 2004 - 2008