6. SQL složitější dotazy, QBE Příklady : Veškeré příklady budou dotazy nad databází KONTAKTY nebo KNIHOVNA nebo FIRMA Databáze KONTAKTY OSOBA (Id_osoba, Příjmení, Jméno, Narození, Město, Ulice, PSČ) EMAIL (Id_email, Osoba, Email) TELEFON (Id_telefon, Osoba, Předvolba, Číslo) SKUPINA (Id_skupina, Název) ČLENSTVÍ (Id_členství, Osoba, Skupina) Databáze KNIHOVNA KNIHA (CisloKnihy, Název, Autor, Ţánr, Rok) ŢÁNR (Id, Název) VÝTISK (EvidCislo, CisloKnihy, Nakladatel, Pořízeno, Cena, Jazyk) AUTOR (Id, Příjmení, Jméno, Stát) ČTENÁŘ (Id, Příjmení, Jméno, Město, Ulice, PSČ, DatumOd, DatumDo) VÝPŮJČKA (Id, Výtisk, Čtenář, Půjčeno, Vráceno ) REZERVACE (Id, CisloKnihy, Čtenář, Datum) NAKLADATELSTVÍ (Id, Název, Město, Stát) Databáze FIRMA ZAMĚSTNANEC (Id, Jméno, Příjmení, Oddělení) ODDĚLENÍ (Id, Název, Místo, Vedoucí) MZDA(Id, Zaměstnanec, Tarif, Příplatek, Osobní, Platnost) Dotazy na neexistující záznamy NOT EXISTS, NOT IN Příklad 6.1a : Příklad 6.1b: Vypsat čísla čtenářů, kteří si letos ještě nic nepůjčili SELECT C.id FROM ČTENÁŘ C WHERE NOT EXISTS ( SELECT * FROM VÝPŮJČKA V WHERE YEAR(V.Půjčeno) = YEAR (DATE ()) AND C.Id = V.Čtenář AND V.CisloKnihy=K.CisloKnihy) Vypsat čísla čtenářů, kteří si letos ještě nic nepůjčili SELECT id FROM ČTENÁŘ WHERE id NOT IN (SELECT čtenář FROM VÝPŮJČKA WHERE YEAR(půjčeno) = YEAR (DATE ())) Příklad 6.2 : Kniha, která se nikdy nepůjčila SELECT Název FROM KNIHA WHERE cisloknihy NOT IN (SELECT DISTINCT Výtisk.cisloKnihy FROM VÝPŮJČKA, VÝTISK WHERE Výpůjčka.Výtisk = EvidCislo)
Příklad 6.3a: Vypsat seznam všech osob, které nemají emaily (pomocí NOT EXISTS) SELECT příjmení, jméno FROM Osoba WHERE NOT EXISTS (SELECT * FROM Email WHERE id_osoba = osoba) Příklad 6.3b: Vypsat seznam všech osob, které nemají emaily SELECT příjmení, jméno FROM Osoba LEFT JOIN Email ON id_osoba = osoba WHERE email IS NULL Příklad 6.4: Vypsat jména autorů, jejichţ knihy knihovna nevlastní SELECT příjmení, jméno FROM Autor A WHERE NOT EXISTS (SELECT * FROM Kniha K, Výtisk V WHERE K.cisloKnihy = V. cisloknihy AND A.id = K.autor) Příklad 6.5: Vypsat seznam skupin, v nichţ není zatím nikdo zařazen SELECT název FROM Skupina WHERE id_skupina NOT IN (SELECT DISTINCT skupina FROM Členství) INTERSECT, EXCEPT Příklad 6.6: Osoby, které nemají ani telefon, ani email SELECT příjmení, jméno FROM Osoba LEFT JOIN Telefon ON Osoba.id_osoba = Telefon.osoba WHERE Telefon.číslo IS NULL INTERSECT SELECT příjmení, jméno FROM Osoba LEFT JOIN Email ON Osoba.id_osoba = Email.osoba WHERE Email.email IS NULL Příklad 6.7: Kamarádi, kteří se mnou nechodí do školy SELECT příjmení, jméno FROM Osoba, Členství, Skupina WHERE Osoba.id_osoba = Členství.osoba AND Členství.skupina = Skupina.id_skupina AND Skupina.název = N'kamarádi' EXCEPT SELECT příjmení, jméno FROM Osoba, Členství, Skupina WHERE Osoba.id_osoba = Členství.osoba AND Členství.skupina = Skupina.id_skupina AND Skupina.název = N'škola'
Spojení JOIN inner join vnitřní spojení propojení odpovídajících záznamů obou tabulek left [outer] join levé vnější spojení do výsledku jsou zahrnuty veškeré záznamy tabulky vlevo nakombinované s odpovídajícími záznamy tabulky vpravo eventuelně s null right [outer] join pravé vnější spojení do výsledku jsou zahrnuty veškeré záznamy tabulky vpravo nakombinované s odpovídajícími záznamy tabulky vlevo eventuelně s null full join plné spojení Příklad 6.8: Vypsat osoby a jejich emaily SELECT příjmení, jméno FROM Osoba INNER JOIN Email ON id_osoba = osoba Příklad 6.8 : Vypsat osoby a jejich emaily včetně osob, které nemají emaily SELECT příjmení, jméno FROM Osoba LEFT JOIN Email ON id_osoba = osoba Příklad 6.9: Vypsat osoby a jejich emaily a telefony SELECT příjmení, jméno, email, číslo FROM (Osoba INNER JOIN Email ON id_osoba = Email.osoba) INNER JOIN Telefon ON id_osoba = Telefon.osoba ve výsledku uvidíme jen osoby, které mají email a zároveň telefon!!! Je třeba pouţít např. left join Příklad 6.10: Vypsat seznam osob a počtu jejich emailů SELECT příjmení, jméno, COUNT(*) AS [počet emailů] FROM Osoba INNER JOIN Email ON id_osoba = osoba GROUP BY příjmení, jméno zahrnuty pouze ty osoby, co mají aspoň 1 email Příklad 6.10 : Vypsat seznam osob a počtu jejich emailů SELECT příjmení, jméno, COUNT(*) AS [počet emailů] FROM Osoba LEFT JOIN Email ON id_osoba = osoba GROUP BY příjmení, jméno zahrnuty všechny osoby, ale započtena 1 u záznamů s null Příklad 6.10 : Vypsat seznam osob a počtu jejich emailů SELECT příjmení, jméno, COUNT(email) AS [počet emailů] FROM Osoba LEFT JOIN Email ON id_osoba = osoba GROUP BY příjmení, jméno SPRÁVNĚ
Příklad 6.11: Vypsat seznam všech osob a počtu jejich emailů a telefonů WITH pemail (id, pr, jm, počet) AS (SELECT id_osoba, příjmení, jméno, COUNT(email) FROM Osoba LEFT JOIN Email ON id_osoba = osoba GROUP BY id_osoba, příjmení, jméno) SELECT id, pr, jm, počet AS emaily, COUNT(číslo) AS telefony FROM pemail LEFT JOIN Telefon ON id = Telefon.osoba GROUP BY id, pr, jm, počet Příklad 6.12: Co bude výsledkem dotazu? SELECT příjmení, jméno, název FROM (Osoba LEFT JOIN Členství ON Osoba.id_osoba = Členství.Osoba) INNER JOIN Skupina ON Členství.Skupina = Skupina.id_skupina Příklad 6.13: Co bude výsledkem dotazu? SELECT DISTINCT Autor.příjmení, Autor.jméno, kniha.název, FROM ((Autor INNER JOIN Kniha ON Autor.id = Kniha.id) INNER JOIN Výtisk ON Kniha.ISBN = Výtisk.ISBN) INNER JOIN Výpůjčka ON Výtisk.invcis = Výpůjčka.invcis WHERE MONTH(vypůjčeno) = MONTH(GETDATE()) AND AND YEAR(vypůjčeno) =YEAR(GETDATE()) Vkládání nových záznamů INSERT INSERT INTO Tabulka [(Sloupec1, Sloupec2, )] VALUES (Výraz1, Výraz2, ) Příklad 6.14: -- vytvoření tabulky Osoba CREATE TABLE Osoba ( id int identity primary key, jméno nvarchar(30), výška float, hmotnost smallint) -- vloţení záznamů INSERT INTO Osoba (jméno, výška) VALUES (N'Peterka Josef', 1.85) INSERT INTO Osoba VALUES (N'Bláhová Alena', 1.65, 58) INSERT INTO Osoba (jméno) VALUES (N'Souček' Jiří) SET IDENTITY_INSERT Osoba ON INSERT INTO Osoba VALUES (13, N'Zelenka Petr', 1.93, 95) Příklad 6.15: INSERT INTO Autor VALUES ('Christie', 'Agatha', 'GBR')
Příklad 6.16: předpokládejme, ţe id A. Christie je 15 INSERT INTO Kniha (cisloknihy, název, autor) VALUES ('978-80-242-2344-5','Vraţdy podle abecedy', 15) Příklad 6.17: INSERT INTO Nakladatelství (název, město, stát) VALUES ('Kniţní klub', 'Praha', 'CZE') Příklad 6.18: INSERT INTO Výtisk (evidcislo, cisloknihy, nakladatel, datum, cena) VALUES ('K2315', '978-80-242-2344-5', 8, '25.08.2008', 209.00) Změna hodnot existujících záznamů UPDATE UPDATE tabulka SET sloupec = {výraz null DEFAULT} [, sloupec = ] [WHERE podmínka] Příklad 6.19: UPDATE Autor SET stát = 'GBR' WHERE stát = 'UK' Příklad 6.20: UPDATE Zaměstnanec SET oddělení = 4 WHERE oddělení = 7' Příklad 6.21: UPDATE Mzda SET příplatek = příplatek + 1500, platnost = GetDate() WHERE Mzda.zaměstnanec IN (SELECT Zaměstnanec.id FROM Zaměstnanec INNER JOIN Oddělení ON Zaměstnanec.oddělení = Oddělení.id WHERE název = 'Sklad') Příklad 6.14: Příklad 6.14: Příklad 6.14: Příklad 6.14: Definice dat v SQL Databázové schéma
nebo CREATE SCHEMA AUTHORIZATION jméno schématu CREATE DATABASE jméno schématu Příklad 6.1: CREATE SCHEMA AUTHORIZATION KNIHOVNA CREATE DATABASE Firma Zrušení schématu nebo DROP SCHEMA jméno schématu DROP DATABASE jméno schématu Příklad 6.2: DROP SCHEMA KNIHOVNA Práce s relacemi (tabulkami) CREATE TABLE, ALTER TABLE, DROP TABLE (definice indexu se dá realizovat pomocí CREATE INDEX) Typy atributů : (standardní) (nestandardní) INTEGER SMALLINT DECIMAL (p,q) NUMERIC REAL DOUBLE PRECISION FLOAT CHAR(n) VARCHAR(n) MONEY DATE.....
Definice relace CREATE TABLE [jméno autorizace ] jméno relace (atribut1 typ1 [ NOT NULL [ UNIQUE ] ], [atribut2 typ2 [ NOT NULL [ UNIQUE ] ],... ] [, UNIQUE seznam atributů ] ) Příklad 6.3 : CREATE TABLE Zaměstnanec ( Jméno VARCHAR(15) NOT NULL, Příjmení VARCHAR(15) NOT NULL, RodCis CHAR(10) NOT NULL, DatNar DATE, Pohlaví CHAR, Vedoucí CHAR(10), Plat DECIMAL(10,2), CisOdd INT NOT NULL, PRIMARY KEY (RodCis), FOREIGN KEY (Vedoucí) REFERENCES Zaměstnanec ( RodCis), FOREIGN KEY (CisOdd) REFERENCES Oddělení (CisOdd)) CREATE TABLE Oddělení ( CisOdd INT NOT NULL,..., Vedoucí CHAR(10) NOT NULL DEFAULT 1122334455,..., CONSTRAINT OdděleníPK PRIMARY KEY (CisOdd), CONSTRAINT VedoucíFK FOREIGN KEY (Vedoucí ) REFERENCES Zaměstanec(RodCis) ON DELETE SET DEFAULT ON UPDATE CASCADE ) Příklad 6.4 : CREATE TABLE VÝPŮJČKA (INV_CIS CHAR(3) NOT NULL, ČÍSLOČ CHAR(3) NOT NULL, DAT_VRÁCENO CHAR(6) Změna struktury ALTER TABLE jméno relace změna ADD atribut typ
ALTER [ COLUMN] atribut SET DEFAULT hodnota ALTER [ COLUMN] atribut typ ALTER [ COLUMN] atribut DROP DEFAULT DROP [ COLUMN ] atribut Příklad 6.5: ALTER TABLE FIRMA.Zaměstnanec ADD Vzdělání CHAR Příklad 6.6: ALTER TABLE FIRMA.Oddělení ALTER Vedoucí DROP DEFAULT Zrušení tabulky DROP TABLE jméno relace Příklad 6.7: DROP TABLE DETI CASCADE Aktualizace UPDATE jméno relace SET atribut = hodnota [, atribut = hodnota...] [ WHERE podmínka ] Příklad 6.8: UPDATE Oddělení SET Místo = Brno, Ulice= Nádraţní WHERE Číslo=5
Přidávání záznamů INSERT INTO jméno relace [ ( atribut [,atribut... ) ] VALUES ( hodnota [, hodnota... ]] příkaz SELECT Příklad 6.9 : INSERT INTO Zaměstnanec (Jméno, Příjmení, RodCis, CisOdd) VALUES ( Jan, Peterka, 6105070123, 2) Rušení záznamu DELETE FROM jméno relace [ WHERE podmínka ] Příklad 6.10 : DELETE FROM Zaměstnanec WHERE Příjmení= Novák Příklad 6.11 : DELETE FROM Zaměstnanec WHERE CisOdd IN ( SELECT Číslo FROM Oddělení WHERE NázevOdd= Výzkum ) Definice indexu CREATE [UNIQUE] INDEX jméno indexu ON jméno relace ( atribut [ uspořádání] [, atribut [ uspořádání] ]...) [CLUSTER] Příklad 6.12 : CREATE INDEX JménoI ON Zaměstanec(Příjmení,Jméno)
Příklad 6.13 : CREATE INDEX PlatI ON Zaměstanec(Plat DESC) Zrušení indexu DROP INDEX jméno indexu Příklad 6.14 : DROP INDEX dat_nar Definice pohledu CREATE VIEW Jméno pohledu [ ( p-atribut1 [, p-atribut2]...) AS SELECT [ DISTINCT] * atribut1 [, atribut2] FROM jméno relace1 [, jméno relace2 ]... [WHERE podmínka] [GROUP BY atribut1 [, atribut2]... [HAVING podmínka ]] [ENABLE UPDATES] Příklad 6.15 : CREATE VIEW Praţák AS SELECT ČísloČ, JménoČ, AdresaČ FROM ČTENÁŘ WHERE AdresaČ LIKE %Praha% Příklad 6.16 : CREATE VIEW Statistika AS SELECT ČísloČ, COUNT(InvCis) FROM VÝPŮJČKA GROUP BY ČísloČ Příklad 6.17 : definice primárních klíčů pomocí SQL89 CREATE TABLE UCITELE
(CISLO INTEGER PRIMARY KEY, JMENO CHARACTER(30), ROD_CIS CHARACTER(10) NOT NULL UNIQUE,... ) CREATE TABLE VYUKA (UCITEL INTEGER, PŘEDMĚT CHARACTER(7), KDY CHARACTER(7),..., PRIMARY KEY (UCITEL, PŘEDMĚT, KDY), FOREIGN KEY (GARANT) REFERENCES UCITELE(CISLO)) Příklad 6.18 : kaskádovitá a NULL varianta zajištění RI v SQL89 CREATE TABLE VYUKA (..., FOREIGN KEY (UCITEL) REFERENCES UCITELE(CISLO) ON UPDATE CASCADE ON DELETE CASCADE, FOREIGN KEY (PŘEDMĚT) REFERENCES PREDMETY(ZKRATKA) ON UPDATE CASCADE ON DELETE CASCADE,... ) CREATE TABLE PREDMETY (..., FOREIGN KEY (GARANT) REFERENCES UCITELE(CISLO) ON UPDATE CASCADE ON DELETE SET NULL,... ) Příklad 6.19 : Příkaz SELECT s klauzulí CHECK CREATE TABLE KATEDRY (..., VEDOUCI INTEGER NOT NULL, CHECK (EXISTS SELECT * FROM UCITELE WHERE VEDOUCI = UCITELE.CISLO AND TITUL IN ( DOC, PROF )),... ) Příklad 6.20 : Integritní omezení v definici pohledu CREATE VIEW UPD_UCITELE AS SELECT * FROM UCITELE WHERE PLAT > 0 AND PRIPLATEK < PLAT *0,5 WITH CHECK OPTION
Transakce TRANSACTION Jméno transakce WHENEVER [ ERROR podmínka ] ROLLBACK Příkazy...... COMMIT END Příklad 6.21 : Transakce TRANSACTION Přecenění WHENEVER ERROR ROLLBACK UPDATE Výtisk SET Cena = Cena * Kurs_DM WHERE Země= SRN COMMIT END OCHRANA DAT Přidělení práv uživatelům GRANT { ALL { DELETE INSERT SELECT UPDATE [ ( atribut1 [, atribut2] ) }} ON jméno relace TO { PUBLIC uživatel1 [, uživatel2] } Příklad 6.22 : GRANT UPDATE (Země) ON VÝTISK TO Jitka GRANT SELECT ON ČTENÁŘ TO PUBLIC GRANT ALL ON PRAŢÁK TO Novák
Zrušení přístupového práva REVOKE { ALL { DELETE INSERT SELECT UPDATE [ ( atribut1 [, atribut2] ) }} ON jméno relace TO { PUBLIC uživatel1 [, uživatel2] } Příklad 6.23 REVOKE ALL ON ČTENÁŘ TO Petr REVOKE UPDATE ON Výtisk TO Jakub
TRIGERY Příklad 6.24 : CREATE TRIGGER predmet_del ON predmety FOR DELETE AS DELETE FROM uci WHERE uci.predmet = zkratka Příklad 6.25: CREATE TRIGGER ucitel_del ON ucitele FOR DELETE AS UPDATE uci SET ucitel = NULL WHERE ucitel = ucitele.cislo Příklad 6.26: CREATE TRIGGER trida_upd ON trida FOR UPDATE AS UPDATE zaci SET trida = trida.nazev WHERE trida = OLD( nazev ) V případě sloţitějších trigerů je třeba pouţít procedury a fce
QBE Druhý nejrozšířenější relační jazyk vznik Zloof, implementace IBM 1975 - tvoří uţivatelské rozhraní v dotazovacím balíku QMF v DB2 ( IBM ) - vyskytuje se SQL/DS ( IBM) - QBE rozhraní Intel - QBE rozhraní Honeywell - hlavní součást Paradoxu ( první implementace na PC ) Jazyk je zaloţen na dvourozměrné notaci na tabulkách. Dotazy se vytvářejí zápisem do prázdných tabulek jedná se o zápis pomocí příkladů. Jazyk QBE podporuje odstranění duplicitních řádků, chceme-li duplicity, musíme pouţít ALL Uspořádání se realizuje pomocí AO nebo DO R A 1 A 2... A a Příklad 6.27 a: ČTENÁŘ Čísloč JménoČ AdresaČ P._J P._A Příklad 6.27 b: ČTENÁŘ Čísloč JménoČ AdresaČ P.ALL _J P.ALL_A Příklad 6.27 c: ČTENÁŘ Čísloč JménoČ AdresaČ P.AO(1) P. AO(2) Příklad 6.28 : VÝTISK ISBN InvCis DatNákup P. > 21.10.1997 Příklad 6.29 a : Logická spojka AND VÝTISK ISBN InvCis DatNákup P._I P._IČ > 10.10.1997 _I _IČ < 10.11.1997 Příklad 6.29 b : Logická spojka AND (Paradox) VÝTISK ISBN InvCis DatNákup P. > 10.10.1997, < 10.11.1997
Příklad 6.30 : Logická spojka OR VÝTISK ISBN InvCis DatNákup P. < 01.07.1997 P. > 10.09.1997 Příklad 6.31 : Autoři, co napsali Přehled SŠ matematiky nebo Přehled SŠ fyziky KNIHA ISBN Autor Název P._X Úvod do SŠ matematiky P._Y Úvod do SŠ fyziky Příklad 6.32 : Autoři, co napsali Přehled SŠ matematiky a současně i Přehled SŠ fyziky KNIHA ISBN Autor Název P._X Úvod do SŠ matematiky P._X Úvod do SŠ fyziky Příklad 6.33 : Spojení dvou tabulek KNIHA ISBN Autor Název REZERVACE ISBN ČísloČ DatRez _IS P. _IS < 31.10.97 Příklad 6.34 : Spojení relace se sebou samou do okna CONDITION napsat _CT1 < _CT2 ČTENÁŘ ČísloČ JménoČ AdresaČ _CT1 _ADR P. _CT1 _CT2 _CT2 _ADR Agregační funkce SUM, AVG, MAX, MIN, CNT Příklad 6.35 a : REZERVACE ISBN ČísloČ DatRez P.CNT.ALL._X Příklad 6.35 b :
REZERVACE ISBN ČísloČ DatRez P.CNT.UN.ALL._X Příklad 6.36 : VÝPUJČKY InvCis ČísloČ DatPůjčeno P.CNT.ALL._IC P.G. Příklad 6.37 : VÝPUJČKY InvCis ČísloČ DatPůjčeno Conditions P.CNT.ALL._IC P.G. Cnt.All._IC > 5 Negace a kvantifikace Příklad 6.38 : CENIK Ev_cislo Značka Cena SKLAD Ev_cislo P. _EC _Z _C _EC Literatura: [1] ELMASRI, R., NAVATHE, S., B. Fundamentals of Database Systems, 5th edition. Addison-Wesley, 2007. ISBN 978-03-213-6957-4. [2] SILBERSCHATZ, A., KORTH H. F., SUDARSHAN S. Database System Concepts, 5 th edition, New York: McGraw-Hill, 2006. ISBN 978-0-07-295886-7 [3] CONOLLY, T., BEGG, C., HOLOWZAK R. Profesionální průvodce tvorbou databází. Praha: Computer Press, a. s., 2009. ISBN 978-80-251-2328-7. [4] HERNANDEZ, M., J. Návrh databází. Praha: Grada, 2006. ISBN 80-247-0900-7. [5] POKORNÝ, J. Databázová abeceda. Veletiny: Science, 1998, ISBN 80-86083-02-2. [6] POKORNÝ, J., HALAŠKA, I. Databázové systémy, 2. vydání. Praha Vydavatelství ČVUT, 2003, ISBN 80-01-02789-9.