Hlavní navigace

Hezky česky v PostgreSQL

Karel Žák 30. 1. 2002

Není v českých konferencích oblíbenějšího tématu ve spojitosti v PostgreSQL než práce s češtinou a různými kódováními. Pojďme se tedy podívat, jak na to.

Protože svět by byl nudný, pokud by byl jednoduchý, již od pradávna si lidé a nejen lidé vymýšlejí různé způsoby, jak si ten život alespoň trošku zpestřit nebo i zkomplikovat. Různost jazyků a způsobů, jak zapisovat v té které části světa slova, je toho dokladem, a v případě snahy přenést a vyřešit tento problém u software jsou toho dokladem i vrásky na tvářích programátoru a uživatelů.

Snahou vývojářů PostgreSQL je, aby vrásek na tváři uživatelů v různých částech světa bylo co nejméně. Pro začátek bude dobré si ozřejmit dva základní pojmy, a to „locale“ a „encoding“.

Tedy „locale“. Často hovoříme o tom, že nějaký program má podporu locale. Znamená to, že daný program umí v přesně definovaných kategoriích pracovat s daty tak, jak je to pro daný stát (oblast) běžné. Těmito kategoriemi jsou:

Tabulka č. 245

LC_COLLATE
LC_CTYPE
LC_MESSAGES
LC_MONETARY
LC_NUMERIC
LC_TIME

porovnávání řetězců
klasifikace znaků
překlady hlášek
formátování zápisu u peněz
formátování zápisu u čísel
formátování zápisu času/datumu

PostgreSQL nevyužívá v současné době všechny tyto kategorie, ale pouze LC_COLLATE, LC_CTYPE, LC_MONETARY. Malou výjimkou jsou funkce to_char() a to_number(), které jsou schopny využívat i typ LC_NUMERIC (v budoucnu možná i LC_TIME). Od verze 7.2 je používán i LC_MESSAGES.

To znamená, že například standardní výstup čísla bude vždy ve formátu s tečkou na místě desetinné čárky. Podobně i čas a datum budou vždy používat anglická jména dní a měsíců. Toto omezení snad bude v některých budoucích verzích řešeno (locale-per-column). Prozatím můžete v případě čísel použít funkci to_char().

K tomu, aby PostgreSQL mohl používal locale, musí být kompilován s jejich podporou (–enable-locale). Je možné, že takto připravený server je součástí i vaší oblíbené distribuce.

Teď mírně přeskočíme a podíváme se na „encoding“, tedy kódování. Masochismus některých lidí okolo počítačů neznal mezí, a proto dnes máme často i pro jeden jazyk několik různých kódování. Čeština není výjimkou, ba dokonce je zářným příkladem. Naštěstí se dnes doba ustálila na dvou základních, a to ISO-8859–2 (alias Latin2), které je mezinárodně potvrzeným standardem, a tím druhým kódováním je Win1250, což je mezinárodně trpěný nestandard firmy Microsoft.

Novější řešení v oblasti kódování je UNICODE, multibyte kódování, které je schopno obsáhnout v sobě všechny myslitelné znaky.

PostgreSQL podporuje všechna tato jmenovaná kódování. Pochopitelné obsahuje i podporu dalších, ve verzi 7.2 jsou to:

Alt (IBM866), BIG5, EUC-CN, EUC_JP, EUC_KR, EUC_TW, ISO-8859–1, ISO-8859–2, ISO-8859–3, ISO-8859–4, ISO-8859–5, ISO-8859–6, ISO-8859–7, ISO-8859–8, ISO-8859–9, ISO-8859–10, ISO-8859–13, ISO-8859–14, ISO-8859–15, ISO-8859–16, KOI8-R, Shift-JIS, UTF-8, WIN1250, WIN1251, SQL_ASCII a MULE_INTERNAL,

Jen pro doplnění a případné zvědavce, „MULE_INTERNAL“ je vlastní PostgreSQL multibyte kódování, které lze používat například namísto UNICODE. Jedná se o historickou záležitost.

Důležité je poznamenat, že PostgreSQL poněkud neštastně používá pro jména kódování aliasy, například LATIN2. Od připravované verze 7.2 bude možné pro jména kódování používat i standardních názvů (např. ISO-8859–2).

Proto, aby PostgreSQL byl schopen využívat různá kódování, je nutné ho kompilovat s přepínačem –enable-multibyte –enable-recode.

Předpokládejme, že již máte PostgreSQL s podporou jak různých kódování, tak locale, a že máte server standardně nainstalovaný.

A teď to nejdůležitější, což je inicializace prostoru, kde budou uloženy databáze. V případě, že za vás tuto inicializaci provádí nějaký instalační systém (deb, rpm), je vhodné se přesvědčit o tom, jak byla inicializace provedena (podle mne by to mělo být u solidního balíčku dané distribuce popsáno). Pochopitelně tuto inicializaci lze provést i dodatečně a třeba i několikrát, ovšem za podmínky, že vaše databáze neobsahují data.

Inicializace prostoru pro databáze (database cluster) se provádí programem „initdb“. Program musí být spuštěn pod uživatelem, pod kterým při běžném použití poběží SQL server.

Locale se nastavují pouze a jen při této inicializaci. Je to proto, že za chodu lze velmi těžko měnit věci, které mají fatální vliv na záležitosti, jako jsou indexy. To znamená, že máte-li inicializaci provedenou s en_US, je pozdější laborování s cs_CZ naprosto zbytečné. Příklad:

# su - postgres
$ export LANG="czech"
$ /usr/local/postgresql/bin/initdb -D /var/postgresql

Tento příklad připraví v adresáři /var/postgresql prostor pro databáze s tím, že se předpokládá použití českých locale.

Při inicializaci lze taktéž definovat implicitní kódování databází, a to pomocí parametru -E (například -E LATIN2). Každá nově vytvořená databáze, není-li specifikováno jinak, pak bude používat toto kódování.

Nyní již máme server kompletně připraven k použítí. Tiše předpokládám, že jste se podívali do dokumentace na to, jak si udělat uživatele (su – postgres; createuser někdo). Stejně tak předpokládám, že jste se vyrovnali s tím, jak donutit server používat TCP/IP (start s parametrem -i). Dobré je v konfiguraci nebo startujících skriptech zohlednit vámi požadované nastavení locale (export LANG=czech), záleží to na vaší distribuci a na způsobu, jakým startuje PostgreSQL server.

A nyní hurá do používání. Server nám běží a je tedy na čase udělat si nějakou tu databázi. Na počátku je dobré použít služeb skriptu createdb. Opět zde lze specifikovat kódování, ve kterém má databáze být (parametr -E). Není-li kódování specifikováno, použije se defaultní, které jste specifikovali při inicializaci pomocí skriptu initdb. Pokud jste ani zde žádné kódování nenastavili, bude databáze vytvořena v kódování SQL_ASCII.

PostgreSQL pochopitelně umožňuje používat databáze v různých kódováních. Společným pro všechny databáze je jen nastavení locale.

Nyní se můžeme k naší databázi přihlásit. PostgreSQL umožňuje jednu důležitou věc, a to rozdílné kódování databáze a klienta. Znamená to, že data jsou v obou směrech serverem překódovávána. Pochopitelně, že k tomu, aby server takové překódování prováděl, potřebuje informaci, co daný klient používá. Tu mu lze poskytnout dvěma způsoby. Buď ještě před startem klienta nastavíme proměnnou PGCLIENTENCODIN­G=LATIN2 (nebo jiné kódování), a nebo za běhu klienta provedeme SQL příkaz SET CLIENT_ENCODING TO ‚LATIN2‘;.

V případě, že serveru nesdělíte, v jakém kódování pracuje klient, bude předpokládat, že se jedná o stejné kódování, jako používá databáze, ke které se klient připojil.

A nyní je naše session s PostgreSQL serverem plně připravena a můžete do serveru vkládat data v daném kódování.

Kontrolu nastavení lze provést příkazy: SHOW CLIENT_ENCODING; a SHOW SERVER_ENCODING;. V klientském programu „psql“ pak lze pomocí příkazu \l zobrazit seznam všech databází včetně používaného kódování. Například:

     Name     |  Owner   | Encoding
--------------+----------+-----------
 il2          | zakkr    | LATIN2
 mape_catalog | mape     | SQL_ASCII
 utf          | nooper   | UNICODE
 template0    | postgres | SQL_ASCII
 template1    | postgres | SQL_ASCII
 (5 rows)

Z vlastní zkušenosti mohu potvrdit i to, že v jedné databázi (s UNICODE) lze mít texty v několika různých jazycích reprezentovaných na straně klienta různými kódováními. Práce s takovou DB je záležitostí pečlivého odlišení jazyka jednotlivých textů a následného adekvátního nastavování CLIENT_ENCODING. To může být efektivní například u web aplikace, která pracuje v různých jazycích.

Pro úplnost ještě poznamenám, že ve spojitosti s kódováním lze použít funkci to_ascii(), která provede překódování do ASCII. Od verze 7.2 bude dostupná další funkce, a to je convert(), umožňující převod z jednoho kódování do druhého.

Nechť vám příliš žluťoučký kůň úpí ďábelské (k)ódy i v PostgreSQL.

Našli jste v článku chybu?

23. 9. 2006 11:10

Shaman2nd (neregistrovaný)
Obavam se, ze ILIKE slapat nebude (osobne mam PG 8.1.3 a stale jeste nefunguje) - to ale nebrani tomu formulovat where clause jako lower(neco) like lower('%neco%'). Ale pozor, funguje to jen za podminky, ze pri vytvareni db uloziste (clusteru) bylo nastaveno locales (LC_TYPE a LC_COLLATE) na nejake ceske (cs_CZ.utf8, cs_CZ.latin2, ...). Zaroven musi byt samotna db (ne tedy cluster, ale ta db, co je v clusteru) ve stejnem kodovani jako tyto locales. Doporucuji se odpichnout zde: http://ww…

9. 12. 2005 16:25

Airie (neregistrovaný)
Dobrý den, nesjem skoro vubec zběhlý d postgresu a hledám pomoc. Mám databázi s kodováním Latin 2 a aplikaci v php. Když hledám pomoci sql dotazu SELECT neco FROM nejakatabulka WHERE neco ILIKE '%neco%' tak mi to sice najde case insenitive znaky, ale ne pro české znaky. Ty to hledá stále case senstitive. Nevíte kde mám co nastavit???
Díky Airie - drdoc@email.cz
Vitalia.cz: To není kašel! Správná diagnóza zachrání život

To není kašel! Správná diagnóza zachrání život

Měšec.cz: mBank cenzuruje, zrušila mFórum

mBank cenzuruje, zrušila mFórum

Podnikatel.cz: Přehledná titulka, průvodci, responzivita

Přehledná titulka, průvodci, responzivita

Podnikatel.cz: Babiše přesvědčila 89letá podnikatelka?!

Babiše přesvědčila 89letá podnikatelka?!

Podnikatel.cz: Víme první výsledky doby odezvy #EET

Víme první výsledky doby odezvy #EET

Lupa.cz: Teletext je „internetem hipsterů“

Teletext je „internetem hipsterů“

Vitalia.cz: Co pomáhá dítěti při zácpě?

Co pomáhá dítěti při zácpě?

120na80.cz: Na ucho teplý, nebo studený obklad?

Na ucho teplý, nebo studený obklad?

Lupa.cz: Insolvenční řízení kvůli cookies? Vítejte v ČR

Insolvenční řízení kvůli cookies? Vítejte v ČR

Měšec.cz: Kdy vám stát dá na stěhování 50 000 Kč?

Kdy vám stát dá na stěhování 50 000 Kč?

Vitalia.cz: Tesco: Chudá rodina si koupí levné polské kuře

Tesco: Chudá rodina si koupí levné polské kuře

Podnikatel.cz: Na poslední chvíli šokuje vyjímkami v EET

Na poslední chvíli šokuje vyjímkami v EET

Měšec.cz: Přejete si číslo účtu na přání?

Přejete si číslo účtu na přání?

DigiZone.cz: Sony KD-55XD8005 s Android 6.0

Sony KD-55XD8005 s Android 6.0

Lupa.cz: Seznam mění vedení. Pavel Zima v čele končí

Seznam mění vedení. Pavel Zima v čele končí

Lupa.cz: EET v e-shopech? Zdražení a horší komfort

EET v e-shopech? Zdražení a horší komfort

120na80.cz: Rakovina oka. Jak ji poznáte?

Rakovina oka. Jak ji poznáte?

Podnikatel.cz: Chtějte údaje k dani z nemovitostí do mailu

Chtějte údaje k dani z nemovitostí do mailu

Podnikatel.cz: Babiš: E-shopy z EET možná vyjmeme

Babiš: E-shopy z EET možná vyjmeme

Vitalia.cz: Dáte si jahody s plísní?

Dáte si jahody s plísní?