[MySQL] Razeni v cestine = bug v MySQL?

C++, C#, Visual Basic, Delphi, Perl a ostatní

Moderátor: Moderátoři Živě.cz

Odeslat příspěvekod floskule 18. 4. 2006 19:19

Dobry den.
Mam takovy drobny problem s cestinou v MySQL. Hledal jsem na internetu, hledal jsem ve foru, ale odpoved jsem zatim nenalezl.

Situace je nasledujici:
Mam server (MySQL 4.1.12), na nem databazi, v ni tabulku a v te sloupec vse v kodovani utf8 s porovnavanim utf8_czech_ci. Pro lepsi predstavu napr. takovouto:
Kód: Vybrat vše
CREATE DATABASE `cz_test` DEFAULT CHARACTER SET utf8 COLLATE utf8_czech_ci;

USE `cz_test`;

CREATE TABLE `cz_test` (
  `cz_text` nchar(50) collate utf8_czech_ci NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci;

INSERT INTO `cz_test` (`cz_text`) VALUES ('aeeiyouudtn'), ('áéěíýóůúďťň');[/code]
[i]
er-set-client, character-set-results i character-set-connection[/i] mam nastaveny na utf8, collation-connection na utf8_czech_ci.
Presto pokud nyni nad tabulkou `cz_test` spustim nasledujici dotaz:
Kód: Vybrat vše
SELECT `cz_text` FROM `cz_test` WHERE `cz_text` = 'AEEIYOUUDTN';
jsou vysledkem oba radky, tj. jak ten bez diakritiky, tak ten s diakritikou. Stejny vysledek mi vrati i opisnejsi verze tehoz:
Kód: Vybrat vše
SELECT `cz_text` FROM `cz_test` WHERE `cz_text` COLLATE utf8_czech_ci = _utf8'AEEIYOUUDTN' COLLATE utf8_czech_ci;
U CI ceskeho vyhledavani by mi to az zas tolik nevadilo, nebot to jde v podmince WHERE velmi snadno obejit:
Kód: Vybrat vše
SELECT `cz_text` FROM `cz_test` WHERE UCASE(`cz_text`) = BINARY _utf8'AEEIYOUUDTN';

Horsi je to ovsem s razenim. MySQL u vyse uvedenych hlasek diakritiku zcela ignoruje a tak po nasledujici dvojici dotazu:
Kód: Vybrat vše
INSERT INTO `cz_test` (`cz_text`) VALUES ('ďábel'), ('diblík'), ('ďoura');

SELECT `cz_text` FROM `cz_test` ORDER BY `cz_text` COLLATE utf8_czech_ci ASC;[/co
skonci diblik mezi dablem a dourou. :(

Prekvapive je, ze:
* u samohlasek č, ř, š, ž mi vyber i razeni funguje jak ma,
* pokud u databaze, tabulky i sloupce nastavim nejake ne-unicode CS kodovani cestiny, pak vyber funguje jak ma.

Takze nez zacnu celou databazi prevadet do latin2/latin2_czech_cs a vsechny dotazy spolehajici na CI prepisovat pomoci UCASE(), chci se zeptat, zda jsem pri utf8_czech_ci-razeni neco zasadniho neopomnel? A pokud ne, muze mi alespon nekdo potvrdit/vyvratit toto chovani na svem MySQL serveru? (osobne jsem testoval na verzich 4.1.12 a 5.0.20).

Predem velmi dekuji. f.
floskule
Kolemjdoucí

Odeslat příspěvekod o@k 18. 4. 2006 22:32

K MySQL serveru momentálně přístup nemám, nicméně řekl bych, že v abecedním řazení českých slov v MySQL bug není. (Alespoň ne ten, který popisujete.)
Naopak z toho, co píšete, se zdá, že jsou česká slova v MySQL řazena v souladu s normou ČSN 97 6030. Zjednodušeně mají podle této normy primární řadíci platnost jen písmena tzv. standardizované abecedy, tj.:
* písmena bez diakritiky doplněná o vámi zmíněné
* 4 souhlásky s háčky č, ř, š, ž a spřežku ch

Všechna ostatní písmena s diakritikou mají až sekundární řadící platnost.

Abych byl konkrétnější:
MySQL v první fázi řazení z českých slov nejprve odstraní diakritiku u všech písmen, kromě č, ř, š, ž a takto upravená slova seřadí. Pokud se v první fázi po odstranění diakritiky vyskytne dvě či více shodných slov, určí se jejich pořadí podle zbývajících (sekundárních) písmen s diakritickými znaménky. V druhé fázi řazení mají diakritická znaménka následující priority (od nejvyšší k nejnižší):
a/ bez diakritických znamének,
b/ tečka nad písmenem,
c/ čárka,
d/ stříška,
e/ oblouček,
f/ háček (pokud nemá primární řadicí platnost),
g/ přehláska,
h/ dvě čárky,
i/ kroužek,
j/ ogonek,
k/ šikmá čárka,
l/ cédille.

(Uvedený seznam znamének je neúplný, přejatý z Wikipedie. Norma ČSN 97 6030 explicitně uvádí asi 18 diakritických znamének, bohužel jejich seznam se mi teď nedaří najít.)

Jak sám vidíte, je podle této normy diblíkovo místo vždy mezi ďáblem a ďourou. Můžete o tom vést spory, můžete s tím nesouhlasit, ale to je tak všechno, co se proti tomu dá dělat. ;-)


Co podle mě není úplně vpořádku je odlišné chování výběru řetězce v podmínce WHERE pro české case insensitive unicode a case sensitive ne-unicode kódování. Jako by MySQL case insensitive unicode utf8_czech_ci porovnávalo jako obyčejný case insensitive unicode, tj. jen jednoprůchodově.
o@k
Junior
Uživatelský avatar


Kdo je online

Uživatelé procházející toto fórum: Žádní registrovaní uživatelé a 0 návštevníků