Nikdy nevíš, kdy to přijde
Zobrazit menu   MENU

25. Kódování řetezců

Jistě se Vám již v programování někdy stalo, že vám česká diakritika pořádně zkomplikovala situaci. O kolik by byl svět programování jednodušší bez diakritiky :) Nicméně diakritika tu je a my se s ní musíme nějak vypořádat a to i v rámci MySQL databáze.

Pokud máme aplikaci, která spolupracuje s databází, musíme řešit diakritiku v podstatě na třech úrovních. Při přesunu dat z aplikace do databáze (ukládání), interně v rámci práce s daty v databází a jako poslední přesun dat z databáze na výstup v aplikaci. My se budeme věnovat části prostřední, protože první a třetí část je závislá na technologii kterou využíváte.

Každý řetezec v MySQL je uložený v nějakém kódování - znakové sadě. Ta může být nastavena na několika úrovních: pro celý server, celou databázi, konkrétní tabulku nebo i konkrétní sloupec. Tak tak možné aby v jedné databázi byly tabulky s různými kódovánímí a dokonce i různě kódované sloupce v jedné tabulce.

Kódování nastavujeme pomocí klíčového slova CHARSET, následovaného rovnítkem a hodnotou. Uvést ho můžeme jak v definici sloupce, tak celé tabulky:

CREATE TABLE `slovnik` (
`slovnik_id` int(10) NOT NULL,
`slovo` varchar(100) NOT NULL
) CHARSET=utf8


A zároveň si vložíme pokusná testovací data:
INSERT INTO `slovnik` (`slovnik_id`, `slovo`) VALUES
(1, 'Peří'),
(2, 'Anakonda'),
(3, 'Hrubý'),
(4, 'Chrobák'),
(5, 'Červotoč'),
(6, 'Cuketa'),
(7, 'Fregata'),
(8, 'Jinovatka');


Diakritika v řazení

Čeština je poměrně specifická pro abecední řazení. Kromě písmen s diakritikou máme ještě specialitu v písmenu "ch". Dříve toto způsobovalo problémy, naštěstí aktuální verze MySQL se s tím vypořádají bez komplikací. Pokud řešíme řazení, jde v kontextu MySQL o tzv. Porovnávání (collate), tedy porovnávání 2 znaků, což je základem jakéhokoliv řazení řetezců.

Způsob porovnávání můžeme opět nastavit na více úrovních, tedy například pro každý sloupec tabulky jinak. Porovnávání nastavíme pomocí klíčového slova COLLATE. U předchozí tabulky nastavíme porovnávání na dánské, které nezná naše české znaky a vyzkoušíme řazení:

ALTER TABLE `slovnik` CHANGE `slovo` `slovo` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_danish_ci NOT NULL;


Nyní si vypíšeme všechny řádky z tabulky seřazené dle sloupce slovo abecedně vzestupně:

SELECT * FROM `slovnik` ORDER BY slovo ASC;


+------------+-----------+
| slovnik_id | slovo     |
+------------+-----------+
|          2 | Anakonda  |
|          5 | Červotoč  |
|          4 | Chrobák   |
|          6 | Cuketa    |
|          7 | Fregata   |
|          3 | Hrubý     |
|          8 | Jinovatka |
|          1 | Peří      |
+------------+-----------+


Jak vidíme z výsledku, data nejsou seřazená tak jak bychom očekávali (přechozené C a Č, ani CH není na svém místě), protože nastavené kódování neumí správně porovnávat české znaky. Nyní změníme porovnávání na české a opět zavoláme stejný dotaz jako v předchozím případě.

ALTER TABLE `slovnik` CHANGE `slovo` `slovo` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_czech_ci NOT NULL;


+------------+-----------+
| slovnik_id | slovo     |
+------------+-----------+
|          2 | Anakonda  |
|          6 | Cuketa    |
|          5 | Červotoč  |
|          7 | Fregata   |
|          3 | Hrubý     |
|          4 | Chrobák   |
|          8 | Jinovatka |
|          1 | Peří      |
+------------+-----------+


Nyní vídíme že vše je již dle našich očekávání. Porovnávání můžeme explicitně zadat i v rámci SELECT dotazu, ale nedovedu si příliš představit situaci kdy by to bylo potřeba. Při běžném použití většinou žádné velké hrátky s kódováním nebývají, ale je dobré mít o něm povědomí.


Další díly tutoriálu

23. Větvení kódu - podmínky a cykly
24. Práce s datem a časem
25. Kódování řetezců