Databázové systémy Cvičení 5 Dotazy v jazyce SQL
SQL jako jazyk pro manipulaci s daty Aktualizace dat v SQL úprava záznamů v relacích (tabulkách) vložení záznamu INSERT INTO oprava záznamu UPDATE vymazání záznamu DELETE FROM příklady: vložení nového čtenáře:
INSERT INTO CTENAR (RC,JMENO,PRIJMENI) VALUES ("750525/1234","Josef", "Novák") změna příjmení čtenáře: UPDATE CTENAR SET PRIJMENI="Nováková" WHERE RC="755105/1000" vymazání čtenáře: DELETE FROM CTENAR WHERE RC="755105/1000"
ČTENÁŘ RČ JMÉNO PŘÍJMENÍ 320612/1234 František Kuldanů 521006/5678 Josef Novák KNIHA ISBN TITUL AUTOR 80-11111-22-3 U nás A. Jirásek 80-85190-38-9 Babička B. Němcová EXEMPLÁŘ PŘÍR_Č CENA 1 100 2 100 3 150 D_NÁK 25.3.1990 25.3.1990 26.3.1990 ISBN 80-85190-38-9 80-85190-38-9 80-11111-22-3
SI_VYPŮJČIL RČ PŘÍR_Č DAT 320612/1234 1 10.11.2005 521006/5678 3 20.11.2005
Manipulace s daty - SELECT dotazy pomocí příkazu SELECT FROM SELECT [DISTINCT ALL]{* jméno_atr1, [jméno_atr2, ]} FROM jméno_tab1, [jméno_tab2, ] [WHERE podmínka][order BY jméno_atr1, [ jméno_atr2, ]]
Manipulace s daty - SELECT DISTINCT ve výsledku potlačí duplicitní řádky ALL implicitní volba, ve výsledku ponechá duplicitní řádky * vybere všechny sloupce
Příklady: výpis všech atributů všech čtenářů SELECT * FROM CTENAR výpis jmen a příjmení všech čtenářů SELECT JMENO, PRIJMENI FROM CTENAR výpis jmen a příjmení všech čtenářů s vynecháním opakujících se SELECT DISTINCT JMENO, PRIJMENI FROM CTENAR
výpis všech čtenářů s příjmením Novák SELECT JMENO, PRIJMENI FROM CTENAR WHERE PRIJMENI="Novák" Pozn: lze použít operátory <, >, <>, <=, >=, logické operátory AND, OR, NOT výpis všech čtenářů Josef Novák SELECT * FROM CTENAR WHERE JMENO="Josef" AND PRIJMENI="Novák"
výpis všechčtenářů s příjmením Novák nebo Pleticha SELECT JMENO, PRIJMENI FROM CTENAR WHERE PRIJMENI="Novák" OR PRIJMENI= "Pleticha"
Užitečný operátor LIKE SELECT * FROM HRA WHERE NAZEV="Naši Furianti" porovnání na přesnou shodu najde hru s názvem Naši Furianti - v DB musí být uložen název přesně s jednou mezerou SELECT * FROM HRA WHERE NAZEV LIKE "Naši% porovnání na částečnou shodu najde všechny hry, jejíž názvy začínají na text Naši
Užitečný operátor LIKE SELECT * FROM HRA WHERE NAZEV LIKE "%Furianti" porovnání na částečnou shodu najde všechny hry, jejíž názvy končí na text Furianti ve standardu SQL se používá jako zástupný znak %, MS Access využívá * SELECT * FROM HRA WHERE NAZEV LIKE "*Furianti"
výpis všech čtenářů seřazených abecedně dle příjmení (ASC znamená řadit vzestupně implicitní volba, není-li uvedeno jinak) SELECT PRIJMENI, JMENO FROM CTENAR ORDER BY PRIJMENI ASC SELECT PRIJMENI, JMENO FROM CTENAR ORDER BY PRIJMENI ASC není nutné psát
výpis všech čtenářů seřazených sestupně abecedně dle příjmení a jména SELECT PRIJMENI, JMENO FROM CTENAR ORDER BY PRIJMENI DESC, JMENO DESC
výpis všech exemplářů, které jsou dražší než 100 Kč SELECT PRIR_C, CENA FROM EXEMPLAR WHERE CENA > 100 výpis všech exemplářů, které stojí mezi 100 Kč a 1000 Kč včetně SELECT PRIR_C, CENA FROM EXEMPLAR WHERE CENA >= 100 AND CENA <= 1000
jinak: SELECT PRIR_C, CENA FROM EXEMPLAR WHERE CENA BETWEEN 100 AND 1000 každý výraz je možné negovat pomocí klíčového slova NOT: výpis všech exemplářů, které jsou levnější než 100 Kč nebo dražší než 1000 Kč SELECT PRIR_C, CENA FROM EXEMPLAR WHERE CENA NOT BETWEEN 100 AND 1000
Realizace operace spojení relací spojení relací se provádí pomocí dotazu SELECT původní SQL86 nemělo žádné klíčové slovo pro operaci spojení spojení se realizovalo uvedením tabulek, které chceme spojit a podmínky v SQL92 existuje navíc klíčové slovo JOIN
výpis jmen a příjmení čtenářů, kteří mají půjčenou nějakou knihu SELECT DISTINCT JMENO, PRIJMENI FROM CTENAR,SI_VYPUJCIL WHERE CTENAR.RC = SI_VYPUJCIL.RC zapsat podmínku rovnosti atributů (přirozené spojení) je nutné, jinak SŘBD provede kartézský součin spojí každý řádek s každým, což vede k zatížení sytému (např. má-li 1 tabulka 1000 řádek a druhá 10000, výsledkem je tabulka o 10 mil. řádků)
pokud je cizím klíčem dvojice atributů, musíme zapsat podmínku rovnosti pro oba atributy a spojit spojkou AND WHERE TAB1.K1 = TAB2.K1 AND TAB1.K2 = TAB2.K2 totéž platí, spojujeme-li více než dvě relace (viz dále) zapisujeme rovnost pro všechny cizí klíče
některé dotazy je výhodné zapsat pomocí množinové operace IN: rychlejší zpracování stejný dotaz: výpis jmen a příjmení čtenářů, kteří mají půjčenou nějakou knihu pomocí IN SELECT DISTINCT JMENO, PRIJMENI FROM CTENAR WHERE RC IN (SELECT DISTINCT RC FROM SI_VYPUJCIL)
množinovou operaci IN lze negovat rychlejší zpracování stejný dotaz: výpis jmen a příjmení čtenářů, kteří nemají půjčenou žádnou knihu: SELECT DISTINCT JMENO, PRIJMENI FROM CTENAR WHERE RC NOT IN (SELECT DISTINCT RC FROM SI_VYPUJCIL) některé dotazy by nešlo bez NOT IN realizovat
výpis všech exemplářů knihy Babička, které jsou dražší než 120 Kč SELECT PRIR_C, TITUL, CENA FROM EXEMPLAR,KNIHA WHERE EXEMPLAR.ISBN=KNIHA.ISBN AND CENA > 120 AND TITUL= "Babička" Poznámka: relace je možné pojmenovat aliasem (pomocným jménem) a odkazovat se na ně tímto jménem
výpis všech knih se stejným názvem, ale různým ISBN (např. od různých nakladatelů) SELECT PRVNI.ISBN, PRVNI.TITUL FROM KNIHA AS PRVNI, WHERE KNIHA AS DRUHY (PRVNI.NAZEV=DRUHY.NAZEV AND PRVNÍ.ISBN <> DRUHY.ISBN) realizuje theta spojení relace sama se sebou Diskuse: Je dobře navržený model knihovny?
výpis všech čtenářů, kteří mají půjčen nějaký exemplář knihy Psohlavci SELECT CTENAR.RC,JMENO,PRIJMENI FROM CTENAR, EXEMPLAR, SI_VYPUJCIL,KNIHA WHERE (KNIHA.TITUL = "Psohlavci" AND KNIHA.ISBN = EXEMPLAR.ISBN AND EXEMPLAR.PRIR_C = SI_VYPUJCIL.PRIR_C AND SI_VYPUJCIL.RC = CTENAR.RC)
úloha: přepište dotaz pomocí množinového konstruktu IN SELECT CTENAR.RC,JMENO,PRIJMENI FROM CTENAR, SI_VYPUJCIL WHERE SI_VYPUJCIL.RC = CTENAR.RC AND PRIR_C IN (SELECT PRIR_C FROM KNIHA, EXEMPLAR ) WHERE KNIHA.TITUL = "Psohlavci" AND KNIHA.ISBN = EXEMPLAR.ISBN
Další operace množinové operace UNION sjednocení INTERSECT průnik EXCEPT rozdíl aplikují se na poddotazy poddotazy musejí dávat takové výsledky, aby měly operace smysl
Další operace zjistěte ID umělců, kteří jsou herci a režiséry zároveň (SELECT ID_U FROM HEREC) INTERSECT (SELECT ID_U FROM REZISER)
Podobný dotaz jinak zjistěte jména umělců, kteří jsou herci a režiséry zároveň (SELECT JMENO,PRIJMENI FROM UMELEC,HEREC,REZISER WHERE UMELEC.ID_U = HEREC.ID_U AND HEREC.ID_U = REZISER.ID_U
Ještě jinak... zjistěte jména umělců, kteří jsou herci a režiséry zároveň SELECT JMENO,PRIJMENI FROM UMELEC WHERE UMELEC.ID_U IN ( (SELECT ID_U FROM HEREC) INTERSECT (SELECT ID_U FROM REZISER) )