MySQL/Kódování

Z Wikiverzity

Databázový server MySQL je schopen pracovat s různým kódováním národních abeced v různých tabulkách. Jeho správná konfigurace je proto nutná zvlášť pro takové národy, které se neobejdou bez zvláštních písmenek, jako jsme my.

Současné pětkové verze MySQL řeší toto kódování jinak než verze předcházející. Zde se budeme zabývat pouze touto novější verzí. Nejdřív je nutno si ale něco říci o proměnných a nastavení serveru.

Proměnné a nastavení serveru[editovat]

MySQL server udržuje mnoho proměnných, které prozrazují, jak je zkonfigurovaný. Které to jsou a jaké mají hodnoty je dáno mj. verzí konkrétního serveru, dále tím, jak byl zkompilovaný a konečně nastavením konfiguračních souborů. Jejich výpis dostaneme příkazem z rootovské řádky:

# mysqld --verbose --help

(# na začátku naznačuje, že příkaz spouštíme z příkazové řádky roota)

Pokud je systémová proměná dynamická, znamená to, že ji můžeme měnit za běhu programu, a to příkazem SET z příkazového řádku klienta mysql.

Z příkazové řádky klienta si můžeme seznam všech systémových proměnných a jejich nastavení prohlédnout:

mysql> SHOW VARIABLES;

+---------------------------------+-----------------------------+
| Variable_name                   | Value                       |
+---------------------------------+-----------------------------+
| auto_increment_increment        | 1                           |
| auto_increment_offset           | 1                           |
| automatic_sp_privileges         | ON                          |
| back_log                        | 50                          |
| basedir                         | /usr/                       |
| binlog_cache_size               | 32768                       |
| bulk_insert_buffer_size         | 8388608                     |
| character_set_client            | latin1                      |
| character_set_connection        | latin1                      |
| character_set_database          | latin1                      |
| character_set_filesystem        | binary                      |
| character_set_results           | latin1                      |
| character_set_server            | latin1                      |
| character_set_system            | utf8                        |
| character_sets_dir              | /usr/share/mysql/charsets/  |
| collation_connection            | latin1_swedish_ci           |
| collation_database              | latin1_swedish_ci           |
| collation_server                | latin1_swedish_ci           |
| completion_type                 | 0                           |
...

atd.

Pokud nás zajímají jen některé proměnné, například ty, týkající se kódování, můžeme použít příkaz:

mysql>  SHOW VARIABLES like 'character_set_%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | latin1                     | 
| character_set_connection | latin1                     | 
| character_set_database   | latin1                     | 
| character_set_filesystem | binary                     | 
| character_set_results    | latin1                     | 
| character_set_server     | latin1                     | 
| character_set_system     | utf8                       | 
| character_sets_dir       | /usr/share/mysql/charsets/ | 
+--------------------------+----------------------------+

(Procento % v MySQL znamená jakýkoli řetězec.)

Dejme tomu, že se rozhodneme změnit nastavení systémové proměnné pro defaultní kódování na úrovni serveru:

 mysql> SET GLOBAL character_set_server='latin2';

 Query OK, 0 rows affected (0.00 sec)


Z nějakého podivného důvodu se nám namísto nového nastavení ukáže to původní:

mysql> SHOW VARIABLES like 'character_set_server';
+----------------------+--------+
| Variable_name        | Value  |
+----------------------+--------+
| character_set_server | latin1 | 
+----------------------+--------+

(přitom ale např. phpMyAdmin nám nové nastavení ukáže.)


Kódování a řazení[editovat]

Jsou dvě věci: jednou je použitá znaková sada a druhou je způsob slovníkového řazení znakových řetězců (kolace). Obě věci spolu souvisí.

Spustíme klienta:

mysql -umojejmeno -p
...

a zadáme příkaz:

mysql> SHOW CHARACTER SET;

dostaneme něco jako:

+----------+-----------------------------+---------------------+--------+
| Charset  | Description                 | Default collation   | Maxlen |
+----------+-----------------------------+---------------------+--------+
| big5     | Big5 Traditional Chinese    | big5_chinese_ci     |      2 |
| dec8     | DEC West European           | dec8_swedish_ci     |      1 |
| cp850    | DOS West European           | cp850_general_ci    |      1 |
| hp8      | HP West European            | hp8_english_ci      |      1 |
| koi8r    | KOI8-R Relcom Russian       | koi8r_general_ci    |      1 |
| latin1   | cp1252 West European        | latin1_swedish_ci   |      1 |
| latin2   | ISO 8859-2 Central European | latin2_general_ci   |      1 |
| swe7     | 7bit Swedish                | swe7_swedish_ci     |      1 |
| ascii    | US ASCII                    | ascii_general_ci    |      1 |
| ujis     | EUC-JP Japanese             | ujis_japanese_ci    |      3 |
| sjis     | Shift-JIS Japanese          | sjis_japanese_ci    |      2 |
| hebrew   | ISO 8859-8 Hebrew           | hebrew_general_ci   |      1 |
| tis620   | TIS620 Thai                 | tis620_thai_ci      |      1 |
| euckr    | EUC-KR Korean               | euckr_korean_ci     |      2 |
| koi8u    | KOI8-U Ukrainian            | koi8u_general_ci    |      1 |
| gb2312   | GB2312 Simplified Chinese   | gb2312_chinese_ci   |      2 |
| greek    | ISO 8859-7 Greek            | greek_general_ci    |      1 |
| cp1250   | Windows Central European    | cp1250_general_ci   |      1 |
| gbk      | GBK Simplified Chinese      | gbk_chinese_ci      |      2 |
| latin5   | ISO 8859-9 Turkish          | latin5_turkish_ci   |      1 |
| armscii8 | ARMSCII-8 Armenian          | armscii8_general_ci |      1 |
| utf8     | UTF-8 Unicode               | utf8_general_ci     |      3 |
| ucs2     | UCS-2 Unicode               | ucs2_general_ci     |      2 |
| cp866    | DOS Russian                 | cp866_general_ci    |      1 |
| keybcs2  | DOS Kamenicky Czech-Slovak  | keybcs2_general_ci  |      1 |
| macce    | Mac Central European        | macce_general_ci    |      1 |
| macroman | Mac West European           | macroman_general_ci |      1 |
| cp852    | DOS Central European        | cp852_general_ci    |      1 |
| latin7   | ISO 8859-13 Baltic          | latin7_general_ci   |      1 |
| cp1251   | Windows Cyrillic            | cp1251_general_ci   |      1 |
| cp1256   | Windows Arabic              | cp1256_general_ci   |      1 |
| cp1257   | Windows Baltic              | cp1257_general_ci   |      1 |
| binary   | Binary pseudo charset       | binary              |      1 |
| geostd8  | GEOSTD8 Georgian            | geostd8_general_ci  |      1 |
| cp932    | SJIS for Windows Japanese   | cp932_japanese_ci   |      2 |
| eucjpms  | UJIS for Windows Japanese   | eucjpms_japanese_ci |      3 |
+----------+-----------------------------+---------------------+--------+
36 rows in set (0.02 sec)

V levé části vidíme, kterými způsoby kódování server disponuje, a vpravo jsou defaultní nastavení kolace. Zapamatujeme si tři pro nás nejdůležitější způsoby kódování:

  • latin1 (cp1252 - západoevropské), defaultní kolace: latin1_swedish_ci – toto je defaultní nastavení MySQL serveru, při kterém bychom měli se zpracováním češtiny zřejmě problémy
  • latin2 (ISO 8859-2 středoevropské), defaultní kolace: latin2_general_ci – mezinárodně doporučené kódování pro středoevropské jazyky, tj. i pro češtinu a slovenštinu
  • cp1250 (středoevropské pro Windows), defaultní kolace: cp1250_general_ci – zvláštní kódování pro středoevropské jazyky, které si vymyslela společnost Microsoft tím, že trochu pozměnila mezinárodně doporučené kódování ISO latin2, pro je lepší se mu vyhnout
  • utf8 (UTF-8 Unicode), defaultní kolace: utf8_general_ci – univerzální kódování, které v sobě zahrnuje znaky všech abeced světa a je mu proto v současné době dávána přednost.

Podíváme se, jaké jsou dostupné kolace pro sadu latin2:

mysql>  SHOW COLLATION LIKE 'latin2%';

+---------------------+---------+----+---------+----------+---------+
| Collation           | Charset | Id | Default | Compiled | Sortlen |
+---------------------+---------+----+---------+----------+---------+
| latin2_czech_cs     | latin2  |  2 |         | Yes      |       4 |
| latin2_general_ci   | latin2  |  9 | Yes     | Yes      |       1 |
| latin2_hungarian_ci | latin2  | 21 |         | Yes      |       1 |
| latin2_croatian_ci  | latin2  | 27 |         | Yes      |       1 |
| latin2_bin          | latin2  | 77 |         | Yes      |       1 |
+---------------------+---------+----+---------+----------+---------+

Všimneme si, že u českého řazení latin2_czech_cs je nejdelší délka podřetězce, podle kterého se třídí – je to dáno zvláštnostmi a složitostí pravidel pro české slovníkové řazení, kde jsou zvláštní pravidla pro řazení písmene ch, písmen s diakritikou, přehlasovaných znaků atd.

Další zvláštnost je, že název českého řazení latin2_czech_cs končí písmeny _cs. Toto cs nemá nic společného s češtinou, ale znamená to case sensitive, tzn. že se řadí s ohledem na velikost písmen. Další řazení, končící na _ci, jsou case insensitive, tzn. řadí se bez ohledu na velikost písmen. U posledního latin2_bin znamená _bin binární způsob řazení podle bitové hodnoty kódu.

Protože kódování utf8 je univerzálnější, má také více možností řazení:

mysql>   SHOW COLLATION LIKE 'utf8_%';
+--------------------+---------+-----+---------+----------+---------+
| Collation          | Charset | Id  | Default | Compiled | Sortlen |
+--------------------+---------+-----+---------+----------+---------+
| utf8_general_ci    | utf8    |  33 | Yes     | Yes      |       1 | 
| utf8_bin           | utf8    |  83 |         | Yes      |       1 | 
| utf8_unicode_ci    | utf8    | 192 |         | Yes      |       8 | 
| utf8_icelandic_ci  | utf8    | 193 |         | Yes      |       8 | 
| utf8_latvian_ci    | utf8    | 194 |         | Yes      |       8 | 
| utf8_romanian_ci   | utf8    | 195 |         | Yes      |       8 | 
| utf8_slovenian_ci  | utf8    | 196 |         | Yes      |       8 | 
| utf8_polish_ci     | utf8    | 197 |         | Yes      |       8 | 
| utf8_estonian_ci   | utf8    | 198 |         | Yes      |       8 | 
| utf8_spanish_ci    | utf8    | 199 |         | Yes      |       8 | 
| utf8_swedish_ci    | utf8    | 200 |         | Yes      |       8 | 
| utf8_turkish_ci    | utf8    | 201 |         | Yes      |       8 | 
| utf8_czech_ci      | utf8    | 202 |         | Yes      |       8 | 
| utf8_danish_ci     | utf8    | 203 |         | Yes      |       8 | 
| utf8_lithuanian_ci | utf8    | 204 |         | Yes      |       8 | 
| utf8_slovak_ci     | utf8    | 205 |         | Yes      |       8 | 
| utf8_spanish2_ci   | utf8    | 206 |         | Yes      |       8 | 
| utf8_roman_ci      | utf8    | 207 |         | Yes      |       8 | 
| utf8_persian_ci    | utf8    | 208 |         | Yes      |       8 | 
| utf8_esperanto_ci  | utf8    | 209 |         | Yes      |       8 | 
| utf8_hungarian_ci  | utf8    | 210 |         | Yes      |       8 | 
+--------------------+---------+-----+---------+----------+---------+

V databázi, která bude obsahovat česky psané záznamy, proto nejspíše budeme používat kódování utf8 a kolaci utf8_czech_ci.


Hierarchie nastavení na čtyřech úrovních[editovat]

Kódování a řazení lze nastavit na čtyřech úrovních, přičemž nižší úroveň má vyšší prioritu.

  1. úroveň serveru
  2. úroveň databáze
  3. úroveň tabulky
  4. úroveň sloupce

Pokud není nikde nic dalšího uvedeno, použije se to kódování a řazení, které je nastaveno pro celý server, nastavení databáze platí pro celou databázi bez ohledu na nastavení serveru, atd. – nastavením nižsí úrovně je možno předcházející vyšší úroveň změnit.

Kódování a řazení na úrovni serveru[editovat]

Defaultní kódování bychom mohli nastavit přepínači při spuštění démona, např:

# mysqld --character-set-server=latin2 --collation-server=latin2_czech_cs

anebo

# mysqld --character-set-server=utf8 --collation-server=utf8_czech_ci

To by ovšem znamenalo nutnost zásahu do spouštěcího skriptu. Proto je lepší příslušné řádky:

character-set-server    = utf8
collation-server        = utf8_czech_ci

přidat do konfiguračního souboru /etc/my.cfg.

Otázkou ale zůstává, jaký má smysl toto nastavení na úrovni serveru měnit. Výhoda to má v tom, že pokud zpracováváme zpravidla databáze v českém prostředí, není potřeba už nic nikde nastavovat a ono to už dál "funguje samo". Nevýhoda tohoto přístupu je v tom, že pokud např. importujeme nějakou databázi, která předpokládá implicitní nastavení serveru latin1 a tudíž žádné vlastní kódování a řazení nedefinuje, zaděláme si na problémy. Proto preferuji ponechat na serveru implicitní kódování latin1 a tím nutit tvůrce databází, aby použité kódování specifikovali na úrovni celé databáze, případně na nižších úrovních (tabulky, sloupce).

Kódování a řazení na úrovni databáze[editovat]

Při vytváření nové databáze proto nezapomeneme definovat použitou znakovou sadu a řazení, např:

mysql> CREATE DATABASE mojedatabaze [DEFAULT] CHARACTER SET utf8 [DEFAULT] COLLATE utf8_czech_ci

U již vytvořené databáze můžeme tyto vlastnosti změnit příkazem:

mysql> ALTER DATABASE mojedatabaze [DEFAULT] CHARACTER SET utf8 [DEFAULT] COLLATE utf8_czech_ci

Chování serveru při vytváření defaultní databáze je řízeno systémovými proměnnými character_set_database a collation_database.

Kódování a řazení na úrovni tabulek a sloupců[editovat]

Podobně lze nastavit kódování a řazení při vytváření či změně tabulky, např:

 CREATE TABLE mojetabulka (seznam sloupcu) CHARACTER SET latin2 COLLATE latin2_czech_cs;
 ALTER TABLE mojetabulka CHARACTER SET latin2 COLLATE latin2_czech_cs;

případně jej ve zvláštních případech specifikovat rozdílně u různých sloupců tabulky. Například když tabulka obsahuje různé sloupce v různých řečech (např. slovník), můžeme pro uložení všech řetězců zvolit společné kódování utf8 a u jednotlivých sloupců různé řazení:

 CREATE TABLE slovnik (
     cesky   VARCHAR(5) COLLATE utf8_czech_ci,
     nemecky VARCHAR(5) COLLATE utf8_esperanto_ci
 ) CHARACTER SET utf8:

Řádkový klient[editovat]

Klient, spouštěný z příkazového řádku textové console či terminálového okna, defaultně přepokládá komunikaci v kódování latin1. Máme-li proto nastaveno prostředí (locales) např. na utf-8, spustíme klienta s volbou:

mysql --default-character-set=utf8