LINUXSOFT.cz
Username: Password:     
    CZ UK PL

> MySQL (23) - relace 1:N a N:N

Co znamenají zkratky 1:N a N:N? Jak souvisejí se psaním spojení a proč by nestačilo mít jen jeden typ spojení? To všechno se dozvíte v dnešním díle seriálu o MySQL.

3.6.2005 07:00 | Petr Zajíc | read 57438×

DISCUSSION   

Zatím jsme v seriálu rozebírali taková spojení, při nichž šlo o dvě tabulky. Napsal jsem ale rovněž, že principielně lze spojit i více tabulek. Ačkoli to nepředstavuje žádný syntaktický zádrhel, pro začátečníky v oblasti databází bývá někdy problém pochopit logiku takových spojení. Proto se jim dnes budeme trochu věnovat.

Spojení 1:N

Toto spojení jsme vlastně již probrali. Tajemnou zkratkou "1:N" se v databázovém světě rozumí spojení, kde jeden záznam v "hlavní" tabulce obsahuje teoreticky libovolný počet odpovídajících záznamů v "podřízené" tabulce. (Teoreticky libovolný počet zahrnuje rovněž nulu). Připomeňme také, že k vyjádření takového spojení se používá:

  • klauzule LEFT JOIN (nebo RIGHT JOIN) v případě, kdy chceme zobrazit všechny řádky z "hlavní" tabulky bez ohledu na to, zda existují nějaké řádky v "podřízené" tabulce
  • klauzule INNER JOIN v případě, kdy chceme zobrazit pouze řádky v "hlavní" tabulce, které mají nějaké související záznamy v tabulce "podřízené"

V praxi existuje celá řada situací, na níž lze toto schéma uplatnit. Pro osvěžení si některá připomeňme:

  • Jedna faktura může mít celou řadu položek ("hlavní" tabulka obsahuje záhlaví faktury, "podřízená" obsahuje položky)
  • Jedna síť může obsahovat řadu počítačů ("hlavní" tabulka obsahuje seznam sítí, "podřízená" obsahuje seznam počítačů v těchto sítích)
  • Jeden zaměstnanec se může starat o řadu zákazníků ("hlavní" tabulka obsahuje seznam zaměstnanců, "podřízená" obsahuje seznam zákazníků)

Celá situace se dá poměrně snadno znázornit graficky. Na obrázku níže můžete vidět, jak by vyladalo spojení mezi tabulkou faktur a jejich položek.

Kdybychom něco takového chtěli zapsat pomocí SQL, nebude to problém:

select * from faktury join polozky on faktury.id = polozky.faktura;

Spojení N:N

Co je špatného na modelu 1:N, že potřebujeme vymyšlet něco dalšího? Na modelu samotném není špatného nic. Problém spočívá v tom, že pro reálný svět tento model zkrátka nepostačuje. Vraťme se na chvíli k naší imaginární databázové aplikaci, která má mapovat provoz v knihovně. Jak byste zmapovali proces půjčování knih? Je pravda, že jeden čtenář si může půjčit více knih, ALE zároveň je pravda, že více čtenářů si může půjčit stejnou knihu (dejme tomu v různém období). Vztah mezi knihami a čtenáři tedy není 1:N, ale N:N.

Realizovat něco takového pomocí dvou tabulek v reálné databázi většinou nejde. Takový vztah se obyčejně programuje pomocí další, třetí tabulky, která je spojena s oběma původními tabulkami. S každou tabulkou má vztah 1:N a celé to dokáže simulovat spojení N:N. Protože se to asi dá jen těžko představit, posloužím zase malým obrázkem:

Je dobré si "prostřední" tabulku nějak smysluplně nazvat, i když to někdy nebude tak úplně jednoduché. My bychom si ji mohli nazvat například "výpůjčky". Z toho je krásně vidět, jak je relace N:N "rozbita" na dvě relace 1:N. Platí totiž:

  • mnoho různých čtenářů si může půjčit mnoho různých knih (N:N)
  • jedna kniha může být půjčena mnohokrát (1:N mezi knihami a výpůjčkami)
  • jeden čtenář může přijít do knihovny vícekrát za život a něco si půjčit (1:N mezi čtenáři a výpůjčkami)

V praxi to často bývá tak, že "prostřední" tabulka neslouží pouze jako technický prostředek k realizaci spojení N:N, ale že obsahuje i nějaké smysluplné informace. Například si dokážu představit, že by tabulka výpůjček docela dobře mohla obsahovat datum půjčení a datum vrácení každé publikace. To totiž nepatří logicky ani do tabulky knih, ani do tabulky čtenářů.

Pozn.: Vidíte mimochodem, jak nesmírně je toto řešení pružné? Umožňuje například postihnout situaci, kdy čtenář nevrátí všechny knihy, které má půjčené ve stejném termínu. Protože pro každou kombinaci kniha-čtenář existuje řádek v tabulce výpůjček, lze to pohodlně zapsat.

V praxi bychom tedy mohli pomocí výše uvedené průpravy například sestavit seznam právě vypůjčených knih:

select knihy.nazev, ctenari.prijmeni from
knihy join vypujcky on knihy.id = vypujcky.kniha
join ctenari on vypujcky.ctenar = ctenari.id
where vypujcky.vracenodne is null;

Poznámky ke spojením

Zejména spojení N:N vyžadují určitou představivost ze strany programátora. Během let, kdy jsem programoval databázové aplikace, jsem si sestavil několik tipů, které se vám možná také budou hodit:

  • Změnit relaci 1:N na N:N v pozdější fázi vývoje může být docela problém. Je lepší pečlivě si promyslet návrh databáze, než ji začnete tvořit.
  • Mnoho spojení N:N samozřejmě znamená zvýšení obemu dat v databázi a zároveň snížení výkonu. Umožňuje však ukládat data pružně a do určité míry reagovat na změny v logice uložení dat. Výhody a nevýhody jsou jak už to bývá protichůdné, takže je třeba pečlivě vybírat.
  • Jestliže nevíte, zda bude mezi dvěma tabulkami vztah 1:N nebo N:N, stop! Je to důležité a obyčejně je to třeba hned promyslet. Leckdy se problém dá převést z počítačové řeči do jazyka, jimž mluví zákazník (třeba čeština ;-)))) a zeptat se.
  • Hotová katastrofa vznikne, když se programátor snaží pomocí 1:N a N:N relací popsat procesy, jejichž toku dostatečně nerozumí (může se jednat například o aplikaci skladového hospodářství se složitým způsobem kompletace výrobků). Nezřídka je pak nutné celý návrh zahodit a začít znovu, pozor na to.
  • Jestliže máte duplicitní údaje ve dvou tabulkách, které spolu jsou v relaci 1:N, možná že měly být v relaci N:N. Možná je čas to předělat, i když to bude složité. Do budoucna to může ušetřit čas, výkon a náklady.
 

DISCUSSION

For this item is no comments.

Add comment is possible for logged registered users.
> Search Software
> Search Google
1. Pacman linux
Download: 4879x
2. FreeBSD
Download: 9067x
3. PCLinuxOS-2010
Download: 8564x
4. alcolix
Download: 10949x
5. Onebase Linux
Download: 9661x
6. Novell Linux Desktop
Download: 0x
7. KateOS
Download: 6245x

1. xinetd
Download: 2413x
2. RDGS
Download: 937x
3. spkg
Download: 4761x
4. LinPacker
Download: 9967x
5. VFU File Manager
Download: 3199x
6. LeftHand Mała Księgowość
Download: 7203x
7. MISU pyFotoResize
Download: 2809x
8. Lefthand CRM
Download: 3563x
9. MetadataExtractor
Download: 0x
10. RCP100
Download: 3121x
11. Predaj softveru
Download: 0x
12. MSH Free Autoresponder
Download: 0x
©Pavel Kysilka - 2003-2024 | mailatlinuxsoft.cz | Design: www.megadesign.cz