Object Query Language (OQL) Rastislav Kadleček 2013 HOFFER, Prescott, McFadden. Modern Database Management, chapter 15. ODMG OQL User Manual.
Obsah Co je OQL? Primitivní datové typy jazyka OQL První dotazy Uvažovaná Struktura databáze Kolekce v OQL Základní struktura dotazu Filtrování kolekcí Konstrukce výsledků Agregační operátory Operátory „Define“, „Element“, „Exists“, „Like“, „Group By“, „Order By“ (Multi)množinové operátory
Co je OQL? Object Query Language Dotazovací jazyk podobný SQL (SQL-92) Na rozdíl od SQL je objektově orientovaný ODMG (Object Data Management Group) standard pro dotazování nad objektově orientovanými databázovými systémy 2 režimy – API pro programovací jazyky nebo interaktivní režim Díky jeho rozsáhlosti neexistuje žádna implementace, která by zahrnovala celou jeho specifikaci Existujíci implementace: GemStone Systems – GemFire (http://www.gemfire.com) Versant - Versant Object Database (http://www.versant.com)
Primitivní datové typy OQL OQL rozlišuje následovné primitivní datové typy: Boolean: hodnoty true, false Integer: celé číslo, např. 10 Float: desetinné číslo, např. 3,14 nebo 314.16e-2 Character: jeden znak ohraničený jednoduchými uvozovkami, např. ’z’ String: řetězec znaků ohraničených dvojitými uvozovkami, např. „toto je řetězec“ Reference na objekt: reference na instanci třídy nebo nil
První dotazy 2 * 2 4 Jan.name “Jan Novák” Aritmetické operace: Vyhodnotí aritmetický výraz a vrátí výsledek Dotaz na hodnotu vlastnosti objektu: Uvažujme třídu Student, která má vlastnost „name“ – jméno studenta Jan je instance třídy Student 2 * 2 4 Jan.name “Jan Novák”
První dotazy students[3].name “Jan Novák” students[3].age 23 Dotaz na konkrétní prvek pole (první prvek má index 0): Volání metody objektu: Zavolá danou metodu objektu a vrátí její výsledek Metoda „age“ vypočte věk studenta z aktuálního data a data narození studenta students[3].name “Jan Novák” students[3].age 23
Uvažovaná struktura databáze
Uvažovaná struktura databáze class Student { ( extent students) attribute string name; attribute Date dateOfBirth; attribute Address address; attribute Phone phone; relationship set CourseOffering takes inverse CourseOffering::taken_by; short age( ); float gpa( ); boolean register_for(string crse, short sec, string term); }; struct Phone { short area_code; long personal_number; }; struct Address { string street_address; string city; string zip; string country; };
Uvažovaná struktura databáze class Course { ( extent courses) attribute string crse_code; attribute string crse_title; attribute short credit_hrs; relationship set Course has_prereqs inverse Course::is_prereq_for; relationship set Course is_prereq_for inverse Course::has_prereqs; relationship list CourseOffering offers inverse CourseOffering::belongs_to; short enrollment( ); }; class CourseOffering { ( extent courseofferings) attribute string term; attribute enum section {1, 2, 3, 4, 5, 6, 7, 8}; relationship set Student taken_by inverse Student::takes; relationship Course belongs_to inverse Course::offers; short enrollment( ); };
Kolekce v OQL Jazyk OQL rozeznává následující druhy kolekcí: Množina (Set) Neuspořádaná kolekce objektů, ve které se objekty nesmí opakovat (každý objekt tam může být pouze jednou) Multimnožina (Bag) Na rozdíl od množiny se objekty mohou opakovat Seznam (List) Uspořádaná kolekce objektů, objekty se v ní mohou opakovat Pole (Array) Uspořádaná kolekce objektú, každý objekt má index své pozice a je možné se na nej odkazovat
Základní struktura dotazu Dotaz nám umožňuje vybrat ze specifikované kolekce prvky splňující požadovaná kritéria Dotaz vrací multimnožinu prvků Dotaz pozůstává ze 3 částí – select .. from .. where select definuje strukturu výsledku dotazu from specifikuje kolekci, nad kterou bude dotaz spuštěn where nepovinná část predikát, který umožnuje nastavit kritéria, která musí splňovat objekt, který bude zařazen do výsledku
Filtrování kolekcí select s from s in students Dotaz slouží k výběru prvků splňujúcich kritéria z kolekce Výsledkem je multimnožina objektů Dotaz najde v kolekci všech studentů studenty se jménem „Jan Novák“ V dotazech je možné využít i vlastnosti vnořených datových struktur select s from s in students where s.name = “Jan Novák” select s from s in students where s.address.city = “Praha”
Filtrování kolekcí select s from s in students Je také možné zřetězit několik podmínek za pomoci logických spojek and, or nebo negovat (operátor !) Po změně objektů v databázi může nastat situace, že některé objekty jsou najednou rovny hodnotě nil Tyto objekty je možné z kolekce explicitně vyloučit Není to však potřeba Pro větší pohodlí programátora OQL automaticky přeskakuje nil-ové objekty Když má objekt hodnotu nil, je predikát v sekci where vždy vyhodnocen jako false select s from s in students where s != nil and s.address.city = “Praha”
Klíčové slovo DISTINCT Protože výsledkem dotazu je multimnožina, výsledek může obsahovat duplicitní objekty Duplicitní objekty je možné odstranit použitím klíčového slova DISTINCT Výsledná kolekce zaručene neobsahuje duplicity – je to množina select distinct s from s in students where s.address.city = “Praha”
Sledování cesty v dotazu Objekty jsou vzájemně propojené vztahy mezi nimi – tvoří graf Při dotazování je možné sledovat libovolnou cestu v tomto grafu Vrátí předměty, které navštěvuje student se jménem „Jan Novák“ select distinct cr from s in students, co in s.takes, cr in co.belongs_to where s.name = „Jan Novák“
Konstrukce výsledků select distinct c.crse_code from c in courses Dosud probrané příklady vždy vracely kolekci celých objektů Je možné se dotazovat jen na určité atributy těchto objektů Vrátí množinu kódů předmětů, které mají dotaci větší než 2 hodiny Jedná se o množinu textových řetezců select distinct c.crse_code from c in courses where c.credit_hrs > 2
Konstrukce výsledků select distinct c.crse_title, c.crse_code Také je možné dotazovat se na více atributů zároveň Vrátí množinu struktur pozůstávajících z názvů a kódů předmětů, které mají dotaci větší než 2 hodiny select distinct c.crse_title, c.crse_code from c in courses where c.credit_hrs > 2 [ { “crse_title” => “Dotazovací jazyky I”, “crse_code” => “NDBI001” }, … ]
Konstrukce výsledků select struct ( name: s.name, address: struct ( Krom toho je možné v dotaze použít klíčové slovo struct Toto klíčové slovo umožnuje konkretizovat přesnou strukturu, jakou má mít každý prvek výsledné kolekce Je možné ho použít i vnořeně select struct ( name: s.name, address: struct ( street: s.address.street_address, city: s.address.city ) from s in students where s.address.country = “CZ”
Konstrukce výsledků Výsledkem dotazu je multimnožina datových struktur tvaru: [ { “name” = > “Jan Novák”, “address” => { “street” => “Anglická 3”, “city” => “Praha” } … ]
Agregační operátory select count (students) select avg(cr.credit_hrs) V jazyku OQL jsou k dispozici nasledujíci agregační operátory: count – počet (objektů v kolekci) min – nejmenší hodnota (v kolekci hodnot) max – největší hodnota (v kolekci hodnot) sum – součet (hodnot v kolekci) avg – průměrná hodnota (z hodnot v kolekci) Příklad: Zjištení celkového počtu studentů Příklad: Nalezení průměrné dotace hodin předmětů select count (students) select avg(cr.credit_hrs) from cr in courses
Operátory - Define define PredmetySe2Hodinama as select c Pomocí operátoru define je možné přiřadit jméno k výsledku dotazu – můžeme se pak na něj odvolat z jiného dotazu Může to výrazně zpřehlednit dlouhé dotazy K pojmenovaným dotazům je možné přistupovat pouze v rámci stejného sezení – až do použití příkazu commit nebo abort define PredmetySe2Hodinama as select c from c in courses where c.credit_hrs = 2 select c.crse_title from c in PredmetySe2Hodinama
Operátory - Element element ( select s from s in students V případě, že máme kolekci pozůstávající pouze z jednoho prvku, je možné tento prvek z dané kolekce extrahovat použitím operátoru element element ( select s from s in students where s.name = “Jan Novák” )
Operátory - Exists select s.name from s in students Pomocí operátoru exists je možné zjistit, jestli v kolekci existuje alespoň jeden objekt splňující požadovaná kritéria Přiklad: Dotaz vybere jména studentů, kteří navštěvují předmět s kódem „NDBI001“ select s.name from s in students where exists c in s.takes.belongs_to : c.crse_code = „NDBI001“
Operátory - Like select s from s in students where s.name like “Jan *” Operátor like umožňuje testování textových řetězců na částečnou shodu Znak ‘*’ je divoká karta, která zastává libovolný textový řetězec včetně prázdného řetezce Příklad: Dotaz vrátí všechny studenty, kteří mají křestní jméno „Jan“ Příklad: Dotaz vrátí všechny studenty, kteří mají příjmení „Novák “ select s from s in students where s.name like “Jan *” select s from s in students where s.name like “* Novák”
{ “age” => “21”, {“name” => “Kristýna Krásná”} }, Operátory – Group By Pomocí operátora group by je možné prvky výsledku „sgrupit“ dohromady podle určitého výrazu Výsledkem dotazu obsahujícího operátor group by je (multi)množina dvojic, kde každá dvojice pozůstává z hodnoty „sgrupujícího“ výrazu a množiny objektů, pro které se výraz vyhodnotil na tuto hodnotu select s from s in students group by s.age [ { “age” => “21”, {“name” => “Kristýna Krásná”} }, { “age” => “23”, {“name” => “Jan Novák”, “name” => “Petr Černý”} }, … ]
Operátory – Order By select s.name from s in students Operátor order by umožňuje seřadit výsledky dotazu dle specifikovaného výrazu Je možné specifikovat více výrazů pro řazení najednou Výsledkem dotazu obsahujícího operátor order by je vždy kolekce typu seznam Směr řazení je možné specifikovat pro každý výraz použitím klíčových slov asc (vzestupně) a desc (sestupně) select s.name from s in students order by s.name asc, s.age desc
(Multi)množinové operátory V jazyku OQL jsou k dispozici nasledujíci operátory definované pro množiny a multimnožiny: union (+) – sjednocení intersect (*) – průnik except (-) – rozdíl Příklad: Sjednocení množin 22 a 23 let starých studentů (select s from s in students where s.age = 22) + where s.age = 23)
Dekuji za pozornost