
Práce s více tabulkami
Dosud jsme pomocí SQL příkazů pracovali pouze s jednou tabulkou. Databáze jsou však v drtivém počtu tvořeny sadou tabulek, jejichž struktura odpovídá modelované realitě. Tabulky jsou mezi sebou svázané vazbou 1:1 nebo 1:n za pomoci cizích klíčů, viz výuková jednotka Úvod do práce s databází, Datový model. SQL standard umožňuje pracovat s více tabulkami pomocí tzv. join operace. Mluvíme o spojování tabulek. Spojování tabulek je dvojího typu, existuje vnitřní a vnější spojení. Rozdíl nejlépe ilustruje příklad, kdy máme 2 tabulky s vazbou 1: n, tabulka pacientů a tabulka jejich vyšetření, každý pacient může mít 0 až n vyšetření, primárním klíčem v tabulce pacientů je sloupec id_pacienta, který slouží jako cizí klíč v tabulce vyšetření:
Tab. 1: Tabulka pacientů | |||||||||||||
|
|||||||||||||
Tab. 2: Tabulka vyšetření | |||||||||||||
|
Tab. 3: Výsledek vnitřního spojení
patient_id | jmeno | prijmeni | datum_vysetreni | hmotnost |
1 | Jan | Starý | 1.2.2012 | 66 |
1 | Jan | Starý | 1.6.2012 | 70 |
2 | Karel | Nový | 14.7.2013 | 69 |
Tab. 4: Výsledek vnějšího spojení
patient_id | jmeno | prijmeni | datum_vysetreni | hmotnost |
1 | Jan | Starý | 1.2.2012 | 66 |
1 | Jan | Starý | 1.6.2012 | 70 |
2 | Karel | Nový | 14.7.2013 | 69 |
3 | Olga | Mladá |
Výsledkem vnitřního spojení jsou řádky, které existují v obou spojovaných tabulkách, řádky, které existují pouze v jedné z tabulek, jsou vynechány. Oproti tomu vnější spojení umožňuje získat všechny řádky z jedné tabulky a k nim připojit existující řádky v druhé tabulce. Jedna ze spojovaných tabulek je u vnějšího spojení řídící, k níž se dle podmínky váží řádky druhé tabulky.
Pro získání dat z více tabulek slouží v SQL klíčové slovo JOIN, které se umísťuje mezi názvy spojovaných tabulek. Následuje klíčové slovo ON, po kterém je nutné definovat způsob propojení. Pokud použijeme samotné slovo JOIN, provede se vnitřní spojení:
SELECT p.id_pacienta, p.jmeno, p.prijmeni, v.datum_vysetreni, v.hmotnost
FROM pacienti p JOIN vysetreni v ON p.id_pacienta = v.id_pacienta
Protože pracujeme s více tabulkami, je nutné sloupce identifikovat plným jménem, které se skládá z názvu tabulky a názvu samotného sloupce, který oddělíme tečkou. Místo plného názvu tabulek můžeme definovat zkrácené pojmenování v části FROM, zkratku zapíšeme přímo za název tabulky. Zkratku tabulky pak používáme ve všech částech SQL dotazu. Způsob spojení tabulek je obvykle definováno podmínkou za klíčovým slovem ON. Podmínka definuje, které řádky se spolu mají párovat. Pokud podmínku nedefinujeme, vzniká tzv. kartézský součin, kdy se každý řádek jedné tabulky spojí s každým řádkem druhé tabulky. Výsledná množina má pak m x n řádků, což u větších tabulek může být enormní počet. Toto chování je ve většině případů nežádoucí, proto musíme být při definování podmínky spojení velmi pozorní. Databáze se tak bude chovat i v případě, kdy dle spojovací podmínky odpovídá jednomu řádku první tabulky více řádků v tabulce druhé. Hodnoty řádku první tabulky se kopírují ke každému řádku druhé tabulky. Výsledkem spojení tabulek je n řádků, kde n je u vnitřního spojení v rozsahu 0 až m * n, u vnějšího spojení v rozsahu m až m * n.
Pokud chceme provést vnější spojení tabulek, doplníme před JOIN jedno z dalších klíčových slov: LEFT, RIGH nebo FULL. Pokud chceme, aby řídící byla uvedená první, použijeme klíčové slovo LEFT JOIN, pokud chceme mít řídící druhou tabulku, použijeme RIGHT JOIN. Extrémem je tzv. úplné spojení (full join), jehož výsledkem jsou všechny řádky obou tabulek. Tento typ spojení však použijeme jen zřídka, navíc je pro databáze výkonnostně nejnáročnější. V našem případě použijeme variantu LEFT JOIN:
SELECT p.id_pacienta, p.jmeno, p.prijmeni, v.datum_vysetreni, v.hmotnost
FROM pacienti p LEFT JOIN vysetreni v ON p.id_pacienta = v.id_pacienta
Alternativou k syntaxi JOIN ON je přímý výčet spojovaných tabulek za FROM a specifikace spojovací podmínky za WHERE. Tato konstrukce může být v případech spojování více tabulek lépe čitelná. Lze ji však standardně použít jen pro vnitřní spojení. Stejný výsledek jako v prvním případě dostaneme i po spuštění této varianty:
SELECT p.id_pacienta, p.jmeno, p.prijmeni, v.datum_vysetreni, v.hmotnost
FROM pacienti p, vysetreni v WHERE p.id_pacienta = v.id_pacienta