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 :
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)
Příklad 6.1b:
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
CREATE SCHEMA AUTHORIZATION jméno schématu nebo
CREATE DATABASE jméno schématu
Příklad 6.1: CREATE SCHEMA AUTHORIZATION KNIHOVNA CREATE DATABASE Firma
Zrušení schématu DROP SCHEMA jméno schématu nebo
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í)
INTEGER SMALLINT DECIMAL (p,q) NUMERIC REAL DOUBLE PRECISION FLOAT CHAR(n) VARCHAR(n)
(nestandardní)
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] ALTER [ COLUMN] ALTER [ COLUMN] DROP [ COLUMN ]
Příklad 6.5:
atribut SET DEFAULT hodnota atribut typ atribut DROP DEFAULT atribut
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
A1
A2
...
Příklad 6.27 a: ČTENÁŘ
Čísloč
JménoČ P._J
AdresaČ P._A
Příklad 6.27 b: ČTENÁŘ
Čísloč
JménoČ P.ALL _J
AdresaČ P.ALL_A
Příklad 6.27 c: ČTENÁŘ
Čísloč
JménoČ P.AO(1)
AdresaČ P. AO(2)
Příklad 6.28 : VÝTISK P.
ISBN
InvCis
Příklad 6.29 a : Logická spojka AND VÝTISK ISBN InvCis P._I P._IČ _I _IČ
Příklad 6.29 b : Logická spojka AND (Paradox) VÝTISK ISBN InvCis P.
DatNákup > 21.10.1997
DatNákup > 10.10.1997 < 10.11.1997
DatNákup > 10.10.1997, < 10.11.1997
Aa
Příklad 6.30 : Logická spojka OR VÝTISK ISBN P. P.
InvCis
DatNákup < 01.07.1997 > 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 _IS P.
REZERVACE ISBN ČísloČ DatRez _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 Příklad 6.35 b :
ČísloČ P.CNT.ALL._X
DatRez
REZERVACE ISBN
Příklad 6.36 : VÝPUJČKY
Příklad 6.37 : VÝPUJČKY
ČísloČ P.CNT.UN.ALL._X
DatRez
InvCis P.CNT.ALL._IC
ČísloČ P.G.
DatPůjčeno
InvCis P.CNT.ALL._IC
ČísloČ P.G.
DatPůjčeno
Conditions Cnt.All._IC > 5
Negace a kvantifikace Příklad 6.38 : CENIK Ev_cislo P. _EC
Značka _Z
Cena _C
SKLAD
Ev_cislo _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, 5th 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.