var BrothersNames = new Array("Ochrana dat v datab_25E1z_25EDch a (nejen) bezpe_25E8nostn_25ED probl_25E9my (1.d_25EDl)","Ochrana dat v datab_25E1z_25EDch a (nejen) bezpe_25E8nostn_25ED probl_25E9my (2.d_25EDl)","SQL v praxi aneb bezpeΦnostnφ oddech","");
var BrothersIDs = new Array("140","142","146","");
//=====INFO======
ItemName='Article146';
InIFrame='No';
TableNum=2;
ItemID=146;
ArticleType='3';
Action='articles'
ItemTitle='SQL v praxi aneb bezpeΦnostnφ oddech';
ItemComment='SQL v praxi aneb bezpeΦnostnφ oddech';
ArticleHead('SQL v praxi aneb bezpeΦnostnφ oddech', 'Michal Till', 'Michal.Till_40Seznam.cz', '28.2.2002', '19:36:05', 'Nßvod');
Intro('Zkratka SQL znamenß Structured Query Language, do ΦeÜtiny bychom to asi nejlΘpe p°elo₧ili jako strukturovan² dotazov² jazyk. Pokud tento jazyk chßpeme jako protokol, tak bychom ho za°adili do SpojovΘ vrstvy referenΦnφho sφ¥ovΘho modelu ISO/OSI. Jazyk SQL slou₧φ pro komunikace aplikace s databßzφ. Optimßlnφ uschovßnφ a sprßva velkΘho objemu dat je velmi specializovanß v∞c a nenφ mo₧nΘ, aby se jφ ka₧d² program zab²val sßm. Vlastnφ databßzov² stroj je tedy odd∞len² program a pro \"dolovßnφ\" dat z n∞ho byl tedy vytvo°en tento, vφcemΘn∞ standardizovan² jazyk.');
Za cφl tohoto Φlßnku jsem si vytyΦil seznßmenφ Φtenß°e s prßcφ s daty pomocφ jazyka SQL. Rozhodn∞ bych necht∞l suplovat n∞jakou referenΦnφ p°φruΦku, co nejvφce bych se zam∞°il na principy fungovßnφ celΘho systΘmu. Naopak klasickΘ p°φkazy nap°. pro vytvo°enφ u₧ivatele, tabulky apod. bych spφÜe p°enechal jin²m zdroj∙m, nebo¥ jde o mΘn∞ zajφmavΘ p°φpady, kdy je pot°eba spφÜe znßt syntaxi ne₧ porozum∞t v∞ci.
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
Ka₧d² databßzovΘ prost°edφ pracuje s tabulkami, v tomto p°φpad∞ je to zßkladnφ "·lo₧iÜt∞ dat". Podobnost s tabulkami, jak je znßme z tabulkov²ch kalkulßtor∙ nenφ nßhodnß, v naÜem p°φpad∞ se ale kladou na jistΘ aspekty prßce mimo°ßdnΘ nßroky, pro kterΘ programy typu Excel nejsou urΦeny. Prßv∞ proto je p°edstava databßze jako₧to jedinΘ tabulky mylnß, jednß se o soustavu tabulek s logick²mi vazbami. Vytvo°me si nynφ pro demonstraci fiktivnφ Ükolu a jejφ zam∞stnance.
Promφtneme-li si popisovanou firmu do reßlnΘ situace v Excelu, zjistφme, ₧e data by byla organizovßna jinak. Byla by pouze jedinß tabulka se t°emi sloupci a jmΘna jednotliv²ch p°edm∞t∙ by se opakovala na jednotliv²ch °ßdcφch. Zde je mezi sloupci U╚ITEL╔.P°edm∞t a P╪EDM╠TY.╚φslo relace. Je to logickß vazba, °φkajφcφ, ₧e hodnota ve sloupci P°edm∞t znaΦφ Φφslo °ßdku v tabulce P╪EDM╠TY (zde se nßzvoslovφ teorie trochu liÜφ s populßrn∞ nauΦnou literaturou, k Φemu₧ se jeÜt∞ vrßtφm). Tφm je nap°φklad pan Durych jednoznaΦn∞ svßzßn s p°edm∞tem Matematika (stejn∞ jako pan Adßmek), panφ ╚ervenß s d∞jepisem apod. Co ale p°φpad zam∞stnankyn∞ HßjkovΘ? NULL v databßzφch p°edstavuje jakΘsi "prßzdno", sloupec v tΘto °ßdce nenab²vß ₧ßdnΘ hodnoty a panφ Hßjkovß tedy ₧ßdn² p°edm∞t nevyuΦuje. Äßdnß anomßlie nenφ takΘ Φtvrt² °ßdek v tabulce P╪EDM╠TY, fyziku prost∞ nikdo nevyuΦuje. Abychom pochopili relaΦnφ model ·pln∞, je pot°eba k tomuto nßzornΘmu p°φkladu "dobalit" trochu d∙le₧itΘ teorie.
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
Jak je z popisovanΘho principu patrnΘ, ka₧d² zam∞stnanec m∙₧e uΦit pouze jeden p°edm∞t, ale ka₧d² p°edm∞t m∙₧e b²t vyuΦovßn vφce lidmi. Takov²to vztah oznaΦujeme jako 1:N. Vedle toho existujφ jeÜt∞ dv∞ dalÜφ formßlnφ oznaΦenφ, jednoduÜÜφ 1:1 a slo₧it∞jÜφ N:M. Prvn∞ jmenovanΘmu vztahu odpovφdß situace dvou tabulek, ve kter²ch jsou v₧dy dva °ßdky jednoznaΦn∞ svßzßny. Uva₧me nap°φklad tabulku T╪═DY se sloupcem T°φdnφ_uΦitel. Nenφ mo₧nΘ, aby jedna t°φda m∞la t°φdnφch uΦitel∙ vφce a ka₧d² m∙₧e b²t t°φdnφ uΦitel maximßln∞ jednΘ t°φdy. Naopak vztah M:N popisuje p°esn∞ opaΦnou situaci. Zkusme poopravit p∙vodnφ dv∞ tabulky tak, aby ka₧d² vyuΦujφcφ mohl uΦit vφce p°edm∞t∙. N∞komu by se mohlo zdßt, ₧e nejde na nßÜ relaΦnφ model aplikovat, ale nenφ to pravda. Musφme akorßt pou₧φt mal² trik, kter²m spojenφ dvou relacφ 1:N v novΘ tabulce VYU╚UJE. Pokud nebude uvedeno jinak, tak se v textu se nadßle budu odvolßvat v₧dy na poslednφ uveden² p°φklad.
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
Tabulka U╚ITEL╔ :
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
<PRE>
╚φslo JmΘno Plat Narozenφ Hodin
1 Durych 8000 1954-11-05 35
2 Adßmek 8000 1967-05-03 32
3 Liborec 11000 1980-09-28 38
4 ╚ervenß 9000 1971-10-10 29
5 Hßjkovß 10500 1979-01-13 39
</PRE>
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
Tabulka P╪EDM╠TY:
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
<PRE>
╚φslo Popis
1 Matematika
2 Zem∞pis
3 D∞jepis
4 Fyzika
</PRE>
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
Tabulka VYU╚UJE:
<PRE>
UΦitel P°edm∞t
1 1
1 4
2 1
3 2
4 3
4 1
</PRE>
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
Tabulka VYU╚UJE je zde nedφlnß spojovacφ Φßst. UrΦuje, ₧e uΦitel s Φφslem 1 uΦφ p°edm∞ty 1 a 4, uΦitel Φ. 2 uΦφ p°edm∞t Φ.3, Φ. 3 uΦφ p°edm∞t Φ.2 a Φ. 4 uΦφ p°edm∞ty Φ.3 a Φ.1. Pro takov²to popis mezi vztahy tabulek se pou₧φvajφ identifikßtory, jejich₧ ·Φelem je jednoznaΦn∞ identifikovat dan² °ßdek tabulky. Jeho hodnota proto v rßmci jednΘ tabulky musφ b²t jedineΦnß, nesmφ se opakovat. NejΦast∞ji to b²vajφ Φφsla - v databßzφch se toti₧ dß nastavit automatickΘ zvyÜovßnφ a dopl≥ovßnφ hodnoty. P°i p°ijmutφ novΘho kantora by tak systΘm automaticky doplnil hodnotu 5 do identifikßtoru Φφslo v tabulce U╚ITEL╔. JednoznaΦn² a nem∞nn² identifikßtor, kter² mß navφc nejkratÜφ dΘlku, naz²vßme primßrnφ klφΦ. Pokud nenφ ₧ßdn² sloupec unikßtnφ, m∙₧e b²t primßrnφ klφΦ takΘ tzv. slo₧en², kdy ho jakoby tvo°φ vφce sloupc∙ najednou. Pou₧itφ primßrnφho klφΦe v cizφ tabulce k vytvo°enφ vztahu naz²vßme cizφ klφΦ. V prvnφm p°φkladu je nap°φklad v tabulce uΦitel∙ sloupec ╚φslo klφΦem primßrnφm, zatφmco sloupec P°edm∞t klφΦem cizφm.
P°φkaz SELECT je jist∞ nejd∙le₧it∞jÜφ Φßstφ jazyka SQL, v knihßch o databßzφch obvykle takΘ zabφrß v∞tÜinu prostoru. V²sledkem vykonßnφ tohoto p°φkazu je tabulka vÜech °ßdk∙, kterß vyhovujφ dan²m kritΘriφm. Ta se potΘ p°edß programu, kter² dotaz vydal (nap°φklad PHP). Vlastnφ syntaxe mß n∞kolik Φßstφ, ze kter²ch jsou povinnΘ pouze dv∞. NejjednoduÜÜφ p°φklad m∙₧e vypadat nap°φklad takto :
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
<SPAN Class=CODE>SELECT * FROM U╚ITEL╔</SPAN>
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
Zde jsme tedy pou₧ili Φßsti SELECT a FROM. Hv∞zdiΦka zde zastupuje vÜechny sloupce tabulky, jak je z asi anglickΘ terminologie patrno, vybere se vÜe z tabulky uΦitel∙. V²slednß tabulka, kterou takov²to dotaz vyprodukuje se tedy bude shodovat s tabulkou uΦitel∙. Daleko v∞tÜφ sφla p°φkazu je ale v ostatnφch Φßstech. Uve∩me si proto nynφ p°φklad dalÜφ.
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
<SPAN Class=CODE>SELECT JmΘno, Plat FROM U╚ITEL╔ WHERE Plat<10000 ORDER BY JmΘno</SPAN>
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
NejlepÜφ vysv∞tlenφ mnoha SQL p°φklad∙ je Φasto jejich "p°eklad" do ΦeÜtiny. Tento kup°φkladu °φkß "vyber sloupce JmΘno a Plat z tabulky U╚ITEL╔ a to pouze ty, kde Plat je menÜφ ne₧ 10000, v²sledek se°a∩ (vzestupn∞) podle jmΘna (tedy abecedn∞). V²slednß tabulka bude tedy vypadat takto :
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
<PRE>
JmΘno Plat
Adßmek 8000
╚ervenß 9000
Durych 8000
</PRE>
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
Tφm ale nekonΦφ ani zßkladnφ mo₧nosti p°φkazu SELECT. Je nutnΘ podotknout, ₧e v Φßstech WHERE a ORDER BY mohou b²t daleko delÜφ v²razy. Tak nap°φklad chceme vybrat vÜechny zam∞stnance, kte°φ se narodili p°ed rokem 1970 a majφ plat menÜφ ne₧ 10 tisφc. Vedle toho jeÜt∞ chceme zjistit jejich hodinovou sazbu zaokrouhlenou na celß Φφsla. V²sledek chceme se°adit podle platu vzestupn∞ a v p°φpad∞ shody podle data narozenφ sestupn∞. Na dotaz
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
<SPAN Class=CODE>SELECT JmΘno, ROUND(Plat/Hodin) AS Na_Hodinu FROM U╚ITEL╔ WHERE (Plat<10000) AND (Narozenφ<'1970-01-01') ORDER BY Plat, Narozenφ DESC</SPAN>
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
odpovφ databßzov² stroj nßsledujφcφ tabulkou:
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
<PRE>
JmΘno Na_Hodinu
Adßmek 250
Durych 288
╚ervenß 310
</PRE>
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
Z tohoto dotazu jsme zjistili t°i novΘ poznatky. Jednak v Φßsti WHERE m∙₧e b²t jakkoliv dlouh² logick² v²rok, ve kterΘm je mo₧no pou₧φvat spojky jako AND, OR, XOR apod., dßle °adit se dß podle n∞kolika sloupc∙ a to sestupn∞ i vzestupn∞ (vÜimn∞te si, ₧e datov² typ datum mß syntaxi YYYY-MM-DD, aby se urychlilo °azenφ) a nakonec si m∙₧eme v Φφsti SELECT vytvo°it nov² sloupec z v²sledk∙ jakΘhokoliv matematickΘho v²razu.
Ka₧dß databßze samoz°ejm∞ takΘ musφ podporovat textovΘ datovΘ typy a to jak omezenΘ na dΘlku (varchar(dΘlka)) tak i "neomezen∞" dlouhΘ (text). Pro sloupce tohoto typu existuje specißlnφ operßtor LIKE, nebo¥ pou₧itφ klasickΘho rovnφtka nenφ v₧dy nejvhodn∞jÜφ. Typicky n∞kterΘ polo₧ky mohou b²t zapsßny velk²mi pφsmeny a p°esnΘ porovnßvßnφ by tedy shodu vyhodnotilo jako zßpornou. V²raz JmΘno LIKE 'Michal' je pravdiv² i pro hodnotu JmΘno='MICHAL'. Dßle se Φasto pou₧φvß wildcard (₧olφk) v podob∞ znaku % (procento) pro nahrazenφ jakΘkoliv mno₧iny znak∙ (i prßzdnΘho °et∞zce). Podmφnka JmΘno LIKE 'Michal %' vybere jak hodnotu "Michal", tak hodnotu "Michal Till" apod. JednotlivΘ znaky je mo₧nΘ nahradit otaznφkem (?). Ve v∞tÜin∞ databßzφ se °et∞zce uzavφrajφ do apostrof∙. Pokud je apostrof (pop°. jin² citliv² znak) souΦßstφ °et∞zce, je nutnΘ jej "vyescapovat" vlo₧enφm zp∞tnΘho lomφtka, tedy nap°φklad 'rock'n'roll'. DalÜφm typem, kter² je nutnΘ Φasto uzav°φt do apostrof∙ je typ datum. Podrobn∞jÜφ informace najdete v dokumentaci k vaÜemu databßzovΘmu systΘmu.
Modifikßtory jsou specißlnφ parametry Φßsti SELECT a zapisujφ se p°φmo za toto slovo, tedy SELECT [modifikßtor] ...pokraΦovßnφ dotazu. Implicitnφ modifikßtor mß nßzev ALL a znaΦφ, ₧e ve v²sledku budou uvedeny vÜechny hodnoty odpovφdajφcφ podmφnkßm. Pokud bychom cht∞li vynechat duplicitnφ hodnoty, pou₧ijeme modifikßtor DISTINCT, dotaz SELECT DISTINCT Plat FROM U╚ITEL╔ tak odpovφ tabulkou s hodnotami 8000 a 9000 - druh²ch 8000 je vynechßno. Podobn∞ pracuje i modifikßtor DISTINCTROW, rozdφl je akorßt v tom, ₧e vynechßvß pouze ty °ßdky, kterΘ se shodujφ ve vÜech polφch, tj. ne jenom v t∞ch vypisovan²ch. DalÜφ modifikßtory jsou implementovßny pouze v n∞kter²ch S╪BD. V MS JDBE je to nap°φklad TOP pro v²pis prvnφch n polo₧ek, kter² nap°φklad v MySQL nahrazuje Φßst LIMIT from,count p°φkazu SELECT.
A₧ do te∩ se ka₧d² dotaz t²kal pouze jedinΘ tabulky. V SQL je mo₧nΘ tabulky libovoln∞ spojovat a konstruovat tak daleko slo₧it∞jÜφ dotazy. Co kdy₧ nap°φklad chceme zjistit, kter² vyuΦujφcφ uΦφ jak² p°edm∞t? Je nutnΘ spojit vÜechny t°i tabulky. Spojenφ v databßzovΘm slova smyslu je totΘ₧ co kartΘzsk² souΦin. Nap°φklad KartΘzsk² souΦin mno₧iny M={a; b; c} a N={1; 2} je roven mno₧in∞ K={(a;1); (a;2); (b;1); (b;2); (c;1); (c;2)}, jednß se tedy o soubor vÜech mo₧n²ch kombinacφ prvk∙ z obou mno₧in. Podobn²m zp∙sobem funguje spojovßnφ tabulek, prvky jednotliv²ch mno₧in jsou °ßdky tabulek. V²sledn² souΦin pro tabulky s k, l a m °ßdky m∙₧e mφt tedy maximßln∞ k*l*m °ßdk∙. Uka₧me si Φßst souΦinu U╚ITEL╔ x P╪EDMETY x VYU╚UJE (byly vy°azeny irelevantnφ sloupce Plat, Narozenφ a Hodin)
Jak je vid∞t, v tabulce je mnoho irelevantnφch souΦin∙, nebo¥ z povahy relace je nutnΘ, aby se rovnala jednak polo₧ka U╚ITEL╔.╚φslo s polo₧kou VYU╚UJE.UΦitel, jednak polo₧ka VYU╚UJE.P°edm∞t s polo₧kou P╪EDM╠TY.╚φslo. P°es tyto sloupce tabulky spojφme. Ostatnφ °ßdky tedy nevyhovujφ reßlnΘ situaci a sprßvn² SQL dotaz (na jmΘno vyuΦujφcφho a nßzev p°edm∞tu) vypadß takto :
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
<SPAN Class=CODE>SELECT JmΘno, Popis FROM U╚ITEL╔, VYU╚UJE, P╪EDM╠TY WHERE (U╚ITEL╔.╚φslo=VYU╚UJE.UΦitel) AND (VYU╚UJE.P°edm∞t=P╪EDM╠TY.╚φslo) ORDER BY JmΘno</SPAN>
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
SystΘm by m∞l vrßtit sprßvnΘ p°i°azenφ jednotliv²ch p°edm∞t∙ k vyuΦujφcφm profesor∙m.
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
<PRE>
JmΘno Popis
Adßmek Matematika
╚ervenß D∞jepis
Durych Matematika
Durych Fyzika
Liborec Zem∞pis
</PRE>
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
Specißln∞ p°i spojovßnφ tabulek je nutnΘ brßt v ohled urΦitou kolizi nßzv∙ sloupc∙, kdy dv∞ tabulky nap°φklad obsahujφ sloupec ╚φslo. V Φßsti SELECT musφme p°i explicitnφm v²b∞ru urΦit, o jakou tabulku jde, tedy nap°. SELECT U╚ITEL╔.╚φslo FROM U╚ITEL╔, P╪EDM╠TY. V p°φpad∞ pou₧itφ hv∞zdiΦky (*) je nutnΘ spornΘ sloupce explicitn∞ p°ejmenovat pomocφ klauzule AS (SELECT *, U╚ITEL╔.╚φslo AS CisloUcitele ... ). Obdobn∞ musφme postupovat v Φßsti WHERE, aby stroj v∞d∞l, kter² sloupec mßme na mysli.
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
DalÜφ typickß situace, kterß m∙₧e nastat, je spojenφ jednΘ tabulky s tou samou. To pou₧ijeme v p°φpad∞, ₧e se jeden sloupec odkazuje na jin² °ßdek tΘ samΘ tabulky. V²sledn² souΦin tak bude mφt maximßln∞ m*m °ßdek, kde m je poΦet °ßdk∙ tabulky p∙vodnφ. Uva₧me nap°φklad situaci tabulky ZAM╠STNANCI, kterß mß pole ╚φslo (integer), JmΘno (string) a Nad°φzen² (integer). Pokud chceme zφskat seznam vÜech pracovnφk∙ se jmΘny jejich nad°φzen²ch, musφme ale dvojφ pou₧itφ stejnΘ tabulky odd∞lit, tedy v Φßsti FROM odd∞lφme a jinak pojmenujeme pracovnφky a jejich nad°φzenΘ. Pou₧ijeme nßsledujφcφ dotaz:
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
<SPAN Class=CODE>SELECT PODRIZENI.JmΘno AS JmΘno, SEFOVE.JmΘno AS èΘf FROM ZAM╠STNANCI PODRIZENI, ZAM╠STNANCI SEFOVE WHERE PODRIZENI.Nad°φzen²=SEFOVE.╚φslo</SPAN>
AgregaΦnφ funkce a seskupovßnφ v²sledk∙</DIV></font>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
Jazyk SQL podporuje velmi ÜirokΘ spektrum r∙zn²ch souhrnn²ch funkcφ, kterΘ se Φasto pou₧φvajφ v praxi. Mφsto dlouhΘho v²kladu si uve∩me jeden dotaz, kter² zodpovφ n∞kolik otßzek najednou.
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
<SPAN Class=CODE>SELECT SUM(Plat), MIN(Plat), MAX(PLAT), AVG(Plat) FROM U╚ITEL╔</SPAN>
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
Takov²to p°φkaz vybere celkovΘ platovΘ nßklady, minimßlnφ a maximßlnφ plat, pr∙m∞rn² plat a to v tomto po°adφ (do pr∙m∞rnΘ hodnoty funkce AVG se nezapoΦφtßvajφ hodnoty NULL). DalÜφ velmi Φasto pou₧φvanou funkcφ je COUNT(), kterß vracφ poΦet °ßdk∙ v danΘm sloupci. Celkov² poΦet vÜech uΦitel∙ Ükoly tak zjistφme dotazem SELECT Count(╚φslo) FROM U╚ITEL╔ (jako poΦet unikßtnφch ╚φsel uΦitel∙).
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
Tyto agregaΦnφ funkce majφ podobn∞ jako p°φkaz SELECT svoje modifikßtory a op∞t je implicitn∞ pou₧it ALL. Modifikßtor *, tedy nap°φklad COUNT(* P°edm∞t) znamenß, ₧e do v²sledku bude zapoΦφtßvßno vÜe, tedy i °ßdky s hodnotou NULL. Modifikßtor DISTICT mß obdobnou funkci jako u p°φkazu SELECT.
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
╚astß nßpl≥ prßce s databßzφ je zφskßvßnφ souhrnn²ch ·daj∙ urΦit²ch skupin, k Φemu₧ se pou₧φvß Φßst GROUP BY [v²raz]. Pro ka₧d² °ßdek v²pisu se [v²raz] vyhodnotφ a stejnΘ v²sledky se jakoby srazφ dohromady. Uva₧me nap°φklad dotaz na poΦet uΦitel∙ jednotliv²ch p°edm∞t∙, zde skupiny vytvo°φme podle stejn²ch Φφsel uΦitel∙. Nejprve spojφme dv∞ tabulky dohromady, obdobn∞ jako v jednom z p°edeÜl²ch p°φklad∙. Nßsledn∞ spoΦφtßme poΦet vÜech unikßtnφch uΦitel∙ pomocφ funkce COUNT().
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
<SPAN Class=CODE>SELECT Popis, COUNT(VYU╚UJE.UΦitel) FROM VYU╚UJE, P╪EDM╠TY WHERE (VYU╚UJE.P°edm∞t=P╪EDM╠TY.╚φslo) GROUP BY VYU╚UJE.UΦitel</SPAN>
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
SystΘm by m∞l odpov∞d∞t tabulkou jednotliv²ch p°edm∞t∙ a poΦtem uΦitel∙, kte°φ je uΦφ. S pou₧itφm GROUP BY se Φasto objevuje klauzule HAVING, kterß specifikuje dalÜφ podmφnku, kterou musφ v²b∞r spl≥ovat. Jejφ v²znam je obdobn² Φßsti WHERE ovÜem s tφm rozdφlem, ₧e p°i seskupovßnφ podmφnka HAVING omezuje jakoby ji₧ hotovß seskupeni, kdy₧to WHERE omezuje jednotlivΘ °ßdky jeÜt∞ p°ed jejich za°azenφm do skupin.
P°φklad s nad°φzen²mi zam∞stnanci popisuje situaci, kdy n∞kterΘ objekty jsou pod°φzenΘ jin²m. Uva₧me, zda je mo₧nΘ totΘ₧ ud∞lat pro v∞tÜφ hierarchickou hloubku. Spojovßnφ tabulek nßm p°estßvß slou₧it, u₧ jenom proto, ₧e poΦet °ßdk∙ souΦinu exponencißln∞ nar∙stß a pro hloubku n je roven k^n, kde k je poΦet °ßdk∙ p∙vodnφ tabulky. Zde se velmi Φasto pou₧φvß tzv. omezenφ intervalem, p°esto₧e mß svΘ podstatnΘ nev²hody, nenφ toti₧ mo₧nΘ stromovou strukturu stavit do nekoneΦna "nahoru" (tedy je omezenß hloubka) ani "do stran", tedy pod jeden objekt m∙₧e pat°it maximßln∞ koneΦn² poΦet objekt∙ jin²ch. Zkusme nap°φklad jednou tabulkou popsat adresß°ovou strukturu disku. Pro ·plnΘ zjednoduÜenφ polo₧me maximßlnφ hloubku adresß°e jako 5 a maximßlnφ poΦet adresß°∙ v jednom podadresß°i na 9. Tabulka STRUKTURA bude mφt v naÜem p°φpad∞ dva sloupce : JmΘno (string) a Hierarchie (integer s implicitnφ hodnotou 100000). Nejprve vlo₧φme domovsk² adresß° s p°ednastaven²m Φφslem hierarchie (dΘle jen Φφslo).
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
Dßle, pokud chceme p°idat slo₧ku pod tu domovskou (s Φφslem 100000), postupujeme nßsledovn∞. Deset podlo₧ek na tΘto ·rovni m∙₧e nab²vat Φφsel od 11...,12..,13... do 19... Tedy nejprve si zjistφme jejich poΦet (SELECT Count(╚φslo) from FROM STRUKTURA GROUP BY ╚φslo) a k n∞mu p°iΦteme jednu. PotΘ vezmeme Φφslo slo₧ky pod kterou chceme p°idßvat a prvnφ nenulovou Φφslici zleva nahradφme takto vypoΦten²m Φφslem. V²sledek s novou hodnotou zapφÜeme do databßze. Pokud se vßm zdß cel² mechanizmus slo₧it², podφvejte se, jak po napln∞nφ tabulky n∞kolika nßzorn²mi °ßdky bude vypadat v²pis SELECT * FROM STRUKTURA ORDER BY Hierarchie.
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
<PRE>
JmΘno Hierarchie
---------------------------
Home 100000
Software 110000
Windows 120000
Office 121000
Word 121100
Excel 121200
Data 120000
Dopisy 121000
Petr 121100
Michal 121200
</PRE>
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
Jak je vid∞t, Üest² znak zleva (jedniΦka) v implicitnφ hodnot∞ zajiÜ¥uje zachovßnφ pot°ebnΘ dΘlky. Pro vypsßnφ celΘho stromu struktury nynφ staΦφ vÜechny slo₧ky se°adit vzestupn∞ podle hierarchickΘho Φφsla. Pokud chceme v²pis zaΦφt nap°φklad od slo₧ky Dopisy, musφme si zjistit meznφ hodnoty. Ta menÜφ, A, je Φφslo poΦßteΦnφ slo₧ky, ta v∞tÜφ je pak Φφslo A, ve kterΘm je prvnφ nenulovß Φφslice zleva zv∞tÜena o 1 (s p°enosem na dalÜφ °ßd v p°φpad∞ 9+1=10). V p°φpad∞ dopis∙ by staΦilo zadat dotaz:
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
<SPAN Class=CODE>SELECT * FROM STRUKTURA WHERE (Hierarchy>=120000) AND (Hierarchy<130000) ORDER BY Hierarchy</SPAN>
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
Jedin² problΘm tohoto schΘmatu je v p°φpad∞ odebφrßnφ prvk∙, respektive p°i nßsledujφcφm p°idßvßnφ. Pokud bychom odebrali slo₧ku Word, tak by nßsledn∞ p°idanß slo₧ka Access m∞la Φφslo 121300, Φφm₧ bychom mohli deset voln²ch mφst zanedlouho vyΦerpat. Proto je nutnΘ p°i p°idßvßnφ brßt jakΘkoliv nepou₧itΘ Φφslo, nikoliv to "dalÜφ", jak bylo v ·vodu pro zjednoduÜenφ uvedeno.
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
Z vlastnφ programßtorskΘ praxe mohu potvrdit ·sp∞ÜnΘ pou₧itφ tΘto techniky, nap°φklad v redakΦnφm systΘmu ve stromovΘ struktu°e komentß°∙ k Φlßnk∙m. PotΘ, co jsem slo₧itΘ rekurzivnφ vypisovßnφ nahradil tφmto efektivnφm zp∙sobem, se prßce se Φlßnky podstatn∞ zrychlila a skripty majφ podstatn∞ menÜφ dΘlku. Tato technika lze navφc pou₧φt i na velmi velkß Φφsla, Hierarchy mß v mΘm p°φpad∞ dΘlku 38 mφst a indexy v jednotliv²ch slo₧kßch jsou po t°ech Φφslicφch (tedy max. 999 podlo₧ek).
Za n∞kter²ch podmφnek je mo₧nΘ spojit dva dotazy v jeden. P°i takov²chto operacφch je p°edevÜφm nutnΘ, aby se jednotlivΘ sloupce shodovali typov∞ i co do poΦtu. Pro tyto ·Φely jsou v SQL MNOÄINOV╔ mno₧inovΘ operßtory. NejjednoduÜÜφm z nich je UNION, kter² zastupuje prostΘ sjednocenφ mno₧in, vΦetn∞ dodatku, ₧e duplicitnφ zßznamy se ve sjednocenφ berou jako jeden prvek. Pokud bychom cht∞li toto odstranit, pou₧ijeme operßtor UNION ALL. Pokud bychom m∞li nap°φklad v naÜφ imaginßrnφ Ükole v odd∞len²ch tabulkßch uΦitele a ostatnφ pracujφcφ, seznam vÜech zam∞stnanc∙ zφskßme nßsledujφcφm dotazem :
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
<SPAN Class=CODE>SELECT JmΘno FROM U╚ITEL╔ UNION SELECT JmΘno FROM OSTATN═_ZAM</SPAN>
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
Obdobn²m zp∙sobem (pochopiteln∞ ovÜem v jinΘ situaci) lze pou₧φt operßtor INTERSECT pro pr∙nik mno₧in (tabulek) nebo MINUS (n∞kdy EXCEPT), p°i kterΘm jsou do v²sledku za°azeny v²sledky z prvnφho dotazu, kterΘ se nevyskytly v dotazu druhΘm.
To by bylo pro tentokrßt z SQL praxe vÜe. Rßd bych Φtenß°e upozornil, ₧e jednotlivΘ databßzovΘ programy (SystΘmy °φzenφ bßze dat, S╪BD) se Φasto svojφ implementacφ SQL liÜφ. P°edevÜφm jsou Φasto odliÜnΘ profesionßlnφ aplikace (Oracle apod...) od t∞ch "amatΘrsk²ch" (nap°. MySQL ve svΘ poslednφ kompletnφ verzi nemß v∙bec slo₧enΘ dotazy implementovßny), kterΘ na druhou stranu vedou co do poΦtu nasazen²ch aplikacφ na internetu a Φasto p°ekvapujφ nevφdanou rychlostφ. Pokud zkopφrujete zde uvedenΘ p°φklady do SQL konzole, je vφce ne₧ mo₧nΘ, ₧e prßv∞ vßÜ systΘm bude pro tu Φi onu vlastnost po₧adovat mφrn∞ odliÜnou syntaxi.
</DIV></FONT></b></i>
<FONT Size=2><DIV Align=Justify Class=Paragraph>
</DIV></FONT></b></i>
</DIV>
<SCRIPT>
TextEnd('')
</SCRIPT><OL Class=None Type=Disc></OL><SCRIPT>
nie('<br>');AdditionalTablesBegin();
CommentsBegin('SQL v praxi aneb bezpeΦnostnφ oddech',2);
Comment('87',' <IMG Src=images/sub.gif valign=top> super clanok','MiKRO','11');
Comment('96',' <IMG Src=images/sub.gif valign=top> Par poznamek','Dusan Bolek','11');