Sortiranje po azbuci (azbuka i mysql)
Као земља са два равноправна писма нисмо баш “стандардни” разним произвођачима програмских пакета са пуном подршком за наш, Српски, језик. Поред “смећа у бази”, врло чест проблем везан за карактер сетове у MySQL-у и Српски језик је
- Сортирање – проблем са сортирањем је прилично смарајући пошто ако имамо садржај писан и латиницом и ћирилицом и пробамо да га сортирамо, прво ће бити сортиран латинични текст по абецеди а затим ће бити ћирилични текст по азбуци, смор, знам
- Поређење – проблем са поређењем је још већи, ако имамо садржај који меша ћирилицу и латиницу (на пример форум где су неки постови латинични а неки ћирилични) претрага тог садржаја ће враћати половичне резултате пошто “иницијализација” и “inicijalizacija” неће бити препознати као иста реч. Многи то решеавају тако што бране да садржај буде на више писама те конвертују сваки текст у једно писмо (најчешће у латиницу пошто је конверзија из ћирилице у латиницу једнозначна и једноставна док обрнуто не бажи).
MySQL а и остали РДБМС који имају потпуну подршку за карактер сетове подржава колације. Колација је сет правила који дефинише како се неки карактер сет понаша у одређеном језику. Ту се дефинише:
- тежина сваког карактера (сортирање)
- једначење карактера (сортирање, поређење)
- контракције (њ==nj na primer)
- експанзије (MySQL их тренутно не подржава)
- …
MySQL долази уз брдо колација за UTF8 карактер сет али ниједна од тих колација не ради посао за Српски језик. На срећу, MySQL дозвољава кориснику да дода своју колацију без рекомпајлирања самог сервера. Екстерне колације се налазе у character_sets_dir директоријуму.
Да би сте додали Српску колацију у MySQL потребно је да у Index.xml фајл у character_sets_dir директоријуму
mysql> show variables like 'character_sets_dir'; +--------------------+-----------------------------------------------------------+ | Variable_name | Value | +--------------------+-----------------------------------------------------------+ | character_sets_dir | /usr/local/mysql-5.5.5-m3-linux2.6-x86_64/share/charsets/ | +--------------------+-----------------------------------------------------------+
у секцији UTF8 додате нову колацију, дакле испод:
<charset name="utf8">
<family>Unicode</family>
<description>UTF-8 Unicode</description>
<alias>utf-8</alias>
<collation name="utf8_general_ci" id="33">
<flag>primary</flag>
<flag>compiled</flag>
</collation>
<collation name="utf8_bin" id="83">
<flag>binary</flag>
<flag>compiled</flag>
</collation>
</charset>
додате:
<collation name="utf8_serbian_ci" id="1200">
<rules>
<reset>\u0410</reset>
<i>A</i>
<i>a</i>
<reset>\u0411</reset>
<i>B</i>
<i>b</i>
<reset>\u0412</reset>
<i>V</i>
<i>v</i>
<reset>\u0413</reset>
<i>G</i>
<i>g</i>
<reset>\u0414</reset>
<i>D</i>
<i>d</i>
<reset>\u0402</reset>
<i>\u0110</i>
<i>\u0111</i>
<i>\u0189</i>
<i>Dj</i>
<i>DJ</i>
<i>dj</i>
<reset>\u0415</reset>
<i>E</i>
<i>e</i>
<reset>\u0416</reset>
<i>\u017D</i>
<i>\u017E</i>
<reset>\u0417</reset>
<i>Z</i>
<i>z</i>
<reset>\u0418</reset>
<i>\u0419</i>
<i>\u0439</i>
<i>I</i>
<i>i</i>
<reset>\u0408</reset>
<i>J</i>
<i>j</i>
<reset>\u041A</reset>
<i>K</i>
<i>k</i>
<reset>\u041B</reset>
<i>L</i>
<i>l</i>
<reset>\u0409</reset>
<i>\u01C7</i>
<i>\u01C8</i>
<i>\u01C9</i>
<i>Lj</i>
<i>LJ</i>
<i>lj</i>
<reset>\u041C</reset>
<i>M</i>
<i>m</i>
<reset>\u041D</reset>
<i>N</i>
<i>n</i>
<reset>\u040A</reset>
<i>\u01CA</i>
<i>\u01CB</i>
<i>\u01CC</i>
<i>Nj</i>
<i>NJ</i>
<i>nj</i>
<reset>\u041E</reset>
<i>O</i>
<i>o</i>
<reset>\u041F</reset>
<i>P</i>
<i>p</i>
<reset>\u0420</reset>
<i>R</i>
<i>r</i>
<reset>\u0421</reset>
<i>S</i>
<i>s</i>
<reset>\u0422</reset>
<i>T</i>
<i>t</i>
<reset>\u040B</reset>
<i>\u0106</i>
<i>\u0107</i>
<reset>\u0423</reset>
<i>U</i>
<i>u</i>
<reset>\u0424</reset>
<i>F</i>
<i>f</i>
<reset>\u0425</reset>
<i>H</i>
<i>h</i>
<reset>\u0426</reset>
<i>C</i>
<i>c</i>
<reset>\u0427</reset>
<i>\u010C</i>
<i>\u010D</i>
<reset>\u040F</reset>
<i>\u045F</i>
<i>\u01C4</i>
<i>\u01C5</i>
<i>\u01C6</i>
<i>Dz</i>
<i>DZ</i>
<i>dz</i>
<reset>\u0428</reset>
<i>\u0448</i>
<i>\u0160</i>
<i>\u0161</i>
</rules>
</collation>
рестартујте MySQL сервер и воила, имате нову колацију:
mysql> show collation like '%serbian%'; +-----------------+---------+------+---------+----------+---------+ | Collation | Charset | Id | Default | Compiled | Sortlen | +-----------------+---------+------+---------+----------+---------+ | utf8_serbian_ci | utf8 | 1200 | | | 8 | +-----------------+---------+------+---------+----------+---------+ 1 row in set (0.00 sec) mysql> select 'latinica' = 'латиница'; +---------------------------------+ | 'latinica' = 'латиница' | +---------------------------------+ | 0 | +---------------------------------+ 1 row in set (0.00 sec) mysql> select _utf8 'latinica' collate utf8_serbian_ci = _utf8 'латиница' collate utf8_serbian_ci; +----------------------------------------------------------------------------------------------+ | _utf8 'latinica' collate utf8_serbian_ci = _utf8 'латиница' collate utf8_serbian_ci | +----------------------------------------------------------------------------------------------+ | 1 | +----------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)



29 Responses to “Sortiranje po azbuci (azbuka i mysql)”
Bogdan Kecman - July 23, 2010
Vezano za kontrakcije, trenutno je napravljeno da su
ђ, đ i dj isti karakter (dj je kontrakcija)
љ, lj i lj isti karakter (lj je kontrakcija)
њ, nj i nj isti karakter (nj je kontrakcija)
џ i dz su isti karakter (dz je kontrakcija)
ovde postoji problem sa џ pošto bi trebala da postoji i kontrakcija dž ali trenutno MySQL ne podržava kontrakciju između 7bitnog i UTF8 karaktera. Ovaj limit je ukljonjen u MySQL 5.6.x ali dotični je tek celosia stablo tako da neće još neko vreme biti blizu GA.
Иван Бишевац - July 23, 2010
Извињавам се ако идем даље од теме али хтео бих да нагласим да има једна нетачна ствар коју сте написали на почетку текста а то је “Као земља са два равноправна писма..”
Ми нисмо земља са два равноправна писма. Имамо само једно писмо и то је ћирилица. Латиница није наше званично писмо већ хрватско. То се може наћи у уставу Србије и Хрватске.
Још једном се извињавам за скретање са теме.
Иначе леп и једноставан текст. Хвала ти још једном Богдане зато што своје слободно време користиш да помогнеш људима.
Поздрав.
Bogdan Kecman - July 23, 2010
Stvarno ?!
Ja sam se zadnji put bavio “pismima” kada sam organizovao sa par drugara prevodjenje open office-a i tada je bilo (~2000. – 2001.) i tada su mi gospoda iz akademije nauka i iz vukove zaduzbine ispricali kako su “dva ravnopravna pisma” i objasnili zasto je to lose i ispricali gomilu problema koje zemlja ima zbog te odluke. Nemam pojma kada je to promenjeno, ali ako jeste – super, hvala za informaciju!
Inace, sama cirilica funkcionise ok, bez ikakvih promena, utf8_general_ci sortira i poredi cirilicu pravilno, tako da ako latinica vise nije “nase” pismo onda default kolacija “radi posao”…
momsab - July 23, 2010
добар чланак, по обичају
што се примедбе о писмима тиче, ћирилица и латиница су равноравна писма при чему прво има предност (обавезно је за званична документа државна, нпр)
иначе, има неких теорија да је латиница старија од ћирилице (причам за српски језик, не уопштено)
Bogdan Kecman - July 23, 2010
nije da je wikipedija uvek “siguran izvor” ali:
Sve u svemu, nisam pravnik da umem da tumacim sve te gluposti koje pisu po tim debelim pravnim knjigama (ili tankim crvenim), nemam potrebu da dokazujem sebi ili drugima da sam veliki Srbin tako sto cu da pisem cirilicom, ne osecam da mi neko nesto uzima/otima … a i ova zemlja takva kakva je mi nije nesto “jasna”, rodio sam se u SFRJ, pa ziveo u SRJ, pa u RJ, pa u SCG pa evo sad u Srbiji .. te “nije budjav kruh nego budjav leba” “doslednosti” mi ne znace previse. Kapiram da nekome ko nije prosao sve to, ili ko je prosao nesto drugo (nesto su mu oteli, odnegde ga oterali) – kao sto mnogi citaoci ovog bloga jesu, ima drugacije misljenje… no svakako treba znati sta je “zvanicno pismo zemlje u kojoj zivimo”, nebitno da li cemo ga koristiti ili ne. Tako da ako neko ima siguran izvor za to sta je zvanicno pismo, nega ga slobodno predstavi, varijente “mi protiv njih” me ne zanimaju
Milan - July 23, 2010
Odlican clanak. Jos jednom kapa dole!!!
Данило - July 23, 2010
Хвала на тексту… Сад коначно више не могу да се позивам на рану имплементацију сличног механизма из 2002. у MySQL-у — мада са рекомпилацијом — http://danilo.segan.org/blog/prevod/mysql-i-kolacija ;)
Проблем који тада нисам успео да решим је LIKE подршка (није да сам се много трудио, ал’ ипак), тј. да ли LIKE може да игнорише разлике између писама? То би било корисно додати.
И наравно, било би лепо да ове табеле постану стандардни део MySQL и осталих деривата.
Bogdan Kecman - July 23, 2010
Like radi komparaciju po kolaciji isti kao i ostali delovi mysql-a:
mysql> select SQL_NO_CACHE a from sr_test where a like (‘ab%’);
+————+
| a |
+————+
| ABVGD |
| abvgd |
| АБВГД |
| абвгд |
+————+
4 rows in set (0.00 sec)
sto se tice “standardni deo mysql-a”, najverovatnije ce biti u 5.6 (posto je tamo dz reseno kako treba)
Bogdan Kecman - July 24, 2010
Ako zelite jednakost izmedju ČĆC .. onda nešto ovako (nisam testirao kako radi, mozda sam zaboravio neko slovo):
<collation name="utf8_serbian_ci" id="1200"> <rules> <reset>\u0410</reset> <i>A</i> <i>a</i> <reset>\u0411</reset> <i>B</i> <i>b</i> <reset>\u0412</reset> <i>V</i> <i>v</i> <reset>\u0413</reset> <i>G</i> <i>g</i> <reset>\u0414</reset> <i>D</i> <i>d</i> <reset>\u0402</reset> <i>\u0110</i> <i>\u0111</i> <i>\u0189</i> <i>Dj</i> <i>DJ</i> <i>dj</i> <reset>\u0415</reset> <i>E</i> <i>e</i> <reset>\u0416</reset> <i>\u017D</i> <i>\u017E</i> <i>\u0417</i> <i>Z</i> <i>z</i> <reset>\u0418</reset> <i>\u0419</i> <i>\u0439</i> <i>I</i> <i>i</i> <reset>\u0408</reset> <i>J</i> <i>j</i> <reset>\u041A</reset> <i>K</i> <i>k</i> <reset>\u041B</reset> <i>L</i> <i>l</i> <reset>\u0409</reset> <i>\u01C7</i> <i>\u01C8</i> <i>\u01C9</i> <i>Lj</i> <i>LJ</i> <i>lj</i> <reset>\u041C</reset> <i>M</i> <i>m</i> <reset>\u041D</reset> <i>N</i> <i>n</i> <reset>\u040A</reset> <i>\u01CA</i> <i>\u01CB</i> <i>\u01CC</i> <i>Nj</i> <i>NJ</i> <i>nj</i> <reset>\u041E</reset> <i>O</i> <i>o</i> <reset>\u041F</reset> <i>P</i> <i>p</i> <reset>\u0420</reset> <i>R</i> <i>r</i> <reset>\u0421</reset> <i>S</i> <i>s</i> <i>\u0428</i> <i>\u0448</i> <i>\u0160</i> <i>\u0161</i> <reset>\u0422</reset> <i>T</i> <i>t</i> <reset>\u040B</reset> <i>\u0106</i> <i>\u0107</i> <reset>\u0423</reset> <i>U</i> <i>u</i> <reset>\u0424</reset> <i>F</i> <i>f</i> <reset>\u0425</reset> <i>H</i> <i>h</i> <reset>\u0426</reset> <i>C</i> <i>c</i> <i>\u0427</i> <i>\u010C</i> <i>\u010D</i> <reset>\u040F</reset> <i>\u045F</i> <i>\u01C4</i> <i>\u01C5</i> <i>\u01C6</i> <i>Dz</i> <i>DZ</i> <i>dz</i> </rules> </collation>Ognjen Pejanović - July 28, 2010
Vuk Karadžić je izvršio reformu latinice a ne Jernej Kopitar kako se doskora mislilo. Hrvati nisu nikako mogli da prisvoje ćirilicu pa su svojatali latinicu, a mi se počeli gaditi na latinično pismo.
Naša je latinica i ćirilica.
Pera - August 13, 2010
Hvala za odgovor na moje pitanje od pre 5 godina :).
Btw, odlican text, kao i prethodni.
Bogdan Kecman - August 13, 2010
Kad smo pricali pre 5 godina mogucnost sa XML-om nije postojala :(, samo ona “ubildovana” varijanta. U 5.6 koji ima validnu kontrakciju za dz srpska kolacija (ovakva kao ova iz posta) bi trebala da se nadje u glavnom kodu (najzad).
Иван Бишевац - September 12, 2010
Скоро сам нашао устав републике Србије и нађох члан у коме се дефинише језик и писмо, па сам се сетио дискусије овде. Тамо имамо следећу ствар:
Језик и писмо
Члан 10.
У Републици Србији у службеној употреби су српски језик и ћириличко писмо.
Службена употреба других језика и писама уређује се законом, на основу устава.
Коментар није потребан, дилема је разрешена.
Иван Бишевац - September 12, 2010
Заборавих да оставим везу до документа. Устав се може наћи на адреси:
http://www.sllistbeograd.rs/documents/ustav_republike_srbije_cyr.pdf
Marko - May 22, 2011
Malo kasnim sa čitanjem članka i mislim da je odličan jedino što meni posle opisanog postupka i dalje ne radi kako treba.
Sama ćirilica se sortira kako treba, i latinica takođe ali ne i zajedno. Odnosno
mysql> select _utf8 ‘latinica’ collate utf8_serbian_ci = _utf8 ‘латиница’ collate utf8_serbian_ci;
Meni vraća 0 a ne 1.
Posle “show collation” jedina razlika između ove nove i ostalih kolacija je što ova nova nije “compiled”. Da možda ipak ne treba da se rekompajlira mysql??
Verzija mysql-a je 5.1.49
Bogdan Kecman - May 23, 2011
ne vezano za problem, savetujem ti da bezis sa 5.1 na 5.5 …
sto se tice problema, koji ti je ID kolacije?
ako si napravio XML fajl kako je u postu jedina mogucnost je da ti je ID “pogresan” (5.5 i 5.1 imaju razlicte pocetne id-ove za xml kolacije) ili da ti je kolacija “prevelika”, tj da si dodavao nesto sto nije u xml-u iz ovog posta
Marko - May 25, 2011
Hvala na odgovoru. ID kolacije mi je 240, trebalo bi da je to u redu. Evo jedan izvod iz SHOW COLLATION, nadam se da će se lepo videti. Jedina razlika u odnosu na ostale kolacije je što nije “Yes” u “Compiled” koloni.
| utf8_hungarian_ci | utf8 | 210 | | Yes | 8 |
| utf8_serbian_ci | utf8 | 240 | | | 8 |
| ucs2_general_ci | ucs2 | 35 | Yes | Yes | 1 |
| ucs2_bin | ucs2 | 90 | | Yes | 1 |
Bogdan Kecman - May 26, 2011
nije compiled zato sto je XML a ne ukompajlirana, to je ok.
to mi moralo da sljaka, sad cu da vidim dal imam negde pri ruci neki 5.1 da probam
Bogdan Kecman - May 26, 2011
cudno, ne radi ni meni sa svezim 5.1 … nemam pojma sta je problem bas cu da proverim … sa 5.5 radi lepo
Vladimir - July 8, 2011
Error
SQL query:
ALTER TABLE `opstina` CHANGE `opstina` `opstina` VARCHAR( 30 ) CHARACTER SET utf8 COLLATE utf8_serbian_ci NOT NULL
MySQL said: Documentation
#1005 – Can’t create table ‘autopijac.#sql-928_7′ (errno: 1005)
U cemu je problem niti mogu da promenim utf8 u utf8_serbian_ci niti da napravim novu tabelu sa utf8_serbian_ci ?
A komanda :
mysql> select ‘latinica’ = ‘латиница’;
kod mene se pretvara u:
mysql> select ‘latinica’ = ‘????????’;
Bogdan Kecman - July 8, 2011
Ako ne mozes da promenis u tu kolaciju znaci da ti kolacija ne valja. Proveri sa show collation sta kaze mysql da ima od kolacija.
Ovaj select ti je otisao u ??? zato sto mysql cli nije utf8, kada startas mysql cli kucni prvo jedno “set names ‘utf8′;”
Nadam se da to sve radis sa 5.5, 5.1 nesto zeza sa ovom procedurom nisam ga dugo probao
Vladimir - July 9, 2011
Podesio sam charset utf8 ali i dalje nece,kad koristim phpMyadmin on vidi utf8_serbian_ci ali opet nista.Naravno koristim 5.5 verziju.
mysql> charset utf8
Charset changed
mysql> show collation like ‘%serbian%’;
+—————–+———+——+———+———-+———+
| Collation | Charset | Id | Default | Compiled | Sortlen |
+—————–+———+——+———+———-+———+
| utf8_serbian_ci | utf8 | 1200 | | | 8 |
+—————–+———+——+———+———-+———+
1 row in set (0.00 sec)
mysql> select ‘latinica’ = ‘????????’;
+————————-+
| ‘latinica’ = ‘????????’ |
+————————-+
| 0 |
+————————-+
1 row in set (0.00 sec)
mysql>
Bogdan Kecman - July 9, 2011
probaj da cimnes taj upit iz phpmyadmin-a. Izleda da tvoja konzola ne zna sta je utf8
Marcus - August 3, 2011
Hm… Ovo bi bilo extra kad bi mi proradilo. Koristim mysql 5.1 pod linuxom (Ubuntu) i uradim sve kako si rekao, izmenim Index.xml fajl, sačuvam, restartujem bazu… ali nema nove kolacije :(
Bogdan Kecman - August 3, 2011
Ja ne stizem to da probam na 5.1 vec mesecima … Zasto ne predjes na 5.5 mnoooooogo je bolji od 5.1 ?
Kada stignem da probam ovo na 5.1 updateovacu post ali nekako uvek imam nesto pametnije da radim :)
Marcus - August 4, 2011
U ubuntu repozitorijumu, 5.1 stoji kao poslednja verzija, 5.5 bih dakle morao instalirati ručno što je malo cimanje. al nije frka, bitno mi je da znam da to radi u 5.5 kad mi bude trebalo za neki komercijalni projekat uzeću 5.5, za sad ću iskoristiti 5.1 za ovaj studentski projekat :)
Bogdan Kecman - August 4, 2011
Ja znam da su korisnici Ubuntu distro-a prilicno lenji ali vec jedno 10tak puta sam na nekoliko mesta spomenuo da MySQL koji dolazi uz distro-e ne valja. Ne moze da se poredi sa binaries koje mozes da skines sa dev.mysql.com. Osnovni problem je to sto svaki distro mora da postuje svoja “pravila” (npr RH mora da koristi sve biblioteke kao so, nema statickog linkovanje nicega, major i minor verzija moraju da ostanu iste tokom jedne verzije distro-a etc… Ubuntu ima svoja pravila SUSE svoja …) i svi oni ako hoce da ispostuju pravila koja vaze za “sve pakete” nikako ne mogu da naprave optimalni binaries za database server.
Rucna instalacija na Ubuntu se svodi na to da skines Linux – Generic 2.6 (x86, ##-bit), Compressed TAR Archive sa dev.mysql.com i raspakujes ga u /usr/local/mysql i to je to, sredis /etc/my.cnf i vozi misko
E sad ako bas oces da ides po turubuntu praxi onda isprati uputstvo odavde:
http://geek.co.il/wp/2011/03/02/mysql-5-5-on-ubuntu-10-10
nikola - November 2, 2011
pozdrav, imam slican problem kao Marko, br 17, od May 25, 2011.
SHOW COLLATION; mi lepo pokaze
|utf8_serbian_ci|utf8|1600|||8|
… ali ne mogu da kreiram tabelu koja bi koristila utf8_serbian_ci, niti da promenim neko od postojecih polja u utf8_serbian_ci.
u pitanju je mysql 5.5, na fedori 15.
inace, isto ovo uputsvto sam koristio pre otprilike godinu dana i sve je bilo ok…
pls help ako je moguce.
nikola - November 2, 2011
DODATAK:
eee, uspeo sam, id mi je bio prevelik, kada sam stavoi 240, sve je proslo ok!
hvala u svakom slucaju, i jos vece hvala na izuzetnom uputstvu!
Leave a Reply