Author
nan
View
34
Download
0
Embed Size (px)
DESCRIPTION
Databázové systémy II. Přednáška č. 8 RNDr. David Žák, Ph.D . Fakulta elektrotechniky a informatiky david.zak @ upce.cz. Obsah. Operátor CAST Operátory a funkce pro práci s hodnotami NULL Řádkové a tabulkové konstruktory Pokročilé dotazy ve standardu SQL 2 Synonyma. - PowerPoint PPT Presentation
Databázové systémy II
Přednáška č. 8
RNDr. David Žák, Ph.D.Fakulta elektrotechniky a informatiky
Obsah
• Operátor CAST
• Operátory a funkce pro práci s hodnotami NULL
• Řádkové a tabulkové konstruktory
• Pokročilé dotazy ve standardu SQL 2
• Synonyma
Výrazy s operátorem CAST
CAST ( <hodnota_výrazu> AS <datový_typ>)
Tento výraz zajišťuje konverzi hodnoty do určeného datového typu.Kromě datového typu je možné použít ve výrazu CAST i doménu, což je specifická množina platných
datových hodnot.
Použití výrazů s operátorem CAST:• zejména při používání jazyka SQL z jiného programovacího jazyka, jehož datové typy
neodpovídají datovým typům podporovaným standardem SQL (například pro převod data a času na řetězec)
• Konverze dat z databázové tabulky, kde je sloupec definován pomocí špatného datového typu (například čísla v uložená jako řetězce znaků)
• Odstranění rozdílů mezi různými typy pro stejná data ve 2 různých tabulkách
Výrazy s operátorem CAST
Příklad
SELECT ID, JMENO, CAST ( VYSKA AS VARCHAR(4))FROM TRPASLICI;
Výrazy s operátorem CASECASE
WHEN <vyhledávací_podmínka>THEN <výsledný_výraz_pravda>
[WHEN <vyhledávací_podmínka2>THEN <výsledný_výraz_pravda2>]
[ELSE <výsledný_výraz_nepravda>]END
Tento výraz umožňuje provádět jednoduché rozhodování.
Příklad
SELECT jmeno, CASE WHEN vyska>110 THEN 'velký'
WHEN vyska>107 THEN 'střední' ELSE 'malý'
END as velikost FROM trpaslici
Výrazy s operátorem CASE
Příklad dotazu, který umožňuje prostřednictvím proměnné zvolit vhodnou variantu řazení výsledků dotazu:
SELECT d.title, a.lastname, a.isbn, costFROM authors a, details d
WHERE a.isbn = d.isbnORDER BY CASE :byorder
WHEN 'TITLE' then titleWHEN 'LASTNAME' then lastnameWHEN 'ISBN' then isbnWHEN 'COST' then costELSE NULL
END;
Práce s hodnotami NULLNVL(testovaný_výraz, výraz_if_NULL)
Pokud není hodnota testovaný_výraz NULL, je vrácena hodnota testovaný_výraz, jinak výraz_if_NULL
NVL2(testovaný_výraz, výraz_if_NOT_NULL, výraz_if_NULL) Pokud není hodnota testovaný_výraz NULL, je vrácena hodnota výraz_if_NOT_NULL, jinak
výraz_if_NULL
Příklady:select NVL(dodavatel_mesto, 'neznámé')
from dodavatele;
select NVL2(dodavatel_mesto, 'vyplněno', ' neznámé ')from dodavatele;
Výrazy s operátorem COALESCENCEPodmínky ve výrazech CASE se používají nejčastěji pro zpracování hodnot NULL. Obvykle je potřeba
nahradit hodnotu NULL hodnotou nějakého řetězce nebo výchozí hodnotou. Operátor COALESCENCE vrací první nenulovou hodnotu. Pokud jsou všechny hodnoty NULL, vrací
NULL.
Příklad a jeho přepis do výrazu s operátorem COALESCENCE
SELECT jmeno, CASE WHEN (prodej_plan IS NOT NULL) THEN plan_prodej
WHEN (prodej_skutecnost IS NOT NULL)THEN prodej_skutecnost ELSE 0
END as prodej_objem FROM prodejci;
SELECT jmeno, COALESCENCE(prodej_plan , prodej_skutecnost, 0 )FROM prodejci;
Funkce NULLIFNULLIF( <výraz1>, <výraz2> )
NULLIF funkce porovnává výrazy výraz1 a výraz2. Pokud výraz1 a výraz2 se rovnají, NULLIF funkce vrací NULL. V opačném případě vrací výraz1.
Příklady využití funkce NULLIF
NULLIF(12, 12) vrací NULLNULLIF(12, 13) vrací 12NULLIF('apples', 'apples') vrací NULLNULLIF('apples', 'oranges') vrací 'apples'NULLIF(NULL, 12) vrací chybové hlášení ORA-00932
Konstruktor řádkové hodnotyStandard SQL2 umožňuje řádky v SQL výrazech používat stejným způsobem, jako se používají
skalární hodnoty. Standard poskytuje syntaxi pro vytváření řádků dat, umožňuje používat poddotazy s využitím celých řádků a definuje význam řádků pro operátory porovnání atd.
Konstruktor řádkové hodnoty:
Příkladem je například: (7, 'Smudla', NULL, 1993)
což představuje řádek se 4 sloupci
Konstruktor tabulkové hodnotyPříklad ukazuje možnost použití pro porovnání konstruktoru řádkového hodnoty prezentovaného (vyska, narozen)(vyska, narozen)a konstruktoru tabulkové hodnoty ((117, 1984), (115,1983))((117, 1984), (115,1983))
SELECT jmeno FROM trpasliciWHERE (vyska, narozen) IN ((117, 1984), (115,1983))
Uvedená konstrukce může významně zkrátit zápis některých komplikovaných podmínek v dotazech.
SELECT trpaslici.jmeno, count (*) FROM trpasliciWHERE ('Stydlin','na louce') =
ANY (SELECT jmeno, sachta FROM sachty WHERE sachty.Id=tezby.Id_sachty
AND trpaslici.Id=tezby.Id_trpaslikaAND tezby.SKUTECNOST>0)
GROUP BY trpaslici.jmeno;
CREATE TABLE AS SELECTJednou z možností efektivní práce je vytvoření nové tabulky z tabulky existující.Použitím této syntaxe budou vytvořeny sloupce stejného typu, jako jsou sloupce ve výsledku
vloženého dotazu SELECT, který je využit pro generování řádků nové tabulky.
CREATE TABLE new_table AS (SELECT * FROM old_table);
Příklad:CREATE TABLE dodavatele
AS (SELECT * FROM spolecnosti WHERE id > 1000);
CREATE TABLE AS SELECTUpřesnění sloupců a řádků vkládaných do nové tabulky :
CREATE TABLE new_table AS (SELECT column_1, column2, ... column_n FROM old_table WHERE podmínka);
Příklad:CREATE TABLE trpaslici3
AS (SELECT JMENO,SELECT JMENO, CAST ( VYSKA AS VARCHAR(4)) vyska_chCAST ( VYSKA AS VARCHAR(4)) vyska_chFROM TRPASLICI WHERE IDFROM TRPASLICI WHERE ID<5<5););
Samozřejmě je možné, aby vložený dotaz SELECT pracoval s několika tabulkami, výsledná tabulka bude sloupci a řádky odpovídat výsledku vnořeného dotazu.
INSERT INTO …. SELECTStejně jako je možné vytvořit tabulku s více řádky jediným příkazem, je možné i vložit více řádku
do tabulky pomocí jediného výrazu.
Příklad
INSERT INTO trpaslici3 (jmeno, vyska_ch) SELECT jmeno, vyska
FROM trpaslici WHERE jmeno='Stydlin';
Uvedený příklad zároveň demonstruje i automatickou konverzi formátů (sloupce vyska a vyska_ch).
JOIN s klauzulí USINGDoplňme si možnosti zápisu spojení tabulek pomocí klauzule JOIN o syntaxi s využitím klauzule
USING či NATURAL JOIN.Při přirozeném spojení pomocí NATURAL JOIN se porovnávají všechny sloupce z obou
spojovaných tabulek, které mají stejné názvy.Při spojení pomocí USING se porovnávají ty sloupce z obou spojovaných tabulek, které jsou
uvedeny v závorce za klauzulí USING (sloupec1, sloupec2, …).
Uvedené příklady mohou zpřehlednit zápis dotazů.
SELECT * FROM sachty JOIN rudy2 ON sachty.id_rudy=rudy2.id_rudy
SELECT * FROM sachty JOIN rudy2 USING (id_rudy)
SELECT * FROM sachty NATURAL JOIN rudy2
CROSS JOINKřížové spojení odpovídající kartézskému součinu vygenerujeme zápisem spojení s vynecháním
podmínek spojení.
SELECT jmeno, sachta FROM trpaslici, sachty
Při zápisu s využitím klauzule JOIN je nutné použít ještě klíčové slovo CROSS
SELECT jmeno, sachta FROM trpaslici CROSS JOIN sachty
TRUNCATESmaže všechny řádky tabulky nebo clusteru, není možné provést rollback
TRUNCATE TABLE nazev_tabulky;
Smazání řádků příkazem TRUNCATE může být více efektivní než odstranění tabulky příkazem DROP a opětovné vytváření příkazem CREATE TABLE. Důvodem je potřeba vytvoření velkého množství objektů závislých na tabulce (indexy, omezení, triggery).
Smazání řádků příkazem TRUNCATE může být rychlejší než použití příkazu DELETE a to zvláště v případě, kdy nad tabulkou jsou vytvořeny triggery, indexy a další závislosti.
Vnořené dotazyVnořené dotazy (poddotazy) se mohou vyskytovat prakticky na libovolném místě hlavního
dotazu. Výsledkem vnořeného dotazu je obecně „virtuálního tabulka“ o několika řádcích a několika sloupcích (v určitých případech pak jednosloupcová či jednořádková) nebo jen jedna jediná hodnota.
a) Vnořený dotaz v klauzuli FROM nebo JOIN – s výsledkem poddotazu se pracuje stejně jako při spojení s tabulkou či pohledem, výsledek poddotazu je v tomto případě vhodné označit aliasem
b) Vnořený dotaz vracející jednu hodnotu v části WHERE – např. výsledek agregační funkce (SUM, COUNT, MIN, MAX, AVG) se porovnává s hodnotou v určitém sloupci tabulky (nebo je vnořeným dotazem vyhledána hodnota v určitém sloupci, kdy řádek tabulky je identifikován pomocí primárního klíče)
c) Použití vnořeného dotazu v části WHERE s využitím množinových operátorů IN, ANY, SOME, ALL
Vnořené dotazy
d) Využití výsledků vnořeného dotazu pomocí operací – UNION, INTERSECT, MINUS, …
e) Použití vnořeného dotazu v části definice výstupních sloupců dotazu, kde se prostřednictvím vnořeného dotazu doplňují hodnoty na základě ostatních hodnot v daném řádku
SELECT (select c1 from t1 b where a.c1 = b.c1), c2 FROM t1 a WHERE <condition>
Komplexní UPDATEMůžeme také provádět mnohem komplexnější příkazy UPDATE, například změnit hodnoty v
řádku na základě hodnot v jiných tabulkách.Poněvadž není možné uvést více než jednu tabulku v příkazu UPDATE, můžeme použít klauzuli
EXISTS.
Příklad:UPDATE suppliers
SET supplier_name = (SELECT customers.name FROM customersWHERE customers.customer_id = suppliers.supplier_id)
WHERE EXISTS (SELECT customers.name FROM customers WHERE customers.customer_id = suppliers.supplier_id);
Kdykoli je supplier_id nalezen mezi hodnotami customer_id v tabulce customers, jeho customers_name přepíše stávající hodnotu supplier_name. Předpokládáme, že sloupce customer_id je primárním klíčem tabulky customers.
SynonymaPoužijte příkaz CREATE SYNONYM pro vytvoření synonyma, které je alternativním jménem pro
tabulku, pohled, sekvenci, proceduru, funkci, balíček, uživatelem definovaný objekt nebo jiné synonyma.
Příklad vytvoření synonama offices pro tabulku „locations“ ve schématu „hr“.
CREATE SYNONYM offices FOR hr.locations;
Specifikací PUBLIC vytvoříte veřejné synonyma, které jsou použitelné pro všechny uživatele.Pro použití synonyma však musí mít uživatel definována přístupová práva k danému objektu, na
který se synonyma odkazuje.
PříkladPříklad
CREATE PUBLIC SYNONYM suppliers FOR app.suppliers;
Pseudo-sloupec ROWNUMROWNUM – 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.
Pseudo-sloupec ROWNUMHodnota ROWNUM je zvýšena pouze po jejím přiřazení,
proto následující dotaz nikdy nevrátí žádný řádekSELECT * 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.
Náhrada ROWNUMAlternativně 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
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.
Architektury a techniky DS – cv. 1
25
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_salesfrom store s, sales slwhere s.store_key = sl.store_keyhaving sum(quantity) > (select sum(quantity) from sales)/(select count(*) from store)group by store_name
Architektury a techniky DS – cv. 1
26
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 salesSELECT store_nameFROM store, sum_sales, number_stores, sales_by_storeWHERE store_sales > (all_sales / nbr_stores);
Architektury a techniky DS – cv. 1
27
Syntaxe průchodu stromů v Oracle 9i,10
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 WHEREPokud není definováno třídění, odpovídá pořadí průchodu pre-orderKaždý řádek obsahuje pseudo-sloupec LEVEL, obsahující úroveň řádku v hierarchii
Architektury a techniky DS – cv. 1
28
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
Architektury a techniky DS – cv. 1
29
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).
Architektury a techniky DS – cv. 1
30
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 0 1 Cambrault Gerald /King/Cambrault King 0 2 Bates Elizabeth /King/Cambrault/Bates King 1 3 Bloom Harrison /King/Cambrault/Bloom King 1 3 Fox Tayler /King/Cambrault/Fox King 1 3 Kumar Sundita /King/Cambrault/Kumar King 1 3 Ozer Lisa /King/Cambrault/Ozer King 1 3 Smith William /King/Cambrault/Smith King 1 3 De Haan Lex /King/De Haan King 0 2 Hunold Alexander /King/De Haan/Hunold King 0 3 Austin David /King/De Haan/Hunold/Austin King 1 4
Architektury a techniky DS – cv. 1
31
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.
Architektury a techniky DS – cv. 1
32
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
Architektury a techniky DS – cv. 1
33
Hierarchické dotazy dle ANSI SQLwith 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
Architektury a techniky DS – cv. 1
34