Wednesday, June 22, 2011

SW: Relacni algebra a SQL

Zmyslom kazdej databazy je poskytovat data, ktore su ziskavane formulovanim dotazov na databazu. Dotazy su zvycajne formulovane v dotazovacom jazyku, ktory musi byt dostatocne silny na to, aby umoznil ziskat lubovolnu (zmysluplnu) podmnozinu dat z relace/tabuliek. Kazdy dotazovaci jazyk vyuziva symbolov popisujucich schemy relace ako zakladne konstrukty jazyka.

Pred tym, ako zacneme tvorit dotazy, tak musime najprv zistit, co to je dotaz. Dotaz je vlastne vymedzenie konkretnej instancie dat. Jediny dotaz moze byt vyjadreny niekolkymi vyrazmi v dotazovacom jazyku. Taketo vyrazy su si ekvivalentne. V klasickych modeloch moze byt vysledkom dotazu pouze podmnonzina dat z databaze - a teda hodnoty priamo obsiahnute v DB. V rozsirenych modeloch moze vysledok dotazu obsahovat aj odvodene data - vypocty, statistiky, apod., ziskane z povodnych dat.

V relacnom modele vyuzijeme relacnu algebru a relacny kalkul. Relacni algebra vyuziva mnozinu operacii nad relacemi a relacny kalkul je databazovym rozsirenim predikatovej logiky 1. radu.


Relacna algebra je mnozina unarnych a binarnych operacii na relaci so schemami, ktorej vysledkom je opat relace a jej schema. Dotazovaci jazyk, ktory umoznuje realizovat vsetky operacie relacnej algebry nazyvame relacne uplny.


Aby sme si zivot ulahcili a tiez aj pochopenie mnozinologie s nazvom relacna algebra, tak as budeme venovat aj SQL. SQL, alebo structured query language, je standardnym jazyk pre pristup k relacnym databazam. Povodne bola snaha o co najprirodzenejsie formulovania poziadavkov, cim sa ma na mysli, pre ludi to najpochopitelnejsie. Dotazy v SQL su vlastne vetami (Select something from somewhere ...). SQL je jazykom, ktory obsahuje konstrukty pre DLL a DML, transakcie, moduly, definiciu IO apod. Komercne systemy zvacsa nejakym sposobm implementuju SQL 99, ale nie striktne. Existuju rozsirenia SQL pre proceduralnu, transakcnu a dalsiu funkcionalitu, napr. Transact-SQL a PL-SQL. 


Prejmenovanie atributov   ->  
Brando je odstraneny, pretoze ak by zostal v relaci R4, tak by
R4 nesplnovala podmienku neduplicitnych n-tic
a teda podmienku relace! 
- unarna operacia
- v tomto pripade sa s datami nic nedeje, jedna sa len o premenovanie atributov

SQL: select herec as hvezda from R3

Zjednotenie   ∪     R1 ∪ R2  
- binarna operacia
- vyzaduje kompatibilne schemy

SQL: select * from R1 UNION select * from R2

Prienik                   R1 ∩ R2  
- binarna operacia
- vyzaduje kompatibilne schemy
- z povahy prieniku nebudu vo vysledku duplikaty

SQL: select * from R1 INTERSECT select * from R2 

Rozdiel          -          R1 \ R2 
- binarna operacia
- vyzaduje kompatibilne schemy
- mnozinova operacia rozdiel A \ B = vsetky prvky, ktore patria do mnoziny A a neptria do mnoziny B, takze sa vlastne spravi A ∩ B a ten vysledok sa vyhodi z A

Napriklad chceme vsetky kina, okrem tych, kde hraju nieco s Brandom.

KINA \ {FILM(HEREC = "BRANDO")[JMENO_F] * MA_NA_PROGRAMU}[NAZEV_K], ludsky by sme povedali, ze sme od mnoziny vsetkych kin odpocitali mnozinu kin, kde hraju nieco s brandom.

SQL: select nazev_k from kina MINUS select f.nazev_k from film f natural join ma_na_programu where jmeno_f like %BRANDO%

Kartezsky sucin     x      R1 x R2
- binarna operacia
- vysledkom je mnozina vsetkych usoriadanych dvojic, ktorych prvy prvok patri do R1 a druhy do R2
- tato operacia vykonstruuje nove schema, zlozene z atributov obidvoch schem - ak existuju rovnake mena atributov, tak sa pouzije rozlisenie v teckovej notacii   -- tato luxusna prupovidka vravi, ze ak sa dva stlpce volaju rovnako, tak vysledok bude R1.meno a R2.meno
- ak robime kartezsky sucin s totoznymi operandami, teda R1 x R1, tak musime ale operandy premenovat (urcite v RA, nie som isty v SQL, mam pocit, ze tam by sa to zvladlo)

SQL: select * from R1 cross join R2

Projekce  R[B]
- unarna operacia
- jedna sa o vyber stlpcov relace
- vpravo ukazkova projekce z mnoziny R1 na atributy Jmeno_F a DATUM
- schema R2 vznikla odstranenim hodnot atributov R2 \ R1
- v R2 sa neozbrazia duplicity, takze ak by sme spravili dotaz R2 := R1[NAZEV_K], tak odhodime vsetky stlpce okrem NAZEV_K a vysledok bude len 1x Mir

SQL: Select jmeno_f, datum from R1

RA - selekce       j       
- unarna operacia
- vyber tych prvkov z R, ktore splnuju logicku podmienku j(u)
- podmienka sa zadava boolovym vyrazom a teda pomocou spojek and, or, not
- v projekci sme vyberali stlpce, teraz budeme vyberat riadky 

- v priklade je podmienka na rovnost nazvu kina


SQL: select * from ma_na_programu where nazev_k like 'Mir'

Prirodzene spojenie    *    R1*R2
- binarna operacia
- je spojenim prvkov relace cez rovnake hodnoty, teda prirodzenym spojenim je spojenie cez rovnost - vysledne relace obsahuje tie zaznamy, ktore sa zhoduju v polozkach, nad ktorymi sa relace vykonava 
- ak prienikom R1 a R2 je prazdna mnozina, tak prirodzene spojenie je vlastne kartezskym sucinom



SQL: Select * from film NATURAL JOIN  r2
SQL: Select * from film f JOIN  r2 r on f.jmeno_f = r.jmeno_f
SQL: Select * from film JOIN  r2 USING(jmeno_f)

Vnuntorne spojenie  (inner join)   Q
- je to obecnejsie prirodzene spojenie 
- spojuje sa cez predikat Q aplikovany na jednotlivych atributoch  <R*, R(A)>[t1Qt2]<S*, S(B)>

mozme mat aj vonkajsie spojenie, takzvanu outer join. Outer join vyuziva doplnenie metahodnoty null k prvkom, ktore nebolo mozne normalne spojit a teda neobjavili by sa vo vnutornom spojeni. 

majme relace Lety a Lietadlo


Chceme najst take lietadla, ktorymi mozu letiet cestujuci tak, aby pocet neobsadenych miest bol mensi ako 200. 

Vnutorne spojenie:
Lety[Lety.pocetCestujucich <= Letadlo.kapacita AND Lety.pocetCestujucich +200 > Letadla.kapacita]Letadla

SQL: select * from lety INNER JOIN letadla on pocet_cestujucich <= kapacita where (pocet_cestujuich + 200) > kapacita)

Vysledok vnutorneho spojenia je v bielych riadkoch.V tomto spojeni nas zaujimaju vsetky atributy, narozdiel od laveho/praveho spojenia. 


Vonkajsie spojenie je mozne pouzit napriklad na dotaz na tie lety a lietadla, ktore nevyhovuju nasmu dotazu. V lavom vonjasom spojeni sa doplnuju null zprava a v pravom sa doplnuju zlava. V plnom sa doplnuju z oboch stran. 

Lave a prave vnutorne polospojenie 
- zaujima nas len lava alebo prava strana 

lave polospojenie : R < t1 Q t2 ] S
prave polospojenie : R [ t1 Q t2 S
lave priordzene polospojenie : R <* S
prave priordzene polospojenie : R *> S

Delenie 
- binarna operacia 
- podla mudrej poucky sa podiel relaci R a S s atributmi A a B da definovat takto: 

<R, R(A)> / <S, S(B podmnozina A )> = <{t | pre vsetky x z S (t zretazenie s) patri R }, A - B>

t zretazenie s znamena zretazenie prvkov za sebou z t a s. Ale aj tak, mne ta definicia vela nedala. 

Delenie vracia tie prvky z R, ktore maju na A rovnake atributy a na B obsahuju vsetky prvky z S. Vyuzijeme to tam, kde musime vybrat tie riadky tabulky, ktorych projekce su obsiahnute vovsetkych riadkoch tabulky. Alternativnou deifnicou by bolo, ze R / S = R[A-B] - ((R[A-B]  x  S) - R)[A-B]

V priklade sme spravili podiel FILMY / HERCI[JMENO_HERCE] a dostaneme vysledok Titanic ako jediny film, kde hrali vsetci herci. 



Doporucujem sa pozriet aj na dalsie dva priklady delenia 






Relacny algebru by sme mali, takze sa mozme pozriet, co nam ponuka SQL, ktore nam uz asi je srdce trochu blizsie. 

Nic sa nestane, ak si zopakujeme, ze SQL je dotazovaci jazyk pre pracu s datami v relacnych databazach. Podporuje 
  • DDL - data definition language, ktory definuje data - vytvaranie tabuliek, schem a podobne. Tieto prikazy nam umoznuju aj vytvorenie pohladov, indexov 
    • CREATE (table | view as select .. )
    • ALTER 
    • DROP
  • DML - data modification language, ktory sluzi pre pracu s datami - pridavanie dat, vyber, aktualizacia, mazanie a pod. 
    • SELECT
    • INSERT
    • UPDATE
    • DELETE
    • EXPLAIN FOR - specialny prikaz, ktory zobrazuje postup spracovania SQL prikazu. Je vhodny pri optimalizacii prikazov 
    • SHOW - zobrazuje databazy, tabulky a definicie 
  • TCL - data control language - prikazy pre riadenie dat
    • GRANT {ALL PRIVILEGES ON objekt TO identifikator}
    • REVOKE
    • BEGIN
    • COMMIT
    • ROLLBACK
Typy dat v SQL
  • presne numericke typy, integer, smallint, numeric, decimal
  • aproximativne numericke typy, float, real, double precision
  • znakove retazce, character
Agregacne funkcie 
  • count
  • sum
  • max
  • avg
  • min
A dalsie 
  • GROUP BY ako vyberove kriterium v kombinacii s HAVING
  • LIKE, IN, ANY, ALL, SOME ako predikaty 
  • EXISTS - true ak mnozina za kvatifikatorom je neprazdna
  • UNION, INTERSECT, DISTINCT, EXCEPT ALL ako mnozinove operacie 

Vytvorenie tabulky pomocou DDL 
CREATE TABLE vyrobok (
  id INTEGER CONSTRAINT pk PRIMARY_KEY,  #id bude primarnym klucom s nazvom pk 
  nazev VARCHAR(128) UNIQUE,            #nazev bude unikatny
  cena DECIMAL(6,2) NOT NULL,           #cena bude mat 6 miest pred radovou ciarkou a 2 po
  datum_vyroby DATE,
  je_na_sklade BOOLEAN true,                #bude to true|false a default hodnota je true
  hmotnost FLOAT,                                   #pohybliva ciarka
  vyrobce INTEGER REFERENCE vyrobce(id) #cudzi kluc do tabulky vyrobce 
}

riadok 
vyrobce INTEGER REFERENCE vyrobce(id) 
 
sa dal vyriesit ako 
CONSTRAINT fk FOREIGN_KEY (vyrobce) REFERENCES vyrobce(id)

CREATE TABLE vyrobce {
  id INTEGER PRIMARY_KEY,   #primary key nie je pomenovany 
  meno_vyrobcu VARCHAR(128),
  sidlo VARCHAR(128)
}

ak by sme sa do tabulky vyrobok pokusili vlozit zaznam s neexistujucim vyrobcom, tak nastane porusenie integrity cudzich klucov. V takom pripade, bud dostaneme chybovu hlasku, alebo sa vykona referencna akcia 

referencnu akciu mozme definovat pomocu 

ON UPDATE/ON DELETE CASCADE/SET NULL/SET DEFAULT/NO ACTION

teda napriklad vyrobce INTEGER REFERENCE vyrobce(id) ON DELETE CASCADE

zaujimavu vlastnost ma napriklad prikaz CHECK, ktory mozme skotrolovat hodnoty vkladane to tabulky 

CONSTRAINT chk CHECK ((id = 0 or id > ALL (SELECT id FROM vyrobek) AND hmotnost >0))

Dalsim zaujimavym jazykom okrem SQL je QBE, co je skratka pre Query By Example. Jedna sa o jednoduchy dotazovaci jazyk, ktory umoznuje eliminovat duplicity v odpovedi a zachovava referencne integrity. Je to prvy graficky dotazovaci jazyk, kde sa dotaz modeluje vizualne za pouzitia tabuliek, zadavania podmienok, prikazov a prikladov dat. Mnozstvo GUI dnes vyuziva QBE. Povodne bol zamerany len na ziskavanie dat, ale vyvinulo sa to do mieri, kde podporuje aj (cast?) DML