DB1 cvičení 4 spojení tabulek a složitější dotazy Spojení tabulek Navázání spojení mezi tabulkami Cizí klíč tabulky Auto referencuje primární klíč tabulky TypAuta: CREATE TABLE TypAuta (pk_ta NUMBER(2) PRIMARY KEY,...); CREATE TABLE Auto; (... fk_ta NUMBER(2) REFERENCES TypAuta,...) Datové typy cizího klíče a primárního klíče si musí odpovídat! Pro smazání tabulek, které mají navázány cizí klíče je třeba za DROP uvést CASCADE CONSTRAINTS, např. DROP TABLE Tabulka CASCADE CONSTRAINTS; Dotaz nad více tabulkami SELECT sloupce FROM Tabulka1, Tabulka2 WHERE podminky AND Tabulka1.pk_t1 = Tabulka2.fk_tab1; Jelikož atributy v různých tabulkách mohou mít stejné názvy, je třeba používat plně kvalifikovaná jména atributů ve formátu tabulka.atribut, tedy např. SELECT Zakaznik.prijmeni FROM Zakaznik, Zakazky WHERE Zakaznik.id = Zakazky.fk_zak; Tabulek může být i více než 2. Musí být uvedeny v pořadí, které umožňuje jejich vzájemné spojení (tedy např. člen-členství-klub, nikoliv člen-klub-členství) a všechny je potřeba navzájem svázat v podmínce přes dvojice cizí klíč-primární klíč. Tabulky si lze v dotazu přejmenovat pro pohodlnější (kratší) psaní: SELECT X.sl1, Y.sl2 FROM Tabulka1 X, Tabulka2 Y WHERE podminky AND X.pk_t1 = Y.fk_tab1; Díky přejmenování je pak možné v dotazu použít dvakrát stejnou tabulku: SELECT X.rod_c AS prvni, Y.rod_c AS druhy FROM Zakaznici X, Zakaznici Y WHERE X.adresa = Y.adresa AND X.rod_c < Y.rod_c (Dotaz najde dvojice zákazníků, kteří mají stejné adresy. Podmínka X.rod_c < Y.rod_c zajistí, že každá dvojice bude vypsána jen jednou).
Vazební tabulky Spojení dvou tabulek umožňuje navázat několik záznamů z referencující tabulky na jeden záznam v referencované tabulce (několik cizích klíčů může ukazovat na jeden primární klíč, tzv. vztah 1:N). Pro navázání vazeb typu M:N je třeba použít tzv. vazební tabulku, jejíž řádky budou k sobě vázat vždy dva záznamy z referencovaných tabulek. Každý řádek může navíc obsahovat doplňkové atributy týkající se vztahu. Primární klíč v tomto případě je tvořen dvojicí cizích klíčů (dva záznamy má smysl k sobě vázat pouze jednou vazbou). Specifikaci prim.klíče a cizích klíčů nyní ale musíme provést odděleně: CREATE TABLE Sberatel (pk_s NUMBER(2) PRIMARY KEY,...); CREATE TABLE Klub (pk_k NUMBER(2) PRIMARY KEY,...); CREATE TABLE Clenstvi (fk_sberatel NUMBER(2), fk_klub NUMBER(2),... PRIMARY KEY (fk_sberatel, fk_klub), FOREIGN KEY (fk_sberatel) REFERENCES Sberatel, FOREIGN KEY (fk_klub) REFERENCES Klub); Vnořené dotazy V SQL lze konstruovat vnořené dotazy. Vnořený dotaz můžeme použít např. pro 1. Spočítání agregovaného údaje, který použijeme v nadřazeném dotazu jako podmínku: SELECT nazev_kina FROM Kina K WHERE 8 < (SELECT COUNT(jmeno_f) FROM Predstaveni P WHERE P.nazev_kina = K.nazev_kina; (Kina, kde mají více jak 8 filmů na programu) 2. Jako alternativu spojení, např. adresy kin, kde dávají film Kolja lze napsat jako SELECT DISTINCT adresa FROM Kina k, Predstaveni p WHERE k.id_kina = p.kino AND jmeno_f = Kolja ); nebo SELECT adresa FROM Kina WHERE nazev_k IN (SELECT nazev_k FROM Predstaveni WHERE jmeno_f= Kolja );
3. Zjištění jiného údaje pro podmínku, např. jméno nejnovejšího kina SELECT nazev_kina FROM Kina WHERE datum_zalozeni = (SELECT MAX(datum_zalozeni) FROM Kina). Pozn.: dotaz předpokládá, že nejnovější kino je jen jedno, pokud by jich mohlo být více, je třeba použít IN místo =. Úplná syntaxe příkazu SELECT SELECT [DISTINCT] { * seznamsloupcu} FROM jmenotabulky [, jmenotabulky]... [WHERE vyberovapodminka] [GROUP BY seznamsloupcu [HAVING vyberovapodminka]] [ORDER BY jmenosloupce [ASC DESC] [, jmenosloupce [ASC DESC]...]] {......}... jedna z možností [... ]... volitelná část seznamsloupců je seznam sloupců oddělených čárkami. Za sloupec považujeme i agregační funkci, tedy např. COUNT(*) se píše na místo sloupce. Úkoly: Pozn: dotazy provádějte k datu 26.10.2005 Dotazy na jednou tabulkou: 1. Zobrazte jména, příjmení a datum narození doktorů starších 40 let. Seřaďte podle stáří od nejmladšího. FIRSTNAME SURNAME BIRTHDATE ------------ ---------- --------------- Petr Bily 14.2.1962 0:00 Ivan Zeleny 15.11.1955 0:00 Jan Novak 4.1.1950 0:00 Joe Davidson 27.3.1949 0:00 2. Které specializace lze nalézt v Praze? SPECIALIZATION ----------------- practicioner surgeon 3. Kolik bodů celkem nashromáždili psychologové? Přejmenujte správně název sloupce výsledku! Celkem bodu -------------- 1500 4. Kolik bodů celkem nashromáždili praktičtí lékaři starší 40 let? SUM(POINTS) --------------
250 5. Kolik bodů průměrně nashromáždily jednotlivé specializace? Nezapomeňte na přejmenování sloupce! SPECIALIZATION Prumerne ----------------- ---------------------------------------- practicioner 162,5 psychologist 750 surgeon 133,333333333333333333333333333333333333 6. S použitím znalostí z předchozího úkolu vytvořte variantu úkolu 3, jejímž výsledkem bude SPECIALIZATION Celkem bodu ----------------- ---------------------------------------- psychologist 1500 7. Vypište specializace, které nashromáždily víc jak 500 bodů (použijte GROUP BY a HAVING). SPECIALIZATION BODU ----------------- ------- practicioner 650 psychologist 1500 Dotazy nad více tabulkami: 8. Které diagnózy diagnostikoval Dr. Asklepios? DIAGNOSIS ------------ alergy diarrhoea flu tonsillitis 9. Data vyšetření pacienta Milana Zeleného. VISITDATE --------------- 27.7.2000 0:00 11.11.2000 0:00 3.11.2000 0:00 10. Jména a příjmení doktorů, kteří již někoho diagnostikovali (tj. mají záznam v tabulce návštěv). FIRSTNAME SURNAME ------------ ---------- Ivan Drago Ivan Zeleny Jan Novak Joe Davidson
Kostas Michailos Milan Petr Kokkinos Asklepios Novak Bily 11. Jména a příjmení pacientů Dr. Jana Nováka (nezapomeňte, že sloupce jméno a příjmení mají jak doktor, tak pacient!). FIRSTNAME SURNAME ------------ ---------- Jan Novak Michal Capek Milan Zeleny Petr Novak 12. Jména, příjmení a data narození pacientů Dr. Jana Nováka, kteří jsou mladší než 30 let. FIRSTNAME SURNAME BIRTHDATE ------------ ---------- -------------- Michal Capek 4.12.1999 0:00 Milan Zeleny 5.5.1988 0:00 13. Kolikrát byl u doktora p. Joe Smith? COUNT(*) ----------- 2 Vnořené dotazy 14. Kteří doktoři (příjmení) diagnostikovali více jak třikrát? SURNAME ---------- Asklepios Novak 15. Příjmení lékařů, kteří diagnostikovali nespavost: pomocí spojení a vnořeného dotazu s IN. SURNAME ---------- Novak Zeleny 16. Nejstarší doktor ID FIRSTNAME SURNAME SPECIALIZATION ADDRESS BIRTHDATE POINTS ----- ------------ ---------- ----------------- --------------------- -------------- --------- 1004 Joe Davidson practicioner London, Regent str. 5 27.3.1949 0:00 50
Speciální dotazy 1. Najděte dvojice lékařů se stejnou specializací (použijte dvakrát stejnou tabulku v jednom dotazu spolu s přejmenováním, viz výše). PRVNI DRUHY --------- -------- Asklepios Davidson Zeleny Novak Asklepios Novak Davidson Novak Drago Kokkinos Drago Bily Kokkinos Bily Asklepios Down Davidson Down Novak Down