Ing. Tomáš Váňa, Ing. Jiří Zechmeister Databázové systémy II Přednáška III Ing. Tomáš Váňa, Ing. Jiří Zechmeister Fakulta elektrotechniky a informatiky tomas.vana@upce.cz, jiri.zechmeister@upce.cz
Obsah Pokročilejší příkazy jazyka SQL v Oracle Database: Pseudo-sloupec ROWNUM Klauzule WITH Hierarchické dotazy Příkaz INSERT ALL a INSERT FIRST Příkaz MERGE IDAS2 - Přednáška III
Pseudo-sloupec ROWNUM ROWNUM – magický sloupec, příčinou řady potíží, proto je nezbytné mu porozumět, pak může být velmi užitečný. Lze jej použít: Pro ladění dotazů, Pro číslování v rámci dotazu, pro provádění nejvyšších N- zpracování Sloupci ROWNUM budou přiřazena čísla 1, 2, 3, 4, .. N Hodnota ROWNUM není přiřazena řádku, řádek v tabulce nemá číslo. Hodnota ROWNUM je přiřazena řádku po jeho průchodu fází predikátu dotazu, ale před řazením nebo souhrnem. IDAS2 - Přednáška III
Pseudo-sloupec ROWNUM Hodnota ROWNUM je zvýšena pouze po jejím přiřazení, proto následující dotaz nikdy nevrátí žádný řádek SELECT * FROM zamestnanci WHERE ROWNUM<=5 ORDER BY mzda Správný zápis pro omezení počtu řádků: SELECT * FROM (SELECT * FROM zamestnanci ORDER BY mzda) WHERE ROWNUM<=5 Správný zápis pro uvedení rozsahu řádků: SELECT * FROM (SELECT dotaz.*, ROWNUM as radek FROM (SELECT * FROM trpaslici ORDER BY jmeno) dotaz) WHERE radek BETWEEN 3 and 5; Použití sloupce ROWNUM nahrazuje klauzuli LIMIT známou z MySQL pro určení rozsahu řádků na výstupu. IDAS2 - Přednáška III
Náhrada ROWNUM Alternativně je možné použít analytické funkce ROW_NUMBER() SELECT * FROM (SELECT jmeno, ROW_NUMBER() OVER (ORDER BY jmeno) as radek FROM trpaslici) WHERE radek BETWEEN 3 and 5 IDAS2 - Přednáška III
Příkazy s klauzulí WITH Klauzule WITH umožňuje přiřadit název určitému poddotazu uvedenému před vlastním dotazem SELECT. V něm se pak můžete odkazovat na tento poddotaz zadáním jména poddotazu – obdobně jako při práci s pohledy. Oracle optimalizuje zpracování poddotazu uvedeného jména - buď jako inline pohled nebo jako dočasnou tabulku. Jednotlivé poddotazy se mohou odkazovat na předchozí poddotazy, stejně jako se na ně odkazuje hlavní dotaz. Použití klauzule WITH je velice vhodné v případě, kdy je výsledek poddotazu odkazován vícekrát v rámci jediného dotazu, například, když průměrné hodnoty zjištěné poddotazem musí být několikrát porovnávány během vykonávání dotazu a běžné řešení by znamenalo bud zřízení samostatného pohledu nebo uvedení několika totožných vnořených dotazů v rámci hlavního dotazu. IDAS2 - Přednáška III
Příkazy s klauzulí WITH - příklad WITH <alias_name> AS (subquery_sql_statement) SELECT <column_name_list> FROM <alias>; Příklad: select store_name, sum(quantity) store_sales, (select sum(quantity) from sales)/(select count(*) from store) avg_sales from store s, sales sl where s.store_key = sl.store_key having sum(quantity) > (select sum(quantity) from sales)/(select count(*) from store) group by store_name IDAS2 - Přednáška III
Příkazy s klauzulemi WITH - příklad WITH sum_sales AS select sum(quantity) all_sales from stores, number_stores AS select count(*) nbr_stores from stores, sales_by_store AS select store_name, sum(quantity) store_sales from store natural join sales SELECT store_name FROM store, sum_sales, number_stores, sales_by_store WHERE store_sales > (all_sales / nbr_stores); IDAS2 - Přednáška III
Hierarchické dotazy Pokud tabulka obsahuje hierarchická data (hierarchie zaměstnanců, kategorie v e-shopech), lze je díky hierarchickým dotazům zobrazit v jejich přirozeném hierarchickém pořadí. IDAS2 - Přednáška III
Syntaxe průchodu stromů v Oracle SELECT sloupce FROM tabulka [WHERE podmínka3] START WITH podmínka1 CONNECT BY podmínka2 [ORDER BY …] Řádky vyhovující podmínce ve START WITH jsou považovány za kořenové řádky na první úrovni vnoření Pro každou řádku na úrovni i se rekurzivně hledají přímí potomci vyhovující podmínce v klauzuli CONNECT BY na úrovni i+1 Řádka předka se v podmínce označuje klíčovým slovem PRIOR Na závěr jsou odstraněny řádky nevyhovující podmínce ve WHERE Pokud není definováno třídění, odpovídá pořadí průchodu pre-order Každý řádek obsahuje pseudo-sloupec LEVEL, obsahující úroveň řádku v hierarchii IDAS2 - Přednáška III
Příklad hierarchického dotazu Příklad: SELECT PRIJMENI, JMENO, level -- pseudosloupec označující úroveň FROM A_HR.ZAMESTNANCI CONNECT BY MANAZER_ID = PRIOR ZAMESTNANEC_ID -- MANAZER_ID se rovná ZAMESTNANEC_ID u předchůdce START WITH MANAZER_ID is null; -- začni od zaměstnance, který nemá nadřízeného IDAS2 - Přednáška III
Příklad hierarchických dotazů SELECT lpad(' ',level*3)||PRIJMENI||' '||JMENO name, SYS_CONNECT_BY_PATH(PRIJMENI, '/') path, CONNECT_BY_ROOT PRIJMENI topmgr, CONNECT_BY_ISLEAF isleaf, level FROM A_HR.ZAMESTNANCI CONNECT BY MANAZER_ID = PRIOR ZAMESTNANEC_ID START WITH MANAZER_ID is null ORDER SIBLINGS BY PRIJMENI; NAME PATH TOPMGR ISLEAF LEVEL King Steven /King King 1 Cambrault Gerald /King/Cambrault 2 Bates Elizabeth /King/Cambrault/Bates 3 Bloom Harrison /King/Cambrault/Bloom Fox Tayler /King/Cambrault/Fox Kumar Sundita /King/Cambrault/Kumar Ozer Lisa /King/Cambrault/Ozer Smith William /King/Cambrault/Smith De Haan Lex /King/De Haan Hunold Alexander /King/De Haan/Hunold Austin David /King/De Haan/Hunold/Austin 4 IDAS2 - Přednáška III
Doplnění hierarchických dotazů Pro jednotlivé záznamy můžete také získat cestu od nejvyššího záznamu (jak to znáte třeba ze souborového systému) nebo řadu dalších informací: Funkce SYS_CONNECT_BY_PATH vrací cestu v hierarchii k aktuálnímu záznamu. Klauzule CONNECT_BY_ROOT vrací hodnotu z příslušného záznamu nejvyšší úrovně (tj. například nejvyššího manažera). Pokud byste chtěli výstup z dotazu použít pro zobrazení ve formě rozbalovací hierarchie tak, jak to třeba dělá u souborů Windows Explorer, bude se vám hodit i pseudosloupec CONNECT_BY_ISLEAF, který určuje, zda je aktuální záznam na poslední úrovni hierarchie (CONNECT_BY_ISLEAF=1) nebo zda má podřízené záznamy (CONNECT_BY_ISLEAF=0). Použití klíčového slova PRIOR <nazev_sloupce> za klíčovým slovem SELECT způsobí vrácení hodnoty předchůdce v daném sloupci (mužem tak např. vypsat jméno přímého nadřízeného). IDAS2 - Přednáška III
Hierarchické dotazy dle ANSI SQL Hierarchické dotazy dle ANSI SQL používají rekurzívní WITH klauzuli, která se odkazuje sama na sebe. Zavedení této syntaxe do Oracle 11gR2 zajišťuje hierarchickým dotazům Oracle SQL kompatibilitu s ANSI. IDAS2 - Přednáška III
Hierarchické dotazy dle ANSI SQL with employees (empno, name, job, mgr, hierlevel) as ( select empno, ename, job, mgr, 1 from emp where mgr is null union all select e.empno, e.ename, e.job, e.mgr, m.hierlevel + 1 from emp e join employees m on (m.empno = e.mgr) -- podmínka spojení a rekurzívní volání ) select * from employees Viz např. http://technology.amis.nl/blog/6104/oracle-rdbms-11gr2-goodbye-connect-by-or-the-end-of-hierarchical-querying-as-we-know-it IDAS2 - Přednáška III
Hierarchické dotazy dle ANSI SQL with org_pracovniku (ZAMESTNANEC_ID , PRIJMENI, JMENO, MANAZER_ID, uroven) as ( select ZAMESTNANEC_ID , PRIJMENI, JMENO, MANAZER_ID , 1 from A_HR.ZAMESTNANCI where MANAZER_ID is null -- začni od zaměstnance, který nemá nadřízeného union all -- spoj výsledek předchozího dotazu s výsledkem následujícího dotazu select pracovnici.ZAMESTNANEC_ID , pracovnici.PRIJMENI, pracovnici.JMENO, pracovnici.MANAZER_ID, manazeri.uroven+ 1 from A_HR.ZAMESTNANCI pracovnici join org_pracovniku manazeri on (manazeri.ZAMESTNANEC_ID = pracovnici.MANAZER_ID) -- podmínka spojení a rekurzívní volání ) select * from org_pracovniku Viz např. http://technology.amis.nl/blog/6104/oracle-rdbms-11gr2-goodbye-connect-by-or-the-end-of-hierarchical-querying-as-we-know-it IDAS2 - Přednáška III
Příkaz INSERT ALL Klasický příkaz INSERT umožňuje vložit 1 a nebo n řádků do jedné, předem specifikované tabulky. Příkaz INSERT ALL umožňuje vložit n řádků do n různých tabulek. IDAS2 - Přednáška III
Příkaz INSERT ALL IDAS2 - Přednáška III
Příkaz INSERT FIRST Pokud místo klíčového slova ALL použijeme FIRST, pak databáze po splnění první podmínky v řadě WHEN klauzulí již další klauzule netestuje. Řádek tak bude vložen maximálně jednou. V případě ALL může být potencionálně vložen tolikrát, kolik je WHEN klauzulí. Klíčové slovo FIRST lze použít pouze u příkazu INSERT obsahujícího WHEN klauzule. IDAS2 - Přednáška III
Příkaz MERGE Příkaz MERGE umožňuje provádět operace INSERT a UPDATE v jedné tabulce v rámci jednoho příkazu. IDAS2 - Přednáška III
Příkaz MERGE IDAS2 - Přednáška III
Děkuji za pozornost Otázky? IDAS2 - Přednáška II