Třetí normální forma

Třetí normální forma (3NF) je soubor doporučení (metodika) pro návrh datové struktury databáze, jehož dodržení vede k optimálnímu využití vlastností systému OLTP při tvorbě databázových aplikací. 3NF obsahuje jako svou podmnožinu druhou normální formu (2NF) a první normální formu (1NF):

  1. Eliminuj duplicitní sloupce v jednotlivých tabulkách.
  2. Pro každou skupinu dat s jasně vymezeným významem vytvoř zvláštní tabulku, každý řádek opatři unikátním primárním klíčem.
  3. Obsahem jednotlivých sloupců tabulky by měla být jednoduchá, dále nedělitelná informace.
  4. Podmnožinu dat se shodnou hodnotou pro určitý sloupec tabulky převeď do samostatné tabulky a spoj s původní tabulkou cizím klíčem.
  5. Odstraň z tabulky sloupce, které jsou přímo závislé na jiné skupině sloupců tabulky než pouze na primárním klíči.

Tak, jak jsou zde zapsány, působí jednotlivá doporučení velice obecně a (alespoň pro toho, kdo již někdy nějakou databázovou strukturu navrhoval) v podstatě samozřejmě. Pokusme se demonstrovat jejich použití na jednoduchém příkladu:

Příklad

Zadání: Navrhněte datovou strukturu (tabulku nebo skupinu tabulek) pro uložení seznamu oddělení firmy, který bude obsahovat číslo oddělení, adresu budovy, kde oddělení sídlí, jméno, příjmení a plat šéfa a jméno, příjmení a plat všech zaměstnanců oddělení.

První pokus o řešení

Vytvořím si jednu tabulku Oddělení, která bude obsahovat následující sloupce:

  • číslo oddělení
  • adresa budovy
  • jméno, příjmení a plat šéfa
  • jméno, příjmení a plat prvního zaměstnance
  • jméno, příjmení a plat druhého zaměstnance
  • jméno, příjmení a plat třetího zaměstnance
  • … a tak dále podle toho, kolik má zaměstnanců největší oddělení ve firmě

Moc hezké, ale zkuste v této struktuře napsat příkaz SELECT, který vybere deset nejlépe placených zaměstnanců. Nebo třeba SELECT, který vybere oddělení s více než deseti zaměstnanci.
Tato struktura rozhodně nesplňuje bod 3 z výše uvedených doporučení – adresa by měla být rozdělena na ulici, město, PSČ a stát a pro každého zaměstnance by mělo být uvedeno zvlášť jméno, zvlášť příjmení a zvlášť plat.
Tato struktura také rozhodně nesplňuje bod 2 – jsou zde dohromady v jedné tabulce smíchány údaje o lidech a o odděleních.

Druhý pokus o řešení

Vytvořím dvě tabulky:

Tabulka Oddělení:

  • číslo oddělení (primární klíč)
  • adresa budovy – ulice
  • adresa budovy – číslo
  • adresa budovy – město
  • adresa budovy – PSČ
  • adresa budovy – stát
  • ID šéfa (cizí klíč do tabulky Lidé)

Tabulka Lidé:

  • ID člověka (primární klíč – uměle vytvořené zaměstnanecké číslo, žádný z existujících sloupců ani jejich skupinu nemohu použít jako primární klíč, neboť ve firmě mohou existovat dva Josefové Novákové pracující ve stejném oddělení za stejný plat)
  • jméno
  • příjmení
  • plat
  • číslo oddělení (cizí klíč do tabulky Oddělení)

Už je to o něco lepší – rozhodně už dokážu pomocí SQL příkazu najít nejlépe placené zaměstnance nebo zjistit počet zaměstnanců jednotlivých oddělení. Problém je ještě v doporučení číslo 4 v případě tabulky Oddělení – firma bude nejspíš mít hodně oddělení, ale málo budov (možná dokonce jenom jednu), rozhodně bude hodně oddělení sedět vždy ve stejné budově. V tabulce Oddělení se mi tedy bude pořád dokola opakovat několik málo adres budov. Správně by tedy měly být adresové sloupce vyvedeny do zvláštní tabulky.

Třetí pokus o řešení

Vytvořím tři tabulky:

Tabulka Oddělení:

Tabulka Lidé:

Tabulka Budovy:

  • ID budovy (primární klíč – uměle vytvořené pořadové číslo budovy)
  • adresa budovy – ulice
  • adresa budovy – číslo
  • adresa budovy – město
  • adresa budovy – PSČ
  • adresa budovy – stát

To už vypadá docela dobře. Dalo by se diskutovat o tom, jestli číslo oddělení je opravdu vhodný primární klíč, co se stane, když dojde k přečíslování oddělení, nebo třeba o tom, že podle PSČ a státu dokážu určit město, takže podle doporučení 5 je položka adresa budovy – město vlastně přebytečná, ale v zásadě jsme se díky pravidlům 3NF dostali ke struktuře, se kterou by nemělo být složité pracovat pomocí příkazů jazyka SQL.

Externí odkazy