🧹 Normalizace (1NF–3NF)

Uklizená tabulka

O čem to je

Trenér vede docházku do kroužků v jedné velké tabulce. U každého zápisu opisuje jméno žáka, jeho třídu, název kroužku i jméno vedoucího. Když vedoucí kroužku změní příjmení, musí ho přepsat na sto řádcích. Jeden přehlédne a tabulka si začne odporovat.

Normalizace je postup, jak takovou tabulku rozdělit na menší, aby se každý údaj ukládal jen jednou. Postupuje se po stupních, kterým se říká normální formy: 1NF, 2NF, 3NF.

Nové pojmy

RedundanceZbytečné opakování stejného údaje v databázi.Jméno vedoucího kroužku uložené u každého žáka.
AnomálieProblém, který redundance způsobuje. Aktualizační: údaj musíš měnit na mnoha místech. Vkládací: nejde vložit údaj bez jiného (nový kroužek bez žáka). Mazací: smazáním jednoho údaje zmizí i jiný (poslední žák odejde a ztratí se i vedoucí kroužku).Změna příjmení vedoucího na sto řádcích.
Atomická hodnotaHodnota, kterou už dál nedělíme, protože s jejími částmi nepotřebujeme pracovat zvlášť.Jedno telefonní číslo v buňce. Ne „777 111 222, 603 333 444“.
Funkční závislost A → BHodnota A jednoznačně určuje hodnotu B. Když znáš A, znáš i B.id_zaka → jmeno: číslo žáka určuje jeho jméno.
Primární klíčSloupec nebo skupina sloupců, která jednoznačně určuje řádek. Skupině se říká složený klíč.Docházka: (id_zaka, id_krouzku).

Tři normální formy

FormaPodmínkaZkráceně
1NFvšechny hodnoty jsou atomické, žádné seznamy v buňce ani opakující se sloupce (tel1, tel2, tel3), tabulka má primární klíčjedna buňka = jedna hodnota
2NFje v 1NF a každý neklíčový sloupec závisí na celém primárním klíči, ne jen na jeho částižádná částečná závislost
3NFje v 2NF a žádný neklíčový sloupec nezávisí na jiném neklíčovém sloupcižádná tranzitivní závislost

Starý pomocný výrok to shrnuje: každý neklíčový sloupec závisí „na klíči (1NF), na celém klíči (2NF) a na ničem jiném než na klíči (3NF)“.

Příklad: 1NF

id_zakajmenotelefony
1Eva Malá777 111 222, 603 333 444
Uveď tabulku výše do 1NF.
Buňka telefony obsahuje seznam a jmeno spojuje jméno a příjmení. Rozdělíš jmeno na jmeno a prijmeni a telefony dáš do samostatné tabulky telefon(id_zaka, cislo), jeden telefon na řádek. Teď je každá hodnota atomická.
Tabulka dochazka(id_zaka, id_krouzku, jmeno_zaka, nazev_krouzku, datum_prihlaseni) s klíčem (id_zaka, id_krouzku). Je v 2NF?
Ne. jmeno_zaka závisí jen na id_zaka a nazev_krouzku jen na id_krouzku, tedy na části klíče. Rozděl na zak(id_zaka, jmeno_zaka), krouzek(id_krouzku, nazev_krouzku) a dochazka(id_zaka, id_krouzku, datum_prihlaseni). Datum závisí na celém klíči, zůstává.
✗Tabulka s jednoduchým (jednosloupcovým) primárním klíčem může porušit 2NF.
✓Je-li tabulka v 1NF a má jednoduchý primární klíč, je automaticky v 2NF.

Částečná závislost znamená závislost na části klíče. Klíč z jednoho sloupce žádnou část nemá.

Normalizace odstraňuje redundanci a anomálie. 1NF: atomické hodnoty. 2NF: neklíčové sloupce závisí na celém klíči. 3NF: neklíčové sloupce nezávisí na jiných neklíčových sloupcích.

Krok za krokem

O čem to je

Malý e-shop si zapisuje objednávky do jedné tabulky v tabulkovém procesoru. Funguje to, dokud má deset objednávek. Pak zákazník změní adresu, zboží zdraží a v tabulce vznikne chaos. Projdeme normalizaci této tabulky krok za krokem, jako u maturitní úlohy.

Cílem je, aby každý údaj byl uložený jen jednou a změna se dělala na jediném místě.

Nové pojmy

NormalizacePostupné rozdělování tabulek podle pravidel (normálních forem) tak, aby se údaje neopakovaly a nevznikaly anomálie.Jedna tabulka objednávek → čtyři menší tabulky.
Funkční závislost A → BKdyž znáš hodnotu A, znáš jednoznačně i B.id_zbozi → nazev_zbozi
Částečná závislostNeklíčový sloupec závisí jen na části složeného primárního klíče. Porušuje 2NF.datum závisí jen na cislo_obj, ne na dvojici (cislo_obj, id_zbozi).
Tranzitivní závislostNeklíčový sloupec závisí na klíči jen přes jiný neklíčový sloupec: klíč → X → Y. Porušuje 3NF.cislo_obj → id_zakaznika → mesto

Výchozí tabulka

Tabulka objednavky je v 1NF (hodnoty jsou atomické, každá položka objednávky má svůj řádek). Primární klíč je složený: (cislo_obj, id_zbozi).

cislo_objdatumid_zakaznikajmenomestoid_zbozinazevcenamnozstvi
5013. 9.7Eva MaláBrno12hrnek1202
5013. 9.7Eva MaláBrno15tričko3501
5024. 9.9Petr NovákZlín12hrnek1205

Postup

Najdi závislosti. cislo_obj → datum, id_zakaznika. id_zbozi → nazev, cena. id_zakaznika → jmeno, mesto. (cislo_obj, id_zbozi) → mnozstvi.
2NF: odstraň částečné závislosti. Co závisí jen na cislo_obj, dej do tabulky objednavka. Co závisí jen na id_zbozi, dej do tabulky zbozi. V původní tabulce polozka zůstane jen to, co závisí na celém klíči: mnozstvi.
3NF: odstraň tranzitivní závislosti. V tabulce objednavka závisí jmeno a mesto na id_zakaznika, ne přímo na cislo_obj. Přesuň je do tabulky zakaznik.
Zkontroluj. Každý údaj je uložený jednou a tabulky jsou propojené cizími klíči.
Tabulka po 3NFSloupce (PK tučně)
zakaznikid_zakaznika, jmeno, mesto
objednavkacislo_obj, datum, id_zakaznika (FK)
zboziid_zbozi, nazev, cena
polozkacislo_obj (FK), id_zbozi (FK), mnozstvi
Které anomálie měla výchozí tabulka?
Aktualizační: zdražení hrnku se musí přepsat na všech řádcích s hrnkem. Vkládací: nové zboží nejde vložit, dokud si ho někdo neobjedná (chybí cislo_obj, část klíče). Mazací: smazáním objednávky 502 zmizí i jediný záznam o Petru Novákovi.
Tabulka zak(id_zaka, jmeno, psc, obec). Platí psc → obec. Je v 3NF?
Pro tento příklad předpokládáme, že PSČ určuje obec. Pak ne: id_zaka → psc → obec je tranzitivní závislost. Rozděl na zak(id_zaka, jmeno, psc) a psc(psc, obec). (Ve skutečnosti jedno PSČ může patřit více obcím, proto se v praxi takto rozděluje opatrně.)
✗Čím víc tabulek, tím lépe. Rozdělím i jméno a příjmení do dvou tabulek.
✓Rozděluj jen podle závislostí: dokud všechny neklíčové sloupce závisí přímo na celém klíči, tabulka je v 3NF a dál ji dělit netřeba.

Zbytečně rozdělené tabulky jen zpomalují dotazy (víc spojování) a nic nepřinesou.

Postup: najdi funkční závislosti, pro 2NF odstraň závislosti na části klíče, pro 3NF závislosti mezi neklíčovými sloupci. Výsledné tabulky propoj cizími klíči.