Byla nebyla početná skupina programátorů, kteří alespoň jednou za život využili databázi. Ale nemalá část z nich dokáže pracovat jen s velmi omezenou škálou funkcionality, co nabízí. Často ani neví, že mohou použít nějaké uložené procedury nebo transakce. A když už to ví, tak často neví jak je správně použít a jaké jsou všechny možnosti a výjimky. Když se pak někdo takový pokusí sestavit větší systém založený na databázích, v práci se nakonec zamotá. Celé to pak může být děravé a nemalou část času tráví ošetřováním nejrůznějších problémů. Jenže při správném návrhu můžete prakticky úplně zamezit, aby se do databáze uložilo něco špatně. Proto jsem se rozhodl napsat tento seriál o Microsoft SQL Serveru. Rád bych na rozdíl od jiných článků zašel do hloubky a popsal i složitější vychytávky, které mohou ve výsledku o dost usnadnit práci. I to jest důvodem, proč budu popisovat problémy spíš z pohledu databázového specialisty než programátora. Navíc nechci vysvětlovat věci jen teoreticky, budu uvádět příklady, kde se popisované funkce dají využít. Dotazy rád odpovím, pokud na to budou mé schopnosti stačit.
Databáze obecně
Tento kus článku je pro opravdové začátečníky, takže kdo už s nějakou databází někdy pracoval, může ho s klidem v duši přeskočit.
Databáze není nic jiného než úložiště na data. I jednoduchý soubor s odřádkovaným textem je vlastně databáze. A kus kódu, který ho parsuje je vlastně databázový systém. U menších projektů můžete občas váhat zda použít řešení podobné textovému souboru nebo velký databázový server. Patrně tušíte, že zde bude rozdíl v robustnosti výsledného řešení. Přeci jenom SQL Server budovaný početnou skupinou profesionálů několik dlouhých let v porovnání s vlastním systémem ukládání, který si napíšete za 5 minut bude nabízet o něco komplexnější služby. Tím nechci říkat, že nasadit těžký server musí být vždy lepší, ale pokud budujete něco většího, určitě se vyplatí zvážit jeho výhody:
- řešení několikanásobného přístupu - zkuste si zapsat 5x vedle sebe do jednoho souboru a máte skoro jistotu, že se program sesype. V databázích můžete ty kolize při dobrém návrhu velmi elegantně řešit.
- několik možných druhů přístupů - přistupujte si do databáze ze sítě, či z internetu přes TCP/IP nebo z lokálního stroje přes sdílenou paměť - je čistě na vás, co vám zrovna vyhovuje
- bezpečnostní politika - disponují silnou bezpečnostní politikou, která umožní dobře aplikace zabezpečit a omezit přístup škůdcům
- zvládá větší objemy dat - databáze jsou navržené aby zvládaly procházet a modifikovat i velké množství dat ve velmi krátkém čase (psát ručně indexování, stránkování a binárně optimalizované ukládání je pro běžného smrtelníka velmi optížné)
- SQL jazyk - dává nám možnost snadno řešit nejrůznější třídění, prohledávání, spojování atp.
Když to všechno sečteme, nabízí nám SQL Server robustní řešení ukládání dat. I proto jsou dnes databáze nezastupitelným prvkem při budování většiny aplikací a to jak desktopovým, internetových i mobilních.
Databázový systém
Databázový systém je zkráceným synonymem pro systém řízení báze dat (DBMS). Jedná se o softwarový produkt, který má na starosti řešit komunikaci mezi softwarem a fyzicky uloženými daty. Má zajistit jistou úroveň abstrakce a poskytnout nám více, či méně efektivní možnosti pro ukládání dat a udržení jejich integrity. Celý tento seriál se bude snažit vysvětlil právě postupy sloužící k úspěšnému udržení databáze v přijatelném stavu. Za přijatelný stav považuji:
- Přístup k datům je v rámci možností rychlý
- Data neobsahují odkazy na neexistující položky
- Logika ukládání dat se udržuje přímo v databázi
- Celá databáze dodržuje jednotné konvence pro pojmenování objektů
Dnešní databázové systémy by měli nabízet především tyto funkce
- Zajištění integrity dat i po nečekaném vypnutí systému (výpadek proudu, pád systému)
- Udržení dat podle definovaných struktur
- Možnost využívat transakčního přístupu k atomickým operacím (buď se provede vše nebo nic)
- Zabezpečení (autentizace a autorizace)
- Model pro řešení konkurenčního přístupu k datům
- Jazyk (primárně SQL) pro ovládání databáze
- Uložené procedury, funkce a triggery – kusy SQL jazyka zajištující úkony s databází a reagující na změnu stavů databáze
- Vazby mezi tabulkami a jednoznačná identifikace záznamů v tabulkách
- Indexy nad sloupci tabulek a zajištění unikátní hodnoty řádků
- … další funkce - každý ze systémů se snaží implementovat vlastní rozšíření
Pro ukázku uvádím několik dnes známých databázových systémů:
- Microsoft SQL Server
- MySQL
- Oracle
- Firebird
- PostgreSQL
- Microsoft Access
V tomto seriálu se budu zabývat pouze jedním z nich. A to Microsoft SQL Serveru.
Typy databází podle struktury dat
Plochá (flat) databáze
Nejzákladnějším typem databáze je databáze plochá (flat). Ta uchovává data jako obyčejnou sadu záznamů. Ukázkou takového typu databáze může být obyčejný textový CSV soubor. Ten na jednotlivých řádcích uchovává jednotlivé záznamy. Každý řádek je pak ještě rozdělen na sloupce pomocí oddělovačů. Důležitým rysem flat databází je, že tento typ neobsahuje vazby na jiné záznamy. Jedná se čistě o sadu záznamů. Využitelnost ploché databáze je ideální jen pro nejzákladnější ukládání seznamů. Tento typ lze samozřejmě implementovat i v rámci komplexnějších typů databází o kterých se dočtete v dalších odstavcích.
Hierarchické a síťové databáze
Dále popíšu 2 typy databází, které bych označil za předchůdce databází využívaných dnes. Bude to tedy spíše teoretický náhled na věci již nepoužívané a proto není 100% nutné správně chápat nebo vůbec znát do detailů jak fungují. Pokud vás toto téma nezajímají, přeskočte přímo na Relační databáze.
Jedná se o hierarchické databáze a síťové databáze. Prosím neplést termín síťový se síťovým prostředím více počítačů a termín hierarchický s ukládáním hierarchických dat (například pomocí hierarchyid ze SQL Server 2008 – o tom se dočtete v některém z pokračování). Jedná se totiž výhradně o strukturu tabulek a jejich vazeb v těchto typech databází.
Jak hierarchické, tak síťové databáze mají společnou snahu o eliminaci redundantních dat (opakujících se). Příkladem může být seznam studentů ve třídách základní školy. Každý student má jednu třídu, kterou navštěvuje. Ta je definovaná jménem a textovým popisem, kde se ve škole nachází. V ploché databázi by měl mít každý student u sebe sloupce jménoTřídy a umístěníTřídy. To je ale vysoce nepraktické hned z několika důvodů. Za prvé to znamená časté opakovaní stejný dat. Navíc změna názvu nebo umístění třídy se bude muset provést u všech záznamů s příslušnou třídou. Pokud na to zapomeneme, získáme různé interpretace téže třídy. Druhým problémem je získání seznamu tříd. Ten by se musel provádět postupným procházením všech studentů a hledáním odlišných tříd – přeci, co kdyby měl zrovna ten poslední student zapsanou jinou třídu? Zda přichází na řadu hierarchické a síťové databáze. Ty dovolují definovat k jednotlivým tabulkám rodičovské tabulky. Obecně pak platí, že každý záznam v tabulce musí obsahovat odkaz na jeden ze záznamů z hierarchický vyšší tabulky. Pro příklad uvádím strukturu tabulek ve školní databázi:
Hierarchická databáze
Podle této struktury může existovat samostatný seznam zaměstnanců (podobný jako ve flat databázi) a dále samostatný seznam tříd. Tabulka studentů je ale umístěna pod tabulkou tříd, což znamená, že každý student (záznam v tabulce studentů) musí mít odkaz na jeden záznam v tabulce tříd. Tím omezíme redundanci dat, protože každý student obsahuje pouze odkaz na jednu ze třít a zabírá tedy minimum prostoru a navíc jsou třídy definované na jednom místě a každá pouze jednou.
Toto byla ukázka hierarchické databáze. Velmi podobně je na tom i síťová databáze. Ta má navíc však jedno rozšíření - možnost více rodičovských tabulek. Například pokud by měl každý ze studentů možnost zvolit jeden povinný cizí jazyk – student se tedy váže na jednu třídu a jeden jazyk:
Síťová databáze
Relační databáze
Relační databáze jsou dnes nejpoužívanějším typem databází a v zásadě plně nahradili ploché, hierarchické a síťové. Alespoň na poli databázových systémů – stále je pravděpodobné, že použijete například plochou databázi pro uložení jednoduchých dat do souboru, protože je prostě zbytečné instalovat databázový systém pro zajištění pokročilých funkcí.
Relační databáze se poučily z chyb a nedostatků předešlých typů databází. Již nemají rozdělení s kořenovým prvkem a nahlížejí na jednotlivé datové tabulky na stejné úrovni.
Relační databáze může obsahovat libovolný počet tabulek, které slouží právě k ukládání dat (řádků - rows). Tyto řádky musí být ve formátu, který určují předem definované sloupce (columns) tabulky. Takže pokud chceme ukládat například uživatele, vytvoříme do databáze tabulku a přidáme jí 3 sloupce: uživatelské jméno, plné jméno a heslo. Sloupce musí mít unikátní jména, takže například: userName, fullName a password. Když potom vkládáme uživatele, přiřadíme sloupcům hodnoty (například: userName='tomas',fullName='Tomáš Jecha' a password='tajne heslo'). Samozřejmě je řada dalších nastavení a úprav tabulky, které by bylo zapotřebí nastavit (třeba znemožnit duplicitní názvy sloupce userName), ale těmi se budeme zabývat později v článku. Navíc je dobré vytvářet unikátní identifikátory řádků, kterými můžete příslušný záznam identifikovat. Těm říkáme primární klíč – tedy sloupec, který musí obsahovat unikátní hodnotu v rámci všech řádků tabulky. V našem případě by to mohl být právě sloupec s uživatelským jménem.
Dále mohou tabulky v relačních databázích obsahovat takzvané cizí klíče (foreign keys). Ty mají zásadní funkci při návrhu databáze – definují odkaz na primární klíč z jiné (možno i stejné) tabulky. Tím pádem máme možnost přidáním sloupce označeného jako cizí klíč definovat, že každý řádek tabulky se odkazuje na jiný řádek jiné tabulky. O tom ale až v dalším článku, který se cizím klíčům věnuje.
Objektové databáze
Dalším typem databáze (který v tomto seriálu nebudu popisovat) jsou databáze objektové. S nástupem objektově orientovaného programování s objevila myšlenka ukládat data v databázi ve formě objektů. Snad někoho neurazím, když si dovolím vyřknout, že objektové databáze se zatím moc nepoužívají a nejsou také příliš podporovány databázovými systémy. Tím ale rozhodně nechci naznačit neužitečnost, či snad zbytečnost objektového přístupu k databázovým záznamům (entitám). Většina dnešních softwarových projektů pracující s databází reprezentuje data formou datových objektů - tedy přístupem objektovým. Dokonce .NET framework nabízí několik postupů jak reprezentovat data z relační databáze objekty – je to Entity Framework a LINQ2SQL.
Techniky, které vytváří datové objekty schopné korespondovat se záznamy v databázi se nazývají object-relation mapping (zkráceně ORM nebo OR mapping) – vytváříme tedy most objektovým přístupem a relační databází. Jinými slovy se snaží udělat z relační databáze z pohledu programátora objektovou databázi.
Objektová databáze sama o sobě je pak pokus jak nabídnout přímý objektový přístup bez nutnosti použití některého z object-relation mapping. Tyto mappery jsou však dnes na takové úrovni, že většina vývojářů nemá potřebu hledat řešení jakým je například právě objektová databáze.
Závěrem
První díl se zaobíral pouze teoretickou částí databázové problematiky. V dalším díle si představíme databázový systém Microsoft SQL Server, se kterým budeme celý tento seriál pracovat.