Jazyk S Q L základy, příkazy pro práci s daty Základní pojmy jazyk množina řetězců nad abecedou gramatika popisuje syntaxi výrazů jazyka pravidla, jak vytvářet platné řetězce jazyka. dotazovací jazyk je svázán s databází tj. dotazy, které výrazy jazyka označují, musejí být vyhodnotitelné. dotaz (databázový dotaz) funkce definovaná nad prostorem všech přípustných databází s daným schématem. Hodnota této funkce je vlastně odpovědí na dotaz (určitá databáze s daným schématem) Vlastnosti této funkce (dotazu) - je vyčíslitelná - odpověď obsahuje pouze hodnoty z databáze - odpověďnezávisí na reprezentaci databáze omezenost jazyka každému výrazu jazyka odpovídá dotaz expresivní jazyk by byl takový jazyk, kterým by se dal vyjádřit libovolný dotaz (platí např. pro programovací jazyky, nikoliv však pro běžné dotazovací jazyky) vyjadřovací síla jazyka množina dotazů, která se dá v daném jazyce vyjádřit perzistence jazyka Úplný jazyk = expresivní + omezený silnější jazyk (slabší) ekvivalentní jazyky ortogonalita jazyka - nezávislost v používání různých konstrukcí jazyka - existence konstruktoru (nižší objekt vyšší objekt) - existence selektoru - možnost přiřazení hodnot jedné třídy jinému objektu téže třídy - možnost porovnání objektů v rámci třídy
- podpora rekurzivně definované syntaxe a uzávěrových vlastností Vývoj počátky používání rok 1974 ( Sequel ) systémy IBM - DB2 ( operační systém MVS/370 ) - SQL/DS ( systémy VM/CMS, DOS/VSE ) - QMF obsahuje SQL jako uživatelské rozhraní pro počítače třídy PC - INFORMIX SQL - INGRES pro PC - ORACLE - xbase - SQLBase - XDB II - XQL databázové servery - ORACLE - INFORMIX - PROGRESS - INGRES
- SQL Server od Sybase - SQL Server Microsoft Standardizace ANSI v r. 1986 SQL86 ( průnik existujících implementací ), rozšíření definičního jazyka s možností definovat RI - SQL89, další standard přijatý ANSI SQL92. Části SQL - jazyk pro definici dat - interaktivní jazyk pro manipulaci dat - jazyk pro manipulaci dat v hostitelské verzi - možnost definice pohledů - možnost definice přístupových práv - možnost definice integritních omezení - řízení transakcí ROLLBACK. Manipulace dat v SQL SELECT, INSERT, DELETE,UPDATE, OPEN, CLOSE, FETCH, COMMIT, Základním konstruktem pro výběr dat je příkaz SELECT - FROM - WHERE.
Klauzule SELECT odpovídá operaci projekce (eventuelně spojení nebo kartézskému součinu) Klauzule FROM obsahuje seznam jmen relací, nad kterými je dotaz definován Klauzule WHERE obsahuje podmínku definující kritéria pro vyhledávaná data (selekční podmínka).tvar dotazu SELECT A 1, A 2,...., A j FROM R 1, R 2,....., R k WHERE Ekvivalentní dotaz v relační algebře ( R 1, R 2,....., R k ) [A 1, A 2,...., A j ] Zjednodušená syntaxe SELECT [ DISTINCT ALL ] { * atribut1 [, atribut2 ]... } FROM relace1 [, relace2 ]... [ WHERE podmínka ] [ ORDER BY klíč1 [, klíč2 ]... ]
Příklad : Uvažujme následující schéma relační databáze KNIHOVNA ČTENÁŘ (ČísloČ, JménoČ, PříjmeníČ, AdresaČ, DatumOd, DatumDo ) KNIHA ( ISBN, Název, Autor, Rok, Žánr) AUTOR (ČísloA, JménoA, PříjmeníA, StátA) VÝTISK (InvCis, ISBN, Nakladatel, DatNákup, Cena ) NAKLADATELSTVÍ (ČísloN, NázevN, AdresaN, StátN) ŽÁNR (ČísloŽ, NázevŽ) VÝPŮJČKA (ČísloČ, InvCis, DatPůjčeno, DatVráceno ) REZERVACE (ČísloČ, ISBN, DatRez ) Příklad 5.1 : Vypsat seznam čtenářů a jejich adres SELECT PříjmeníČ, JménoČ, AdresaČ FROM ČTENÁŘ Příklad 5.2 : Vypsat seznam čtenářů z Českých Budějovic SELECT * FROM ČTENÁŘ WHERE AdresaČ LIKE %České Budějovice%
Příklad 5.3a : Vypsat seznam čtenářů přihlášených letos SELECT * FROM ČTENÁŘ WHERE YEAR(DatumOd) = YEAR(GETDATE()) Příklad 5.3b : Vypsat seznam nových čtenářů přihlášených o prázdninách SELECT * FROM ČTENÁŘ WHERE DatumOd BETWEEN 01.07.02 AND 31.08.02 Příklad 5.4 : Vypsat názvy knih rezervovaných do konce října SELECT DISTINCT Název FROM KNIHA, REZERVACE WHERE KNIHA.ISBN = REZERVACE.ISBN AND DatRez < 31.10.02 Poznámka: Klauzule DISTINCT zaručuje výběr neduplicitních záznamů Příklad 5.5a : Vypsat seznam všech výtisků vydaných v USA a jejich cenu SELECT DISTINCT ISBN, NázevN, Cena FROM VÝTISK, NAKLADATELSTVÍ WHERE StátN = USA AND ČísloN = Nakladatel Poznámka: Jedná se vlastně o výpis údajů ze dvou tabulek, takže musíme v klauzuli WHERE uvést, jakým způsobem jsou tabulky propojeny. V podstatě se jedná o kartézský součin filtrovaný podmínkou uvedenou ve WHERE.
Příklad 5.5b : Vypsat všechny důležité informace o knihách vytištěných v USA SELECT DISTINCT VÝTISK.ISBN, InvCis, JménoA, PříjmeníA, Název, Cena FROM NAKLADATELSTVÍ, VÝTISK, KNIHA, AUTOR WHERE StátN = USA AND ČísloN = Nakladatel AND Výtisk.ISBN = KNIHA.ISBN AND Autor = ČísloA Agregační, statistické funkce COUNT(), SUM(), AVG(), MAX(), MIN(), STDEV(), VAR() Příklad 5.6 : Celkový počet čtenářů knihovny SELECT COUNT (*) FROM ČTENÁŘ Příklad 5.6 : Celkový počet čtenářů knihovny lépe SELECT COUNT (*) AS počet_čtenářů FROM ČTENÁŘ WHERE DatumDo <= GetDate() Příklad 5.7a : Počet čtenářů, kteří mají rezervovanou nějakou knihu SELECT COUNT (DISTINCT ČísloČ) FROM REZERVACE
Příklad 5.7b : Počet čtenářů, kteří mají půjčenou nějakou knihu SELECT COUNT (DISTINCT ČísloČ) FROM VÝPŮJČKA WHERE DatVráceno IS NULL Příklad 5.8 : Počet knih vydaných v USA v nakladatelství McGraw Hill SELECT COUNT (*) AS knihy_mcgrawhill FROM VÝTISK, NAKLADATEL WHERE NázevN = McGraw Hill AND StátN = USA AND ČísloN = Nakladatel Příklad 5.9 : Zjisti celkový počet výtisků knih Aloise Jiráska v knihovně SELECT COUNT (*) FROM AUTOR, KNIHA, VÝTISK WHERE PříjmeníA= Jirásek AND JménoA= Alois AND Autor=ČísloA AND KNIHA.ISBN = VÝTISK.ISBN Příklad 5.9 : Zjisti celkový počet knih Aloise Jiráska v knihovně SELECT COUNT (DISTINCT VÝTISK.ISBN) AS knihy_jirásek FROM AUTOR, KNIHA, VÝTISK WHERE PříjmeníA= Jirásek AND JménoA= Alois AND Autor=ČísloA AND KNIHA.ISBN = VÝTISK.ISBN
Konstrukt GROUP BY dává možnost aplikace agregačních funkcí na podmnožiny relace zkonstruované podle výběrového kritéria - klasifikace podle hodnot vybraného atributu. Relace se konceptuálně, nikoliv fyzicky rozdělí na skupiny, pro které je hodnota zvoleného atributu konstantní. (Řádky s prázdnou hodnotou daného atributu tvoří zpravidla jednu skupinu.) PRAVIDLO : Použitím DISTINCT nic nezkazíš! Příklad 5.10 : Vypsat celkový počet dosud vypůjčených různých knih pro každého čtenáře SELECT VÝPUJČKA.ČisloČ, JménoČ, PříjmeníČ, COUNT (DISTINCT InvCis) AS knihy_celkem FROM VÝPUJČKA, ČTENÁŘ WHERE VÝPUJČKA.ČísloČ = ČTENÁŘ. ČísloČ GROUP BY VÝPUJČKA.ČisloČ Příklad 5.11a : Vypsat počty různých vydaných knih podle jednotlivých žánrů SELECT NázevŽ, COUNT (DISTINCT ISBN ) FROM ŽÁNR, KNIHA WHERE ČísloŽ = Žánr GROUP BY Žánr Příklad 5.11b : Vypsat počty různých knih (ne výtisků), které jsou k dispozici v knihovně podle jednotlivých žánrů
SELECT NázevŽ, COUNT (DISTINCT VÝTISK.ISBN ) FROM ŽÁNR, KNIHA, VÝTISK WHERE ČísloŽ = Žánr AND KNIHA.ISBN = VÝTISK.ISBN GROUP BY Žánr Příklad 5.12a : Vypsat jména čtenářů, kteří přečetli víc jak 500 knih SELECT PříjmeníČ, JménoČ, COUNT (DISTINCT InvCis) FROM VÝPŮJČKA, ČTENÁŘ WHERE VÝPŮJČKA.ČísloČ = ČTENÁŘ.ČísloČ GROUP BY VÝPŮJČKA.ČísloČ HAVING 500 < COUNT (DISTINCT InvCis ) Příklad 5.12b : Vypsat jména čtenářů, kteří přečetli víc jak 500 knih SELECT PříjmeníČ, JménoČ, COUNT (DISTINCT InvCis) AS počet FROM VÝPŮJČKA, ČTENÁŘ WHERE VÝPŮJČKA.ČísloČ = ČTENÁŘ.ČísloČ GROUP BY VÝPŮJČKA.ČísloČ HAVING 500 < počet Příklad 5.12c : Vypsat jména čtenářů, kteří přečetli víc jak 500 knih SELECT PříjmeníČ, JménoČ FROM VÝPŮJČKA, ČTENÁŘ WHERE VÝPŮJČKA.ČísloČ = ČTENÁŘ.ČísloČ
GROUP BY VÝPŮJČKA.ČísloČ HAVING 500 < COUNT (DISTINCT InvCis ) Příklad 5.13 : Celkové měsíční přírůstky v roce 2000 SELECT MONTH(DatNákup) AS Měsíc, COUNT(InvCis) AS Počet, SUM(Cena) AS Celkem_Kč FROM VÝTISK WHERE YEAR(DatNákup) = 2000 GROUP BY Měsíc Příklad 5.14 : Celkový denní počet výpůjček v říjnu 2002 SELECT DatPůjčeno, COUNT(InvCis) AS Denní_výpůjčka FROM VÝPŮJČKA WHERE DatPůjčeno BETWEEN 01.10.02 AND 31.10.02 GROUP BY DatPůjčeno Příklad 5.15 : Celkový měsíční počet výpůjček pro každého čtenáře jednotlivě SELECT PříjmeníČ, JménoČ, YEAR(DatPůjčeno) AS Rok, MONTH(DatPůjčeno) AS Měsíc, COUNT(InvCis) AS Výpůjčka FROM VÝPŮJČKA, ČTENÁŘ WHERE VÝPŮJČKA.ČísloČ = ČTENÁŘ.ČísloČ GROUP Rok,, Měsíc, VÝPŮJČKA.ČísloČ
Příklad 5.16a : Názvy knih, které přečetlo víc jak 200 čtenářů SELECT ISBN, NázevK FROM KNIHA K WHERE 200 < (SELECT COUNT (*) FROM VÝPŮJČKA V, VÝTISK T WHERE V.ISBN = T.ISBN AND C.ČísloČ = V. ČísloČ AND C.ČísloK = V.ČísloK) Příklad 5.16b : Názvy knih, které přečetlo víc jak 200 čtenářů SELECT ISBN, NázevK FROM KNIHA K, VÝPŮJČKA V, VÝTISK T WHERE V.ISBN = T.ISBN AND C.ČísloČ = V. ČísloČ AND C.ČísloK = V.ČísloK GROUP BY V. ČísloČ HAVING 200 < Count(InvCis) Příklad 5.17a : Průměrný celkový počet vypůjčených knih připadajících na jednoho čtenáře v roce 2002 SELECT COUNT(InvCis) / COUNT(DISTINCT ČísloČ) AS Počet FROM VÝPŮJČKA WHERE YEAR(DatPůjčeno) = 2002
Příklad 5.17b : Průměrný počet vypůjčených knih během jedné návštěvy knihovny (tj. v jednom dni) připadajících na jednoho čtenáře Nejde realizovat jedním příkazem jedná se totiž o průměr z celkových počtů tj. agregační funkce AVG by se měla použít na agregační fci COUNT není přípustné INSERT INTO POCTY (Datum, Čtenář, Počet) SELECT DatPůjčeno, ČísloČ, Počet= COUNT(InvCis) FROM VÝPŮJČKA GROUP BY DatPůjčeno, ČísloČ SELECT AVG(Počet) AS Prům_výpůjčka FROM POCTY Příklad 5.18a : Největší knihomol (čtenář, co si půjčil nejvíc knih) SELECT TOP 1 PříjmeníČ, JménoČ, COUNT(InvCis) AS Počet FROM VÝPŮJČKA, ČTENÁŘ WHERE VÝPŮJČKA.ČísloČ = ČTENÁŘ.ČísloČ GROUP BY VÝPŮJČKA.ČísloČ ORDER BY Počet DESCENDING
Příklad 5.18b : Největší knihomol (čtenář, co si půjčil nejvíc knih) INSERT INTO PŘEČTENO (Příjmení, Jméno, Počet) SELECT PříjmeníČ, JménoČ, Počet = COUNT(InvCis) FROM VÝPŮJČKA, ČTENÁŘ WHERE VÝPŮJČKA.ČísloČ = ČTENÁŘ.ČísloČ GROUP BY VÝPŮJČKA.ČísloČ SELECT Příjmení, Jméno FROM PŘEČTENO WHERE Počet = SELECT MAX(Počet) FROM PŘEČTENO Příklad 5.19a : Autoři, kteří napsali více jak 5 knih SELECT JménoA, PříjmeníA FROM AUTOR, KNIHA WHERE ČísloA = Autor GROUP BY ČísloA HAVING 5 < COUNT(*) Příklad 5.19b : Autoři, kteří napsali více jak 5 knih SELECT JménoA, PříjmeníA FROM AUTOR WHERE 5 < ( SELECT COUNT (DISTINCT ISBN) FROM KNIHA WHERE ČísloA = Autor)
Příklad 5.20a : Vypsat čtenáře, kteří mají vypůjčeny nějaké knihy a současně mají v aktuálním měsíci rezervaci SELECT DISTINCT ČísloČ FROM REZERVACE WHERE MONTH(YEAR) = MONTH(DatRez) AND ČísloČ IN ( SELECT ČísloČ FROM VÝPUJCKA WHERE DatVráceno IS NULL ) Příklad 5.20b : Lze napsat i v opačném pořadí podmínek SELECT DISTINCT ČísloČ FROM VÝPUJCKA WHERE DatVráceno IS NULL AND ČísloČ IN (SELECT ČísloČ FROM REZERVACE WHERE MONTH(YEAR) = MONTH(DatRez) ) Příklad 5.21 : Vypsat všechny výtisky vydané v GB, SRN a FR SELECT ISBN, InvCis, NázevK, StátN FROM KNIHA, VÝTISK, NAKLADATELSTVÍ WHERE KNIHA.ISBN = VÝTISK.ISBN AND Nakladatel = ČísloN AND StátN IN ( GB, SRN, FR ) Příklad 5.22a : Vypsat jména čtenářů, kteří mají rezervovanou knihu Průvodce SQL
(dva poddotazy) SELECT JménoČ, PříjmeníČ FROM ČTENÁŘ C WHERE ČísloČ IN ( SELECT ČísloČ FROM REZERVACE WHERE ISBN = ( SELECT ISBN FROM KNIHA WHERE NázevK = Průvodce SQL ) ) Příklad 5.22b : Vypsat jména čtenářů, kteří mají rezervovanou knihu Průvodce SQL (jeden poddotaz) SELECT JménoČ, PříjmeníČ FROM ČTENÁŘ C WHERE ČísloČ IN ( SELECT ČísloČ FROM REZERVACE R, KNIHA K WHERE K.ISBN = R.ISBN AND NázevK = Průvodce SQL ) Příklad 5.22c : Vypsat jména čtenářů, kteří mají rezervovanou knihu Průvodce SQL SELECT JménoČ, PříjmeníČ FROM ČTENÁŘ C, REZERVACE R, KNIHA K WHERE C.ČísloČ = R.ČísloČ AND R.ISBN = K.ISBN AND NázevK = Průvodce SQL )
Příklad 5.22d : Vypsat jména čtenářů, kteří mají rezervovanou knihu Průvodce SQL SELECT JménoČ, PříjmeníČ FROM ČTENÁŘ INNER JOIN REZERVACE INNER JOIN KNIHA ON REZERVACE.ISBN = KNIHA ISBN ON ČTENÁŘ.ČísloČ = REZERVACE.ČísloČ WHERE NázevK = Průvodce SQL Příklad 5.23 : Vypsat čísla všech knih dražších než jakákoliv kniha vydaná u nás SELECT InvCis FROM VÝTISK WHERE Cena > ALL (SELECT V.Cena FROM VÝTISK V, NAKLADATELSTVÍ N WHERE StátN = CZ AND N.Číslo = V.Nakladatel) Příklad 5.24a : Vypsat knihy, které jsou rezervovány SELECT DISTINCT Název FROM KNIHA WHERE ISBN IN ( SELECT ISBN FROM REZERVACE )
Příklad 5.24b : SELECT DISTINCT Název FROM KNIHA WHERE EXISTS (SELECT * FROM REZERVACE WHERE KNIHA.ISBN = REZERVACE.ISBN) Příklad 5.24c : SELECT DISTINCT Název FROM KNIHA INNER JOIN REZERVACE ON KNIHA.ISBN = REZERVACE.ISBN Příklad 5.25a : Vypsat čísla čtenářů, kteří si letos ještě nic nepůjčili SELECT ČísloČ FROM ČTENÁŘ C WHERE NOT EXISTS ( SELECT * FROM VÝPŮJČKA V WHERE YEAR(V.DatPůjčeno) = YEAR (DATE ()) AND C.ČísloČ = V.ČísloČ AND V.ČísloK=C.ČísloC) Příklad 5.25b : Vypsat čísla čtenářů, kteří si letos ještě nic nepůjčili SELECT ČísloČ FROM ČTENÁŘ WHERE ČísloČ NOT IN (SELECT ČísloČ FROM VÝPŮJČKA WHERE YEAR(DatPůjčeno) = YEAR (DATE ()))
Příklad 5.26 : Kniha, která se nikdy nepůjčila SELECT Název FROM KNIHA WHERE ISBN NOT IN (SELECT DISTINCT VÝTISK.ISBN FROM VÝPŮJČKA, VÝTISK WHERE VÝPŮJČKA.InvCis = VÝTISK.InvCis) Příklad 5.27 : Vypsat čtenáře, kteří mají půjčenou nebo rezervovanou knihu o PHP SELECT ČísloČ, JménoČ, PříjmeníČ FROM REZERVACE, KNIHA, ČTENÁŘ WHERE ČTENÁŘ.ČísloČ = REZERVACE.ČísloČ AND KNIHA.ISBN = REZERVACE.ISBN AND NázevK LIKE %PHP% UNION SELECT ČísloČ, JménoČ, PříjmeníČ FROM VYPUJČKY, VÝTISK, KNIHA, ČTENÁŘ WHERE ČTENÁŘ.ČísloČ = REZERVACE.ČísloČ AND KNIHA.ISBN = VÝTISK.ISBN AND VYPUJČKY.InvCis = VÝTISK.InvCis AND NázevK LIKE %PHP% Příklad 5.28 : Zjistit celkovou hodnotu knih v knihovně SELECT SUM(Cena) AS Celkova_Cena FROM VYTISK
Problémy k zamyšlení : P1 : Najít knihu s největším počtem výtisků P2 : Vypsat seznam autorů, u nichž má knihovna k dispozici všechny jejich vydané publikace P3 : Vypsat seznam autorů, kteří nejsou v knihovně vůbec zastoupeni žádným výtiskem P4 : Najít a vypsat název nejfrekventovanějšího žánru Práce s řetězci Podmínky typu atribut LIKE řetězcová konstanta Autor LIKE JI% Autor LIKE K_ Autor LIKE %p Adresa LIKE %Budějovice%