Normalizace

Normalizace je proces organizování dat v databázi. Představte si to jako úklid skříně – chceme, aby každá věc měla své logické místo a nic jsme neměli dvakrát.

Hlavní cíle normalizace:

Celá normalizace se bude týkat vždy závislostí mezi atributy jedné relace, kterou, identifikujeme-li problém, budeme rozdělovat. Pojďme se tedy nyní ponořit do pojmů týkajících se závislostí mezi atributy.

Závislosti atributů

Abychom vůbec mohli přistoupit k normalizaci, musíme nejprve pochopit vztahy mezi jednotlivými atributy v relaci.

Funkční závislost

Pokud znám hodnotu A, znám jednoznačně i hodnotu B. A → B

Říkáme, že B vyplývá z A (pozor nikoliv obráceně) nebo A určuje B.

Příklad: představme si pod A rodné číslo, pod B jméno. Jestliže známe A, jednoznačně nám z něj vyplývá B, tj. například z rodného čísla 0712152101 nám jednoznačně vyplyne Antonín.

Plná funkční závislost

Týká se situace, když klíč (A) je složený (z více atributů).

Atribut B závisí na celém klíči A, nikoliv pouze na jeho části. (A1, A2) → B

Příklad: představme si klíč složený z částí StudentID (A1) a Předmět (A2) – pak z něj můžeme vyvodit hodnocení na konci roku (B). Jestliže známe konkrétního studenta, například 2023C23 a předmět DEJ, můžeme z něj vyvodit známku 2.
Naopak z tohoto klíče nemůžeme odvodit název předmětu, protože ten závisí pouze na A2, nejedná se tedy o plnou funkční závislost.

Částečná funkční závislost

Týká se opět situace, kdy klíč (A) je složený (z více atributů).

Atribut B závisí pouze na části klíče A, nikoliv na celém složeném klíči. A1 → B, resp. A2 → B

Příklad: představme si klíč složený z částí StudentID (A1) a Předmět (A2) – pak z něj můžeme vyvodit hodnocení na konci roku (B). Jestliže známe konkrétního studenta, například 2023C23 a předmět DEJ, můžeme z A1 vyvodit například jméno studenta nebo jeho příjmení, z A2 pak například název předmětu nebo hodinovou dotaci.

Tranzitivní závislost

Jestliže A určuje B a B určuje C, pak A tranzitivně určuje C. A → B ∧ B → C ⇒ A → C

Příklad: představme si ObjednavkaID jako A, ZakaznikID jako B a Mesto jako C. Můžeme říct, že z A jednoznačně vyplývá B, protože každou objednávku udělal vždy jeden konkrétní zákazník. Také můžeme říct, že z B jednoznačně vyplývá C, protože zákazník má jednoznačně stanovené město, kam objednávku doručit. V tom případě můžeme říct, že z objednávky (A) můžeme vyvodit město doručení (C) – nikoliv sice napřímo, ale tranzitivně (přes prostředníka).

Vícehodnotová závislost

Týká se situace, kdy klíč (A) je složený ze třech nebo více atributů.

Vícehodnotová závislost nastává, když jeden klíčový atribut (A1) určuje více hodnot u dvou jiných atributů (A2 a A3), přičemž A2 a A3 jsou na sobě vzájemně nezávislé.

Lidsky řečeno – v rámci klíče nemíchejme hrušky s jablky.

Příklad: Představme si relaci, kde primární klíč je složený z atributů (Student, Project, Hobby). Můžeme si představit i konkrétní hodnoty – student Lohnický pracuje na projektu Web Mlsná Koza a na projektu MongoDB. Jako koníčky má šachy a pěší turistiku. Abychom to vše v jedné relaci zachytili, museli bychom to ale zkombinovat:

StudentProjectHobby
LohnickýWeb Mlsná Kozašachy
LohnickýWeb Mlsná Kozapěší turistika
LohnickýMongoDBšachy
LohnickýMongoDBpěší turistika

Atributy Project (A2) a Hobby (A3) spolu totiž nesouvisejí – nemůžeme říct, že všichni, kteří pracují na projektu Web Mlsná Koza mají jako koníček šachy a z projektu MongoDB vyplývá jednoznačně pěší turistika. Abychom to tedy zachytili do jedné relace, museli jsme udělat kartézský součin všech možných hodnot. Teď si představte, že velmi aktivní student Lohnický se přihlásí do dalšího projektu nebo se začne věnovat dalšímu koníčku. Ufff.

Normální formy

Máme celkem 6 normálních forem:

přičemž platí, že relace je v dané normální formě, jestliže je již ve všech předchozích normálních formách.

Zdroj: Notebook LM na základě této webové stránky.

První normální forma

Relace je v 1. NF, jestliže každý atribut v relaci představuje jedinečný typ informace.

Toto pravidlo může trochu připomínat podmínku relačnosti ohledně elementárnosti jednotlivých hodnot. Například není možné mít několik lidí vypsaných v jednom atributu Absolventi. Není možné napsat několik hodnot do jednoho atributu Složení. Není možné napsat ulici, číslo popisné, město a PSČ do jednoho atributu Adresa.

Tato relace například nesplňuje první normální formu:

#RCNameCellphone
9802014345Jiří Novák607 524 978
0211039850Václav Kolenatý602 334 694
0351120049Emílie Vopršálková608 748 333
607 220 449
0201239590Miloslav Chlupatý608 443 323
602 937 410

Vidíme totiž hned několik chyb:

Aby relace splnila 1. NF, musíme relaci rozdělit minimálně na dvě:

#RCFirstNameLastName
9802014345JiříNovák
0211039850VáclavKolenatý
0351120049EmílieVopršálková
0201239590MiloslavChlupatý
#ContactIDRC (FK)CellPhone
19802014345607 524 978
20211039850602 334 694
30351120049608 748 333
40351120049607 220 449
50201239590608 443 323
60201239590602 937 410

Druhá normální forma

Relace je v druhé normální formě, jestliže je v první normální formě a všechny neklíčové atributy v relaci závisí na celém primárním klíči (v relaci nemáme žádnou částečnou funkční závislost).

Například tato relace nesplňuje druhou normální formu:

#Subject#YearTeacherSubject_Name
WBD2025NěmecWebdesign
DBS2025LelovskiDatabáze
WBD2026SvobodaWebdesign
DBS2026NěmecDatabáze

Rozdělíme si nejprve atributy relace na klíčové a neklíčové:

Nyní se ptáme u všech neklíčových atributech, na jakých klíčových atributech závisejí:

Pro splnění druhé normální formy je tedy nutné relaci rozdělit nejméně na dvě:

#Subject#YearTeacher
WBD2025Němec
DBS2026Lelovski
WBD2025Svoboda
DBS2026Němec
#SubjectSubject_Name
WBDWebdesign
DBSDatabáze

Rozdělením jsme dokonce ušetřili místo (odstranili redundanci), protože název předmětu máme uložený pouze jedenkráte.

Třetí normální forma

Relace je ve třetí normální formě, jestliže je ve druhé normální formě a všechny její neklíčové atributy závisí pouze na klíčových atributech a nikoliv mezi sebou (relace v sobě nemá tranzitivní závislost).

Například tato relace nesplňuje třetí normální formu:

#FilmIDZanrIDZanrNazev_FilmuDelka
11DokumentárníApollo 1193
25AkčníLost Bullet92
35AkčníOld Guard: Nesmrtelní125
41DokumentárníThis is it113

Nyní procházíme jeden atribut za druhým a ověřujeme, že závisí výlučně na primárním klíči:

Aby relace splňovala třetí normální formu, je tedy nutné ji rozdělit minimálně na dvě relace:

#FilmIDZanrID (FK)Nazev_FilmuDelka
11Apollo 1193
25Lost Bullet92
35Old Guard: Nesmrtelní125
41This is it113
#ZanrIDZanr
1Dokumentární
5Akční

Boyce-Coddovo pravidlo

Relace je v BCNF, jestliže je ve 3. NF a cokoliv něco určuje, musí být klíčem.

Pojďme si opět ukázat problematickou relaci, která je ve 3. NF, ale nikoliv v BCNF:

CourtStart TimeEnd TimeRate Type
109:3010:30SAVER
111:0012:00SAVER
114:0015:30STANDARD
210:0011:30PREMIUM-B
211:3013:30PREMIUM-B
215:0016:30PREMIUM-A

Můžeme říci, že platí:

Poslední závislost je ale nesprávná, protože nemůžeme odvodit Court z Rate Type – Rate Type není klíč.

Abychom tedy relaci opravili, je potřeba ji rozdělit do dvou:

#Rate TypeCourt
SAVER1
STANDARD1
PREMIUM-A2
PREMIUM-B2
#Rate Type#Start TimeEnd Time
SAVER09:3010:30
SAVER11:0012:00
STANDARD14:0015:30
PREMIUM-B10:0011:30
PREMIUM-B11:3013:30
PREMIUM-A15:0016:30

Čtvrtá normální forma

Relace je ve 4. NF, jestliže je v BCNF a její složený primární klíč není tvořen z nezávislých atributů (v klíčových atributech nesmí být vícehodnotová závislost).

Tuto normální formu tedy ověřujeme pouze v případě, že primární klíč je tvořen třema a více atributy.

Například tato relace není ve 4. NF:

#IDStudent#IDCollege#IDHobby
01FAVFotbal
01FPEChess
01FELStrategyGames
02FAVStrategyGames

Pojďme prozkoumat jednotlivé dvojice klíčových atributů, zda-li spolu souvisejí:

Vícehodnotovou závislost tedy odstraníme rozdělením relace:

#IDStudent#IDCollege
01FAV
01FPE
01FEL
02FAV
#IDStudent#IDHobby
01Fotbal
01Chess
01StrategyGames
02StrategyGames

Pátá normální forma

Relace je v 5. NF, pokud je ve 4. NF a dále již nelze bezztrátově rozložit.

Představme si opět relaci, která má složený klíč (minimálně ze třech atributů):

#Supplier#Customer#Part
S1AUDIVolant
S1VWSedačka
S2AUDIVolant
S2VWVolant

V této relaci vidíme tři atributy, které tvoří primární klíč. Mohli bychom si je představit také jako tři dvojice:

Pojďme tedy zkusit tuto relaci rozložit na tři relace podle těchto dvojic:

#Supplier#Customer
S1AUDI
S1VW
S2AUDI
S2VW
#Supplier#Part
S1Volant
S1Sedačka
S2Volant
#Customer#Part
AUDIVolant
VWSedačka
VWVolant

Nyní si zkusíme tyto tři relace opětovně složit dohromady. Dostaneme:

#Supplier#Customer#Part
S1AUDIVolant
S1VWSedačka
S1VWVolant
S2AUDIVolant
S2VWVolant

Ale pozor! Dostali jsme o jeden záznam více – S1 dodává VW, S1 vyrábí volanty a VW nakupuje volanty – čili všechny tři dvojice záznamů jsme z rozložených relací dostali – přesto podle původní relace vidíme, že VW od S1 volanty nenakupuje. Složením rozložených relací jsme tedy získali tzv. Ghost record (falešný záznam) (v tabulce výše červeně).

Tím jsme dokázali, že původní relaci již nelze dále bezztrátově rozložit, a tudíž původní relace již byla v 5. NF.