Prezentace se nahrává, počkejte prosím

Prezentace se nahrává, počkejte prosím

Petr Čermák Michal Danihelka

Podobné prezentace


Prezentace na téma: "Petr Čermák Michal Danihelka"— Transkript prezentace:

1 Petr Čermák Michal Danihelka
Rekurzivní SQL Petr Čermák Michal Danihelka

2 Osnova Úvod do problematiky Rekurzivní SQL v Oraclu
Řešení rekurzivních úloh bez podpory rekurzivního SQL Rekurzivní SQL v DB/2 Použití DB/2 UDF

3 Úvod do problematiky

4 Co je to rekurzivní dotaz?
Dotaz je rekurzivní, pokud se záznamy odkazují sami na sebe pomocí primárního nebo cizího klíče. Vazba může být přímá, nebo i přes několik tabulek

5 Použití rekurzivních dotazů
Obecně kdekoliv mají data hierarchickou strukturu Uspořádání organizace Struktura výrobku Rodinná hierarchie

6 Divergentní hierarchie
Každý uzel má nejvýše jednoho otce Reprezentace tabulkou s poli Klíč, Otec a nějaká hodnota přiřazená objektu Kořen možno označit například Klíč = Otec klic = otec – dobre pred uvedenim rekurzivniho sql, nebot bylo mozno rozvinout hierarchii pomoci joinu. – Michal (??)... u rekurze riziko zacykleni Napriklad geograficke objekty... staty, kraje, okresy, mesta..

7 Konvergentní hierarchie
Uzel může mít víc předků, nesmí však být svým otcem / dítětem (acyklický graf) Jedna tabulka nestačí Potřebujeme dvě – Objekty(PKey, Num) a Vztahy(PKey, CKey, Parametr vztahu) 2 tabulky – kdyz chceme u objektu mit vic info.. jinak by to tam bylo vickrat S tou jsme delali na zacatku.. Problem: A->B, A->C, B->D, C->D, kolik deti ma A? treba hierarchie ve firmach...

8 Rekurzivní hierarchie
Graf může obsahovat i cykly Reprezentace stejná jako v předchozím případu Riziko zacyklení

9 Další dělení Vyvážené Nevyvážené Hladiny většinou různých typů
Bývají divergentní Nevyvážené Hladiny prvků stejného druhu Zminit hierarchii s ukazately? (jde predevsim o strukturu) vs. data – nutno provadet i vypocty...

10 Podpora rekurze v SQL ANSI SQL nepodporuje dotazování popsaným způsobem ani výpočet obecně rekurzivních funkcí podpora je zahrnuta v „chystaném“ ANSI SQL3 (SQL:1999) náznaky implementace v ORACLE a DB2

11 Vlastnosti rekurzivních dotazů
vše na jeden dotaz nepřehlednost výhodné pouze když využiji velkou část výsledkové sady

12 Jak se obejít bez rekurze?
Použití cursorů, cyklů, ... Ztráta možnosti optimalizace Kód není tak “elegantní”

13 Požadavky kladené na rekurzi
Při procházení grafem můžeme získat: dosažitelnost vyčíslitelnost cest spojování cest výpočet obecně rekurzivní funkce při průchodu vrcholem nebo hranou

14 Příklad: (vztahy mezi součástmi)
2 2 2 P2 P3 P4 3 2 1 3 P5 P6 P7 2 1 P8 P9

15 Dosažitelnost Z daného vrcholu, nebo množiny vrcholů, chceme zjistit všechny dosažitelné potomky “Z jakých částí se skládá výrobek P1?”

16 Vyčíslitelnost cest “Zobraz celou strukturu výrobku P1 se všemi jeho částmi” P1(1) 2 2 2 P2(2) P3(2) P4(2) 3 2 1 3 P5(6) P6(4) P6(2) P7(6) 2 1 2 1 P8(8) P9(4) P8(4) P9(4)

17 Spojování cest “Jaké jsou části výrobku P1 a kolik jich je třeba k jeho sestavení?” P1(1) 2 2 2 P2(2) P3(2) P4(2) 3 2 1 3 P5(6) P6(6) P7(6) 2 1 P8(12) P9(6)

18 Rekurzivní SQL v Oraclu

19 Co Oracle podporuje? dosažitelnost vyčíslitelnost cest
jednu rekurzivní funkci level

20 Příklad: (struktura výrobku)
CREATE TABLE Parts (part# CHAR(5) PRIMARY KEY, part_name CHAR(4) NOT NULL, assembly_time INTEGER NOT NULL CHECK (VALUE >= 0), category_id INTEGER NOT NULL, FOREIGN KEY category_id REFERENCES Category); CREATE TABLE Usage (parent_part# CHAR(5) NOT NULL, component_part# CHAR(5) NOT NULL, quantity INTEGER NOT NULL, PRIMARY KEY(parent_part#, component_part#), FOREIGN KEY parent_part# REFERENCES Parts, FOREIGN KEY component_part# REFERENCES Parts);

21 CONNECT BY, START WITH Klauzule START WITH CONNECT BY
definuje počáteční podmínku pro dotaz CONNECT BY specifikuje vazbu mezi rodičovskými řádky a potomky (pomocí operátoru PRIOR)

22 Příklad: (zobraz strukturu výrobku – vyčíslitelnost cest)
SELECT LEVEL, parent_part#, component_part# FROM Usage CONNECT BY PRIOR component_part# = parent_part# START WITH parent_part# = ‘P1’ Výsledek dotazu není tabulka, výsledek je nutně uspořádaný Omezení -- nemožnost počítat libovolnou obecně rekurzivní funkci omezení na používání spojení v rek. dotazech

23 Algoritmus zpracování dotazu
1) Zjisti řádky splňující podmínku v START WITH 2) Najdi všechny potomky vzhledem k řádkům z kroku 2 nebo předchozího kroku 3 splňující podmínku v CONNECT BY 3) Opakuj krok 3 dokud dostáváš nové řádky 4) Eliminuj všechny řádky, které nesplňují podmínku ve WHERE 5) Vrať zbylé řádky.

24 Pořadí vrácených řádků
Řádky jsou vraceny v preorderu tj. nejdříve rodičovský vrchol, pak teprve podstromy.

25 Příklad: (Dosažitelnost)
SELECT DISTINCT component_part# FROM (viz. select pro zobrazení struktury)

26 Příklad: (obcházení joinu v connect by – součástky s popisem)
SELECT part#, category_name FROM Parts,Category WHERE Parts.category_id = Category.category_id AND part# IN (SELECT component_part# FROM Usage START WITH parent_part# = ‘P1’ CONNECT BY PRIOR componet_part# = parent_part#);

27 Příklad: (obcházení joinu v connect by – dosažitelné dvojice)
SELECT DISTINCT PX.part#, PX.part_name#, PY.part#, PY.part_name# FROM Parts PX,Parts PY WHERE PY.part# IN (SELECT component_part# FROM Usage START WITH parent_part# = PX.part# CONNECT BY PRIOR componet_part# = parent_part#) ORDER BY PX.part#, PY.part#;

28 Rozšíření Oracle 9i – podpora join
SELECT employee_name, manager_name, dept_name FROM employee, dept WHERE employee.deptno = dept.deptno START WITH employee_name = 'KING' CONNECT BY PRIOR employee_id = manager_id;

29 Rozšíření Oracle 9i – třídění řádků s daným předkem
SELECT employee_name, manager_name, dept_name FROM employee, dept WHERE employee.deptno = dept.deptno START WITH employee_name = 'KING' CONNECT BY PRIOR employee_id = manager_id ORDER SIBLINGS BY hire_date;

30 Rozšíření Oracle 9i - cesty
SELECT employee_name, SYS_CONNECT_BY_PATH(employee_name, '/') "PATH" FROM employee START WITH employee_name = 'KING' CONNECT BY PRIOR employee_id = manager_id;

31 Rozšíření Oracle 10g – společný předek
SELECT DISTINCT CONNECT_BY_ROOT assembly_id, CONNECT_BY_ROOT assembly_name FROM bill_of_materials WHERE part_number = 1019 START WITH parent_assembly IS NULL CONNECT BY parent_assembly = PRIOR assembly_id; CONNECT_BY_ROOTASSEMBLY_ID CONNECT_BY_ROOTASSEMBLY 100 Automobile

32 Rozšíření Oracle 10g – jsem list? – část 1
SELECT ASSEMBLY_ID, RPAD(' ', 2*(LEVEL-1)) || assembly_name assembly_name, quantity, CONNECT_BY_ISLEAF FROM bill_of_materials WHERE LEVEL <= 2 START WITH assembly_id = 100 CONNECT BY parent_assembly = PRIOR assembly_id; ASSEMBLY_ID ASSEMBLY_NAME QUANTITY CONNECT_BY_ISLEAF 100 Automobile 110 Combustion Engine 1 120 Body 130 Interior

33 Rozšíření Oracle 10g – jsem list? – část 2
SELECT ASSEMBLY_ID, RPAD(' ', 2*(LEVEL-1)) || assembly_name assembly_name, quantity, CONNECT_BY_ISLEAF FROM bill_of_materials WHERE LEVEL = 2 START WITH assembly_id = 110 CONNECT BY parent_assembly = PRIOR assembly_id; ASSEMBLY_ID ASSEMBLY_NAME QUANTITY CONNECT_BY_ISLEAF 111 Piston 6 1 112 Air Filter 113 Spark Plug 114 Block 115 Starter System

34 Rozšíření Oracle 10g – cykly
ASSEMBLY_NAME QUANTITY CONNECT_BY_ISCYCLE Automobile Combustion Engine 1 Piston 6 Air Filter Spark Plug Block SELECT RPAD(' ', 2*(LEVEL-1)) || assembly_name assembly_name, quantity, CONNECT_BY_ISCYCLE FROM bill_of_materials START WITH assembly_id = 100 CONNECT BY NOCYCLE parent_assembly = PRIOR assembly_id;

35 Řešení rekurzivních úloh bez podpory rekurzivního SQL

36 Formáty pro tabulky jakožto výsledky dotazů – část 1
Na rozdíl od oracla nesmějí mít tyto tabulky žádné číslování, aby šli používat v poddotazech Formát dostupnosti (kam se všude dostanu z vrcholu) – stačí binární tabulka obsahující kořen a syna parent_part# component_part#

37 Formáty pro tabulky jakožto výsledky dotazů – část 2
Formát vyčíslování cest (struktura s počtem podčástí) – použijeme následující tabulku seq# level parent_part# componet_part# max_subtree_seq# total_quantify Formát spojování cest (seznam následníků s počtem) – použijeme následující tabulku parent_part# componet_part# total_quantify

38 Kterak použít ANSI SQL k vyhodnocení rekurzivních dotazů – část 1
Dostupnost SELECT DISTINCT parent_part#, component_part# FROM PartsPathEnum WHERE parent_part# = ‘P1’ Vyčíslování cest SELECT * ORDER BY squence#;

39 Kterak použít ANSI SQL k vyhodnocení rekurzivních dotazů – část 2
Spojování cest SELECT parent_part#, component_part#, SUM(total_quantity) FROM PartsPathEnum WHERE parent_part# = ‘P1’ GROUP BY parent_part#,component_part#;

40 Kde vzít tabulku vyčíslitelnosti cest?
PL/SQL nebo jakýkoliv jazyk podporující rekurzi a SQL Doporučeno udělat index na kombinaci sloupců (parent_part#,component_part#), jelikož je tato tabulka typicky hodně veliká Není aktuální, ale v praxi většinou nevadí

41 Ořezávání dotazu SELECT PE1.*
FROM PartsPathEnum PE1, PartsPathEnum PE2 WHERE PE1.parent_part# = ‘P1’ AND PE2.parent_part# = ‘P1’ AND PE2.component_part# = ‘P3’ AND (PE1.seq# NOT BETWEEN PE2.seq# AND PE2.max_subtree_seq#) ORDER BY PE1.seq#;

42 Rekurzivní SQL v DB/2

43 Úvodní příklad Úkol: Získat seznam potomků (i nepřímých) uzlu A.
HIERARCHY A PKEY CKEY NUM A B 1 C 5 D 20 E 33 44 F G B C D E F G

44 Řešení PKEY CKEY A B C D E F G A B C D E F WITH PARENT (PKEY, CKEY) AS
(SELECT PKEY, CKEY FROM HIERARCHY WHERE PKEY = ‘A‘ UNION ALL SELECT C.PKEY, C.CKEY FROM HIERARCHY C, PARENT P WHERE P.CKEY = C.PKEY ) SELECT PKEY, CKEY FROM PARENT; PKEY CKEY A B C D E F G G With definuje tzv. Common table expression. Tabulka, která trva pouze po dobu dotazu. Nepotrebuje vlastní tablespace.. (to samy jako select * from a as (select ...), b where a... Select, nebo Select All, select distinct není povolen.. Stejne jako pouze union all Typy sloupecku jsou urceny prvnim podselektem, který nesmi byt rekurzivni (jinak změna pomoci CAST) Rekurzivni dotaz nesmi obsahovat zadne group by, having.., nesmi obsahovat poddotaz odkazujici se na parent.

45 Řešení problému zacyklení
Týká se rekurzivních hierarchií Dvě základní metody řešení: Zastavit procházení po určitém počtu hladin Udržovat si seznam navštívených uzlů a ignorovat dříve navštívené

46 Příklad 2 Seznam potomků s hloubkou, v jaké se nalézají. CKEY LVL A B
F Seznam potomků s hloubkou, v jaké se nalézají. CKEY LVL A B 1 C D E 2 F G 3 G WITH PARENT (CKEY, LVL) AS (SELECT DISTINCT PKEY, 0 FROM HIERARCHY WHERE PKEY = ‘A‘ UNION ALL SELECT C.CKEY, P.LVL + 1 FROM HIERARCHY C, PARENT P WHERE P.CKEY = C.PKEY ) SELECT PKEY, CKEY FROM PARENT; Distinct u toho nerekurzivniho selectu nevadi. Po kliknuti se zobrazi tabulka.

47 Příklad 3 Seznam potomků hloubky max. 2 CKEY LVL A B 1 C D E 2 F A B C
B 1 C D E 2 F G WITH PARENT (CKEY, LVL) AS (SELECT DISTINCT PKEY, 0 FROM HIERARCHY WHERE PKEY = ‘A‘ UNION ALL SELECT C.CKEY, P.LVL + 1 FROM HIERARCHY C, PARENT P WHERE P.CKEY = C.PKEY ) SELECT PKEY, CKEY FROM PARENT, WHERE LVL < 3; Vsichni vidi, ze to je osklivy...

48 Příklad 3 podruhé Seznam potomků hloubky max. 2 CKEY LVL A B 1 C D E 2
F Seznam potomků hloubky max. 2 CKEY LVL A B 1 C D E 2 F G WITH PARENT (CKEY, LVL) AS (SELECT DISTINCT PKEY, 0 FROM HIERARCHY WHERE PKEY = ‘A‘ UNION ALL SELECT C.CKEY, P.LVL + 1 FROM HIERARCHY C, PARENT P WHERE P.CKEY = C.PKEY AND P.LVL + 1 < 3 ) SELECT PKEY, CKEY FROM PARENT; Tohle uz je lepsi, nejenze je to efektivnejsi (neprohledava to celou hierarchii), ale taky zabranuje zacykleni.

49 Příklad 4 Výpis cesty, která má délku 4 CKEY LVL G 4 F 3 D 2 A 1 A B C
WITH TEMP1 (CKEY, LVL) AS (SELECT DISTINCT PKEY, 1 FROM HIERARCHY WHERE PKEY = ‘A‘ UNION ALL SELECT C.CKEY, P.LVL + 1 FROM HIERARCHY C, TEMP1 P WHERE P.CKEY = C.PKEY AND P.LVL < 4 ), TEMP2 (CKEY, LVL) AS (SELECT CKEY, LVL FROM TEMP1, WHERE LVL = 4 UNION ALL SELECT C.PKEY, D.LVL – 1 FROM HIERARCHY C, TEMP2 D WHERE D.CKEY = C.CKEY ) SELECT * FROM TEMP2; CKEY LVL G 4 F 3 D 2 A 1 Takto lze definovat vic temp. pohledu najednou... takhle lze projit treba vic hierarchii v jednom dotazu... neni povoleno cyklicke volani.. tzn aby se temp1 odkazovala na temp2 a naopak. Pri ruznych dotazech – varovani, ze se muze zacyklit...

50 Příklad 5 Všichni potomci uzlu A do 4. hladiny HIERARCHY A B C D E F G
PKEY CKEY A B C D E F G B C D Pribyl radek D A CREATE TABLE HIERARCHY (PKEY CHAR(03) NOT NULL, CKEY CHAR(03) NOT NULL, CONSTRAINT TBX1 PRIMARY KEY (PKEY, CKEY), CONSTRAINT TBC1 CHECK (PKEY <> CKEY), CONSTRAINT TBC2 CHECK (LOCATE(‘>’, PKEY) = 0), CONSTRAINT TBC3 CHECK (LOCATE(‘>’, CKEY) = 0)); CREATE UNIQUE INDEX TBLE_X1 ON HIERARCHY (CKEY, PKEY); INSERT INTO HIERARCHY VALUES (‘..’, ‘..’), (.... E F G

51 Příklad 5 - řešení A B C D E F G WITH PARENT (CKEY, LVL) AS
B 1 C D E 2 F 3 G E F WITH PARENT (CKEY, LVL) AS (SELECT DISTINCT PKEY, 0 FROM HIERARCHY WHERE PKEY = ‘A‘ UNION ALL SELECT C.CKEY, P.LVL + 1 FROM HIERARCHY C, PARENT P WHERE P.CKEY = C.PKEY AND P.LVL + 1 < 4 ) SELECT PKEY, CKEY FROM PARENT; G Tohle uz tam jednou bylo... (to s tim PKEY – ziska to spravnej typ, chyba, kdyz to tam nebude) Nevyhody – musime mit odhad na lvl, dostali se nam tam duplikaty, navis s ruznymi hladinami...

52 Příklad 5 – lepší řešení A B C D E F G WITH PARENT (CKEY, LVL) AS
(SELECT DISTINCT PKEY, 0 FROM HIERARCHY WHERE PKEY = ‘A‘ UNION ALL SELECT C.CKEY, P.LVL + 1 FROM HIERARCHY C, PARENT P WHERE P.CKEY = C.PKEY AND P.LVL + 1 < 4 ), NO_DUPS (CKEY, LVL, NUM) AS (SELECT CKEY, MIN(LVL), COUNT(*) FROM PARENT GROUP BY CKEY ) SELECT CKEY, LVL, NUM FROM NO_DUPS; G CKEY LVL NUM A 2 B 1 C D E F G 3 Treba takhle bychom chteli spocitat hladinu.. Pouzity dve temporarni tabulka, aby se no_dups dalo jeste pripojit k jinym.

53 Příklad 6 Udržování seznamu navštívených uzlů A B C D E F G
WITH PARENT (CKEY, LVL, PATH) AS (SELECT DISTINCT PKEY, 0, VARCHAR(PKEY, 20) FROM HIERARCHY WHERE PKEY = ‘A‘ UNION ALL SELECT C.CKEY, P.LVL + 1, P.PATH || ‘>‘ || C.CKEY FROM HIERARCHY C, PARENT P WHERE P.CKEY = C.PKEY AND LOCATE(C.CKEY || ‘>‘, P.PATH) = 0 ) SELECT CKEY, LVL, PATH FROM PARENT; CKEY LVL PATH A B 1 A>B C A>C D A>D E 2 A>C>E A>D>E F A>D>F G 3 A>D>F>G Typy sloupecku jsou urceny prvnim selektem. Naalokovat radeji velke, varchatr stejne zabira jen co potrebuje Zde se tvori cesta z korene do uzlu, ktery je prave prochazen. Viz. sloupec path Zabraneni vybrani jiz navstiveneho uzlu. (Tohle neuvazuje smycky) LOCATE vrati pozici podretezce, 0, kdyz se tam nevyskytuje. Vyuziva to toho, ze klic je definovan tak, ze nesmi obsahovat znak >, viz Je to efektivnejsi, nez orezavani dle lvl, protoze to do nekonecnych cyklu vubec nevleze.

54 Definice tabulky pro př. 6
CREATE TABLE HIERARCHY (PKEY CHAR(3) NOT NULL, CKEY CHAR(3) NOT NULL, CONSTRAINT TBX1 PRIMARY KEY (PKEY, CKEY), CONSTRAINT TBC1 CHECK (PKEY <> CKEY), CONSTRAINT TBC2 CHECK (LOCATE(‘>’, PKEY) = 0), CONSTRAINT TBC3 CHECK (LOCATE(‘>’, CKEY) = 0)); CREATE UNIQUE INDEX TBLE_X1 ON HIERARCHY (CKEY, PKEY); TBC1 Zabrani smyckam TBC2, 3 Zabrani vyskytu > v klicich. Pokud mame klice ciselne, staci na ne pouzit funkci CHAR

55 Příklad 7 – Detekce cyklů
WITH PARENT (CKEY, LVL, PATH) AS (SELECT DISTINCT PKEY, VARCHAR(PKEY, 20) FROM HIERARCHY WHERE PKEY = ‘A‘ UNION ALL SELECT CASE WHEN LOCATE(C.CKEY || ‘>‘, P.PATH) > 0 THEN RAISE_ERROR(‘70001‘, ‘CHYBA: Graf obsahuje cyklus‘); ELSE C.CKEY END, P.PATH || ‘>‘ || C.CKEY FROM HIERARCHY C, PARENT P WHERE P.CKEY = C.PKEY ) SELECT CKEY, PATH FROM PARENT; A B C D Driv, nez vleze do cyklu, vyhodi chybu E F G

56 Př. 8 - Tvorba syntetických dat
Ve spojení s INSERT CREATE TABLE NUMBERS(COUNTER INTEGER, RANDOM INTEGER) INSERT INTO NUMBERS(COUNTER, RANDOM) WITH TEMP(N) AS (VALUES (1) UNION ALL SELECT N + 1 FROM TEMP WHERE N < 1000 ) SELECT N, INTEGER(RAND() * 1000) FROM TEMP;

57 Rekurze s počítáním Komponenty křídla letadla: Křídlo 5 1 1 8 Příčka
Křidélko Podvozek Graf vyjadrujici, kolik ktera cast potrebuje komponent jineho typu 3 100 5 2 Pant 10 4 Nýt

58 Příklad 9 Počet nýtů COMPONENTS PART SUBPART QTY Křídlo Příčka 5
Křidélko 1 Podvozek Nýt 100 10 Pant 2 3 8 4 WITH WINGPARTS(SUBPART, QTY) AS (SELECT SUBPART, QTY FROM COMPONENTS WHERE PART = ‘Křídlo‘ UNION ALL SELECT C.SUBPART, P.QTY * C.QTY FROM WINGPARTS P, COMPONENTS C WHERE P.SUBPART = C.PART ) SELECT SUBPART, SUM(QTY) AS QTY FROM WINGPARTS WHERE SUBPART = ‘Nýt‘; Zde je priklad, proc muze rekurze potrebovat duplicity. Kliknuti – vysledek...

59 Příklad 9 - Výsledek Křídlo Příčka Křidélko Podvozek Pant Nýt 5 10 100
SUBPART QTY Příčka 5 Křidélko 1 Podvozek Nýt 100 50 Pant 2 3 8 12 Křídlo Příčka Křidélko Podvozek Pant Nýt 5 10 100 2 8 4 3 1 No..a pak uz staci bud select sum, where, nebo pokud chceme vsechny dily, tak GROUP BY SUBPART, SUM(QTY)

60 Použití DB/2 UDF

61 Kde rek. SQL DB/2 nestačí Problém: Nelze psát korelované rekurzivní poddotazy rekurzivních dotazů Příklad korelovaného poddotazu: SELECT POSSIBLE.ENAME, POSSIBLE.DEPT, POSSIBLE.SALARY FROM EMPLOYEE POSSIBLE WHERE SALARY > (SELECT AVG (SALARY) FROM EMPLOYEE AVERAGE WHERE POSSIBLE.DEPT = AVERAGE.DEPT); Jmeno, oddeleni, plat lib. zamestnance, ktery ma plat vyssi, nez prumer v jeho oddeleni Vyhodnoceni poddotazu zavisi na zpracovavanem radku vnejsiho dotazu. Neboli... je to poddotaz, kterej je spusten pro kazdou radku vnejsiho dotazu... Je to vlastne poruseni podminky acyklicnosti zavislosti mezi common table expressions.(?)

62 Příklad 10 Sporty Uživatelé Skupina A Skupina B Hobby Prof. Franta
Fotbal Basket Karel Dokument 1 Dokument 2 Dokument 3

63 Příklad 10 - dotaz Potřebujeme zjistit, na jaké dokumenty ze stromu sportů má uživatel Karel přístup a ke kterým předmětům náleží. Musíme rozvinout hierarchii sportů pro získání dokumentů a pro každý dokument z hierarchie práv zjistit, zda na něj má Karel právo. Řešení - UDF user defined functions.. .driv v Java / C, ted uz i SQL

64 Příklad 10 – datový model Group Subject item_id parent_id item_name
grp subgrp grpname Subject_Document Group_Document Document Dekompozice m:n item_id parent_id document_id grp subgrp document_id document_id name Tabulky: Subject, Group, Document, Subject_Document, Group_Document

65 Příklad 10 - Strategie Rozvineme hierarchii sportů -> získáme dokumenty (vnější rekurzivní dotaz)* Pro každý dokument z hierarchie sportů rozvineme skupiny uživatelů a zjistíme, zda se v nich nachází Karel (UDF s parametry ID dokumentu a uživatel) SELECT za * na každý vrácený dokument zavolá zmíněnou UDF

66 Příklad 10 - UDF CREATE FUNCTION ISELIGIBLE (Doc Integer, Uname character (64)) RETURNS INTEGER LANGUAGE SQL READS SQL DATA NO EXTERNAL ACTION NOT DETERMINISTIC RETURN WITH Main (subgrp, grpname) AS (SELECT subgrp, grpname FROM Group WHERE (subgrp) IN (SELECT subgrp FROM Group_Document WHERE document_id=Doc ) UNION ALL SELECT C.subgrp, C.grpname FROM Group C, Main M WHERE M.subgrp = C.grp ) SELECT COUNT(*) FROM main WHERE Ucase(grpname)=Ucase(Uname) Pokud tam neni, je tam 0 Prohlizi se smerem od group obsahujicich dokument DOLU. (smerem k uzivatelum)

67 Příklad 10 – Výsledný dotaz
WITH Rpl (parent_id, item_id, item_name) AS (SELECT ROOT.parent_id, ROOT.item_id, ROOT.item_name FROM Subject ROOT WHERE ROOT.parent_id = 1 UNION ALL SELECT CHILD.parent_id, CHILD.item_id, CHILD.item_name FROM RPL PARENT, Subject CHILD WHERE PARENT.item_id = CHILD.parent_id ) SELECT DISTINCT Rpl.parent_id, Rpl.item_id, Rpl.item_name, document.document_id, document.name, ISELIGIBLE(document.document_id, char('Karel')) eligible FROM (Rpl JOIN Subject_Document sd ON Rpl.item_id = sd.item_id ) JOIN document ON document.document_id = sd.document_id; Predpokladame, ze Sport ma ID 1 (pokud tam maj bejt i ty druhyPK, tak tam prijde za ON jeste AND Rpl.parent_id = sd.parent_id


Stáhnout ppt "Petr Čermák Michal Danihelka"

Podobné prezentace


Reklamy Google