SQLite je velmi lehké řešení SQL databáze, ne vždy je potřebný „těžkotonážní server“ (PostgreSQL, MariaDB, …), a tak postrádá některou funkčnost. Mírně jsem postrádal ZEROFILL INTEGER, nebo možnost si jej emulovat pomocí funkce LPAD().
Proč?
ZEROFILL potřebuji na řazení. Používám hierarchickou strukturu pro technická data kategorií, ale v rozšířené struktuře mám i atribut visorder
, jež určuje pořadí a který si pak funkcí CONCAT_WS()
spojuji do dlouhého řadícího řetězce. Řazení podle takto vygenerovaného atributu je lexikografické, takže v řazení stromu s vygenerovanými řetězci ‚00001100002‘ a ‚112‘ by bylo úplně jiné, rozhodně potřebuji za sebou 00000100001, 00000100022, 000002, 00000200001, ale nikoliv 1, 11, 2, 21, 122 (nadřazená je 1 pod níž je 22, nebo je nadřazená 12 a pod ní 2?).
Pravda není to udeální stav, řazení by šlo udělat i podle atributu left
a v administraci bych musel pořešit „přeházení left
i right
na dané úrovni a ve všech podřazených větvích. (A do toho se mi nechce.)
Není to jediné uplatnění, třeba ve mzdovém software používáme osobní čísla a čísla útvarů doplněná zleva nulami na pevnou délku. Avšak mzdy jsou psány nad FirebirdSQL, takže funkce LPAD a RPAD mám k dispozici.
Jak v SQLite?
Dovolím si krátké vysvětlení, jak LPAD funguje. Základní syntaxe je lpad(string text, pozadovana_delka int [, vyplnovy_text text])
(například SELECT LPAD('test', 5, '#');
vrátí #test
), pokud se nezadá výplňový text, je použit znak mezery. Ekvivalentně funguje RPAD, jen doplňuje zprava.
Funkci LPAD i RPAD v SQLite programátor nenajde, jde ji však snadno emulovat pomocí funkcí pro práci s řetězci. Zkrátka „malým cimrmanovským úkrokem stranou“.
Workaround funkcí LPAD a RPAD vypadá následovně:
- LPAD(sloupec, 10, ‚#‘)
- SUBSTR(‚##########‘ || sloupec, -10, 10)
- RPAD(sloupec, 10, ‚#‘)
- SUBSTR(sloupec || ‚##########‘, 1, 10)
Snad jedinou slabinou je nutnost mít výplňový řetězec celý, tj. v maximální délce, do jaké hodláme doplňovat.
Komentáře
4 komentáře: „SQLite: emulace RPAD a LPAD“
SQLite API má jednu úžasnou vlastnost, lze jím registrovat další funkce, které se pak volají v SQL dotazech. Takže si lze napsat vlastní implementaci vlastně čehokoli. Jedna z věcí, která se takto doslova musí psát, byť je pro to v SQLite rezervované slovo, je regexp 😉
[Ondřej Tůma] To jsem použil na něco složitějšího (v C#), attachují se po každém připojení. Bohužel mám pocit, že to je dobrý nápad v programu, kde je připojení perzistentní po dobu běhu aplikace (řádově minuty, hodiny), ne v něčem tak krátkodobém, jako je script generující web stránku.
Nekoukal sem do zdrojáků, ale očekával bych, že registrace i volání této funkce je levná záležitost. Tzn, zápis do nějaké hash tabulky a pak jen volání fce.
[Onřej Tůma] To stojí za otestování, díky za hint a udělám to na stejném případě :-).