V předchozím dílu jsem vysvětloval, že jedním z hlavních nastavení sloupců je jejich datový typ. Určuje formát uložených dat. Pochybuji, že by mělo smysl popisovat význam datových typů jako takových. Obecně se snažíme vybírat typ, jenž zabere v databázi nejméně místa a zároveň splní naše požadavky. Tedy je například očividně jasným plýtváním pro uložení čísla využít textový formát. Na druhou stranu je hloupost uvažovat o co nejúspornějším typu na úkor rizika možného překročení rozsahu v budoucnu. Nám to pak leda přidělá dost práce jej měnit na všech místech v databázi a aplikaci. A to naprosto zbytečně. Vždy bych tedy volil typ, se kterým neplýtváme místem, ani si nesvazujeme ruce do budoucna.
Jak rozdělujeme datové typy?
Systémové datové typy dodávané a podporované SQL Serverem je možné si prohlédnout v každé databázi v okně Object Explorer z Microsoft SQL Server Management Studia. Rozbalte si větev Databases \ “Libovolná databáze” \ Programmability \ Types \ System Data Types. Zde máte několik kategorií datových typů. Pod každým z nich pak nalezneme konkrétní seznam typů. My si je probereme postupně podle kategorií.
Legenda:
jsou datové typy dostupné až od verze SQL Server 2008 (verze 10)
Datové typy podle kategorií
Exact numerics - přesné číselné typy
Typy jasně definující rozsah a přesnost. Vhodné pro operace s čísly, kde je ztráta přesnosti nepřípustná (například finanční operace) a zároveň operace, kde postačí celočíselná hodnota.
- BIT - 1 bit (rozsah 0-1)
- TINYINT - 1 byte (rozsah 0-255)
- SMALLINT - 2 byty (rozsah -32,768 až 32,767)
- INT - 4 byty (rozsah -2^31 až 2^31-1)
- BIGINT - 8 bytů (rozsah -2^63 až 2^63-1)
- DECIMAL(p,s) - číslo s desetinnou čárkou (p je maximum cifer celkem a s je maximální počet desetiných mít, takže 0<=s<=p, rozsah p je 1 až 38). Zabírá celkem 5 až 17 bytů podle rozsahu. Pokud neuvedeme rozsah, jedná se o ekvivalent pro DECIMAL(18,0) – tedy žádná desetinná místa.
- NUMERIC(p,s) – ekvivalent pro DECIMAL.
- SMALLMONEY - také desetinné číslo na desetitisíciny - 4 byty (- 214,748.3648 to 214,748.3647).
- MONEY - desetinné číslo na desetitisíciny - 8 bytů (-922,337,203,685,477.5808 to 922,337,203,685,477.5807).
Approximate numerics - přibližné číselné typy
Přibližné datové typy mají obrovský rozsah na úkor přesnosti. Čím větší číslo bude, tím více se plovoucí desetinná čárka posunuje a tím větší šance je ztráty přesnosti na nižších řádech čísla. Matematické operace často a rády končí nepřesnostmi typu čísel 199999.99875 a podobně. Proto využijeme typ právě pro operace s tolerancí k výpočtu.
- FLOAT(n) - číslo s plovoucí desetinnou čárkou, kde n (1-53) určuje počet bitů - přesnost čísla je přibližná a přímo ovlivněná celkovým počtem cifer - celkem vždy zabírá 4 nebo 8 bytů
- REAL - je to samé jako FLOAT(24)
Date and time - datum a čas
Tady nebude moc co vysvětlovat. Datové typy pro uchování informace o času nebo datu. Microsoft vyslyšel přání vývojářů a přidal ve verzi SQL 2008 nové typy pro uchování data a času.
- SMALLDATETIME – 4 byty a rozsah od 1900-01-01 do 2079-06-06 (přesnost 1 minuta) – pro kompaktní uchování data a času blízké minulosti
- DATETIME – 8 bytů a rozsah od 1753-01-01 do 9999-12-31 (přesnost 3.33 milisekund) – pro uchování běžného data a času (bohužel až od roku 1753)
- DATE
– 3 byty a rozsah 0001-01-01 až 9999-12-31 (přesnost 1 den) – pro uchování pouze data (výhoda plného rozsahu roků od 0001 až 9999) - TIME(n)
- 3 až 5 bytů podle uvedené přesnosti – uchovává pouze čas, rozsah 00:00:00 0000000 až 23:59:59 9999999. Přesnost n je v rozsahu 0 až 7 – uvádí počet desetinných míst vteřin. Pokud n neuvedeme, bude přesnost maximální – tedy 7 desetinných míst. Pokud n uvedeme jako 0, bude mí datový typ nejnižší přesnost - 1 vteřinu. - DATETIME2(n)
- 6 až 8 bytů podle uvedené přesnosti – nastavitelný a přesnější nástupce typ DATETIME. Uchovává datum a čas v rozsahu 0001-01-01 00:00:00.0000000 až 9999-12-31 23:59:59.9999999. Nastavování přesnosti je naprosto identické jako u času TIME – tedy určuje počet desetinných míst vteřin (rozsah 0 až 7, při neuvedeném n je 7). - DATETIMEOFFSET(n)
- 8 až 10 bytů podle uvedené přesnosti. Vychází z datového typu DATETIME2. Je rozšířen o uchování časového pásma (-14 hodin až +14 hodin). Přesnost ovlivňuje naprosto identicky (jako u TIME a DATETIME2) desetinná místa vteřin.
Character strings - běžné textové řetězce (1 byte na znak)
Typy textových hodnot. Každý znak má v paměti přesně 1 byte. Nedoporučuje se používat na kterékoliv texty, co mohou obsahovat nestandardní znaky.
- CHAR(n) - řetězec s pevnou délkou n znaků (1 až 8000) - nepoužité znaky budou mít nulovou hodnotu
- VARCHAR(n) - řetězec s variabilní délkou, kde n udává maximální délku (opět 1 až 8000) - pokud se místo n použije klíčové slovo MAX - tedy VARCHAR(MAX) - maximální délka je v tomto případě 2^31-1 bytů.
- TEXT – maximální délka textu - místo tohoto datového typu se doporučuje používat ekvivalent VARCHAR(MAX)
Unicode character strings - unicode textové řetězce (2 byty na znak)
Typy pro ukládání řetězců s kódováním UNICODE (1 znak = 2 byty) – ideální pro všechen text, obsahující diakritiku, či jiné nestandardní znaky
- NCHAR(n) - viz CHAR(n), jen zabírá 2x víc místa v paměti (unicode kódovaní) a dokáže tak lépe zpracovat například diakritiku nebo obecně nestandardní znaky – kvůli dvojnásobku zabraného místa je rozsah n zmenšen na 1-4000.
- NVARCHAR(n) - viz VARCHAR(n), jen zabírá 2x víc místa v paměti (unicode kódovaní) a dokáže tak lépe zpracovat například diakritiku nebo obecně nestandardní znaky – kvůli dvojnásobku zabraného místa je rozsah n zmenšen na 1-4000.
- NTEXT- maximální délka textu - místo tohoto datového typu se doporučuje používat ekvivalent NVARCHAR(MAX)
Poznámka: Všimněte si počátečního písmene N. To vyjadřuje zkratku slova national, což je označení právě textů s možným výskytem nestandardních znaků podle norem ISO pro SQL.
Binary strings - binární formáty
Typy pro ukládání binárních informací. Řešení pro ukládání souborů, či serializovaných objektů.
- BINARY(n) - datový typ s pevnou délkou n bytů (rozsah 1 až 8000) pro ukládání binárních dat (souborů, obrázků, atp.)
- VARBINARY(n) - datový typ s variabilní délkou, kde n udává maximální kapacitu v bytech (rozsah opět 1 až 8000) - stejně jako u VARCHAR lze použít klíčové slovo MAX, které zaručí nastavení maximálního počtu bytů na 2^31-1
- IMAGE - místo tohoto datového typu se doporučuje používat VARBINARY(MAX)
CLR Data Types – datové typy importované z knihoven .NET
CLR (Common Language Runtime) je způsob jak využívat knihoven .NETu přímo v SQL Serveru. Tato možnost je tu již od SQL Server 2005, ale až ve verzi 2008 přišel Microsoft se svým prvním oficiálním typem zaintegrovaným přímo do SQL Serveru – hierarchyid.
- HIERARCHYID
– uchovává hierarchickou adresu v binární podobě (například /1/14/67.3/24/). Výhodou je možnost binárního třídění a optimalizací prohledávání. Tento typ elegantním způsobem řeší problémy se zápisem hierarchické struktury v databázích a rozhodně si proto zaslouží vlastní článek.
Spatial Data Types – prostorové datové typy
Slouží pro uchování geometrických a geografických objektů (poloh, čar, polygonů). Jsou novinkou v SQL Serveru 2008.
- GEOMETRY
- dokáže uchovávat pozice a geometrické obrazce na rovném souřadnicovém systému - GEOGRAPHY
- slouží (podobně jako GEOMETRY) pro uchovávání pozice a geometrických obrazců – tentokrát však na souřadnicovém systému země (mínění, že země je placka snad už pominulo) - navigace v rámci zakřivení povrchu není úplně banální a převody z různých souřadnicových systémů mohou být příjemným usnadněním při práci s mapou
Other data types - ostatní datové typy
Aneb co se jinam nevešlo. Jsou to typy, jejichž využití je tak specifické, že je nelze kategorizovat. Rozhodně se ale nejedná o zbytečné typy.
- CURSOR – reprezentuje dotaz, jehož výsledky můžeme postupně číst přímo v T-SQL jazyce - budu popisovat samostatnou kapitolou, nelze využít jako datový typ sloupce tabulky
- TABLE - slouží k dočasnému uložení datové tabulky (například výstup funkcí a předávání tabulek do procedur) - opět nelze použít jako typ sloupce
- SQL_VARIANT - dokáže obsahovat různé datové typy (BIT, INT, DECIMAL, CHAR, BINARY, NCHAR, UNIQUEIDENTIFIER…) - použitý formát se určuje automaticky podle vstupu. Nedokáže obsahovat velké objekty (typy s označením velikostí MAX), CLR datové typy a uživatelské typy. SQL_VARIANT nedoporučuji používat, pokud máte možnost znát typ dat.
- TIMESTAMP - název mate, protože tento 8mi bytový binární typ datum ani čas neukládá - sloupec typu TIMESTAMP může být v tabulce jen jeden a automaticky se inkrementuje při každém vložení nebo změně řádku - slouží tím pádem pro verzovací účely
- UNIQUEIDENTIFIER - jedná se o 16ti bytový unikátní identifikátor ve tvaru xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, kde každý znak je hexadecimální znak (0-9 nebo A-F) – přes jeho název se může se v rámci řádků tabulky opakovat, pokud unikátnost nevynutíte nějakým omezením – tento lze vygenerovat náhodně funkcí NEWID()
- XML - tento datový typ dokáže ukládat XML struktury a to buď volně nebo podle schématu - dále je možné uložit buď celý XML dokument i s hlavičkou nebo jen jeho část (větev)
Vysvětlení hodnoty MAX u řetězcových a binárních typů
V popisu typů pro uchování řetězců a binárních hodnot jsem uvedl, že v závorce určujeme buď velikost číslem (1-8000 bytů, resp 1-4000 znaků u typů s unicode kódování) nebo slovem MAX, které reprezentuje maximální délku 2^31-1 bytů. Můžete se ptát, proč je tedy určení velikosti omezeno na 8000 bytů, když přitom maximální délka se slovem MAX je v přepočtu 2147483647 bytů.
Důvodem je fyzické ukládání dat. Pokud budete vědět, že text nebo binární pole má menší počet bytů (1 až 8000), uvedeme jeho velikost a SQL Server se dokáže lépe vypořádat s jeho uložením, jelikož se vejde do interně používaných 8kB stránek. Dokáže s maximální velikostí plánovat a vnitřně lépe optimalizovat příslušné operace. Oproti tomu větší bloky (8000 bytů +) již SQL Server zpracovává neoptimalizovaným způsobem a je mu v zásadě již jedno, jak veliká data to doopravdy mohou být.
Závěr
Volba správného datového typu a popřípadě jeho velikosti je základ dobře navržené databáze. Není to ani nic složitého, jen se musí člověk trochu zamyslet. Často se totiž setkávám s problémem, že programátoři znají jen pár datových typů a navíc je používají špatně. Nikdo neříká, že se musíte naučit velikosti jednotlivých typů v bytech (nejsme přece ve škole, abychom cpali do hlavy věci násilím). Pouze stačí, když budete mít třeba tento přehled někde po ruce a on se vám pomalu dostane do krve při používání.
Tomáš Jecha již několikátým rokem získal ocenění Microsoft MVP. V současné době pracuje ve společnosti AVAST jako architekt a vývojář interních systémů. Působí také jako lektor a konzultant v počítačové škole Gopas. V současné době se zajímá především o SQL Server a technologie nad .NET Frameworkem 4. Společně s Tomášem Hercegem napsal tento web a stará se o jeho administraci.
Problém s triggery
Datum: 21.1.2010 14:17
Autor: neregistrovaný (146.102.33.19)
Hodnocení autora: není
Příspěvků: 0
Ahoj,
prosimtě potřeboval bych poradit, jak vytvořit trigger, který by kontroloval, aby se do určitého sloupce s názvem např. "je_vedouci" mohla vložit je jedna hodnota jejíž datový typ boolean je true, false se mohou vkládat neomezeně.Zkrátka zajistit, aby každá pobočka měla jen jednoho vedoucího.
Snad je dotaz dost jasný.
Děkuji za případnou odpověď,
Martin S.
K seriálu Stopařův průvodce po databázích
Datum: 21.2.2010 19:12
Autor: neregistrovaný (93.99.142.42)
Hodnocení autora: není
Příspěvků: 0
Ahoj,
měl bych k tomuto seriálu dvě poznámky. Za prvé bych chtěl pochválit styl jakým jsou články psané. Je to opravdu srozumitelné a pochopitelné i pro "svátečního programátora", a prozatím jsem nenarazil na obdobně dobrý web pro začátečníky.
Ta druhá poznámka už tak pozitivní není. Chápu, že se tomuto webu věnujete ve volném čase, myslím si ale, že rozepsat seriál bez jakéhokoliv smysluplného dotažení nějakého celku dokonce a zase rozepsat další je o ničem. Když jsem se v prosinci díval na články a u prvních dvou jsem vyděl datování cca 2 roky staré, tak jsem se u toho dost pozastavil. Nyní, po pár dílech, kdy nastává další blíže nespecifikovaná časová prodleva, si říkám jestli vůbec celý ten seriál má smysl? Když budu odhadovat čas dokončení seriálu z počátečních článků,tak dříve než by tento seriál měl být dokončen se budou používat úplně jiné programovací jazyky, nebo jejich verze.
Promiň to vyznění té druhé poznámky, ale musel jsem to napsat, protože opravdu mne velice mrzí, že tak dobře udělaný seriál je takto useknutý
jakr
Pokračování ?
Datum: 22.4.2010 9:10
Autor: neregistrovaný (93.91.144.178)
Hodnocení autora: není
Příspěvků: 0
Seriál je dobrý a užitečný! Kdy bude pokračování?
S pozdravem, Igor.
pokračování
Datum: 26.7.2011 11:10
Autor: neregistrovaný (83.208.133.180)
Hodnocení autora: není
Příspěvků: 0
Bude pokračování tohoto seriálu?