Lekce 8 - SQLite - Datové typy, NULL a dynamické typování
V předešlém cvičení, Řešené úlohy k 7. lekci SQLite, jsme si procvičili nabyté zkušenosti z předchozích lekcí.
V dnešním SQLite tutoriálu se vrátíme k datovým typům
a řekneme si něco o hodnotě NULL
.
Datové typy
Hned na začátku seriálu jsme se setkali s několika datovými typy. Tehdy
jsem vám s nimi nechtěl motat hlavu. Řeč byla o typech INTEGER
a TEXT
. Databáze (konkrétně zde SQLite) jich má sice ještě
několik, ale na rozdíl od jiných SQL databází jich je poměrně málo.
Celé číslo - INTEGER
Dle velikosti samotného čísla, které se ukládá, se použije 1, 2, 3, 4, 5, 6, 7 nebo 8 bajtů.
Pokud hledáte datový typ boolean (hodnoty
true
/false
), tak k ukládání této hodnoty se
používá rovněž INTEGER
– 0
=
false
, 1
= true
.
Reálné číslo - REAL
K ukládání reálných čísel se používá 64 bitů, přesnost je zhruba 15 až 16 čísel a číslo může nabývat hodnot +-5.0 * 10^−324 až +-1.7 * 10308.
Textový řetězec - TEXT
Datový typ TEXT
se používá k ukládání řetězců znaků
dle použitého kódování databáze (UTF-8, UTF-16BE nebo UTF-16LE).
Používá se taktéž k ukládání času ve formátu
rrrr-mm-dd hh:mm:ss.sss
, ale jde použít i datový typ
INTEGER
ve formátu Unix, tedy počet sekund od 1. ledna 1970 0:00,
nebo typ REAL
.
Binární data - BLOB
Obecná data v binárním tvaru, použití je analogické jako u typu
TEXT
. Umožňují do databáze ukládat např. obrázky nebo
zvuky.
Hodnota NULL
Datové typy v databázích se malinko odlišují od datových typů, jak je
známe v programovacích jazycích. Zatímco třeba v Céčku může mít
int
hodnoty jen nějakých -32.000 až +32.000 a nic kromě toho,
databázový INTEGER
může nabývat i hodnoty NULL
.
NULL
nemá vůbec nic společného s nulou (0
),
označuje to, že hodnota nebyla ještě zadána. Filozofie
databází je takto postavena, nezadané hodnoty mají výchozí hodnotu
NULL
(pokud jim nenastavíme jinou) a každý datový typ má
kromě hodnot, které bychom v něm očekávali, navíc možnou hodnotu
NULL
. Datovému typu tuto hodnotu můžeme i zakázat, více
dále.
Pokud např. příkazem INSERT
vložíme uživatele a vyplníme
jen některé hodnoty, do dalších hodnot se vloží NULL
. Zkusme
si to:
INSERT INTO "uzivatele" ("jmeno", "prijmeni") VALUES ('Pan', 'Neuplny');
Výsledek:

Přínos hodnoty NULL
Asi se ptáte, k čemu hodnota NULL
vlastně je? Její přínos
je v tom, že poznáme, jestli byla hodnota zadána. Např. při zadávání
čísla neexistuje hodnota, podle které bychom poznali, že číslo není
zadáno. Kdybychom si k tomuto určili hodnotu nula (0
), nevíme,
jestli uživatel číslo nezadal nebo zadal právě nulu. NULL
mimo
jiné i šetří místo v databázi, kde na rozdíl od výchozích hodnot
nezabírá místo.
NULL
na straně aplikace
Již jsme si řekli o tom, že programovací jazyky hodnotu NULL
zpravidla nemají (tedy ty staticky typované). V jazycích jako je třeba
dynamické PHP nemusíme datový typ vůbec řešit, i když je dobré vědět,
že se na NULL
můžeme zeptat, když to budeme potřebovat. V
jazycích typovaných, jako je třeba Java nebo C#, musíme použít jiné
datové typy. V C# můžeme kterýkoli datový typ označit jako NULLovatelný a
on pochopí, že v něm může být i NULL
. V Javě budeme
používat datové typy s velkými písmeny, tedy např. pro čísla místo
int
použijeme Integer
.
Upřesňující informace k datovým typům
K datovým typům (chcete-li ke sloupcům) můžeme uvést několik
upřesňujících informací. Již jsme se setkali s AUTOINCREMENT
.
Podívejme se na další:
Název | Popis |
---|---|
AUTOINCREMENT | Při vkládání řádku dejte této položce hodnotu NULL a systém jí automaticky přidělí hodnotu o 1 větší než dal minulému řádku (přírůstek se teoreticky dá změnit, ale tím se teď nebudeme zatěžovat). Výborná věc pro pohodlnou tvorbu unikátních identifikačních klíčů. |
UNIQUE | Říká, že nesmí existovat víc řádků, které mají v této položce stejnou hodnotu (s výjimkou hodnoty NULL). Smysl to má pouze u klíčů. |
NOT NULL | Tato hodnota nesmí být prázdná - nepůjde do ní vložit hodnota NULL. |
PRIMARY KEY | Tím se určí, že se tento sloupec (v každé tabulce max. jeden) bude používat jako klíč. Vhodné pro nějaké relativně krátké identifikační kódy, podle kterých budeme řádky nejčastěji hledat. Primární klíč je vždy NOT NULL a UNIQUE; i když to nenařídíme, dostane tyto vlastnosti implicitně. |
DEFAULT hodnota | Výchozí hodnota, kterou položka dostane, když ji při vkládání řádku neuvedeme. Nefunguje u typů TEXT, BLOB a u položek, které mají nastavený AUTOINCREMENT. |
Nová slova upřesňující datový typ se vkládají za něj, stejně jako
tomu bylo u AUTOINCREMENT
. Uveďme si nějaký příklad:
CREATE TABLE "uzivatele" ( "uzivatele_id" INTEGER PRIMARY KEY AUTOINCREMENT, "jmeno" TEXT NOT NULL, );
Dynamické typování
Naprostá většina SQL databází používá k ukládání statické typování, při vytvoření tabulky zadáme datový typ, který má daný sloupec obsahovat, a datový typ položky se určuje pouze podle toho. SQLite naopak používá dynamické typování, kdy se určuje datový typ podle samotné položky (hodnoty), kterou tam nahráváme. Pojďme si to vyzkoušet.
Připomeňme si strukturu naší tabulky uživatelů:
CREATE TABLE "uzivatele" ( "uzivatele_id" INTEGER PRIMARY KEY AUTOINCREMENT, "jmeno" TEXT, "prijmeni" TEXT, "datum_narozeni" TEXT, "pocet_clanku" INTEGER );
Logicky by neměl jít uložit do sloupce počtu článků nějaký text, takže si zkusíme vložit takovýto záznam:
INSERT INTO "uzivatele" ("pocet_clanku") VALUES ('Mnoho');
Avšak výsledek je díky dynamickému typování takovýto:

Až na sloupec s parametry INTEGER PRIMARY KEY
můžeme ve
SQLite ukládat jakýkoli typ hodnoty do jakéhokoli sloupce.
Možná vás teď napadá, jestli jsme tedy nemohli definovat tabulku takto:
CREATE TABLE "uzivatele" ( "uzivatele_id" INTEGER PRIMARY KEY AUTOINCREMENT, "jmeno", "prijmeni", "datum_narozeni", "pocet_clanku" );
Ano mohli, je to naprosto validní SQL příkaz v SQLite, avšak doporučuji
vám, abyste datové typy definovali a dodržovali. Potom víte, v jakém
formátu tam ukládat data a v jakém je očekávat třeba ve své aplikaci. Na
tento typ se také SQLite pokusí převést data, takže pokud jste sloupec
označili jako INTEGER
a vložíte do něj hodnotu
15.0
, uloží se číslo 15.
Kompatibilita s ostatními databázemi
V rámci kompatibility s ostatními SQL databázemi mění SQLite podobné datové typy ostatních databází na své vlastní. Naše tabulka uživatelů by se vytvořila v SQL takto:
CREATE TABLE `uzivatele` ( `uzivatele_id` int AUTO_INCREMENT, `jmeno` varchar(60), `prijmeni` varchar(60), `datum_narozeni` date, `pocet_clanku` int, PRIMARY KEY (`uzivatele_id`) );
Pokud bychom tento kód rozběhli na SQLite, tak by byl překvapivě úspěšně proveden, a byl by chápán stejně, jako kdybychom zadali kód:
CREATE TABLE "uzivatele" ( "uzivatele_id" INTEGER PRIMARY KEY AUTOINCREMENT, "jmeno" TEXT, "prijmeni" TEXT, "datum_narozeni" TEXT, "pocet_clanku" INTEGER );
Tato vlastnost nám hodně ulehčí práci, když přecházíme z jiné databáze na SQLite a chceme si přenést i data.
V následujícím kvízu, Kvíz - Export, import, řazení a datové typy v SQLite, si vyzkoušíme nabyté zkušenosti z předchozích lekcí.