c07. xquery - cs.ubbcluj.roivarga/documentation/semistructureddata/course2013/...• xquery = 3...

46
C07. XQuery Date Semistructurate, 2012-2013

Upload: others

Post on 25-Sep-2019

2 views

Category:

Documents


0 download

TRANSCRIPT

C07. XQuery

Date Semistructurate, 2012-2013

C07. DS

• XQuery

• In general, un document XML este stocat ca fisier individual sau intr-o baza de date relationala / obiect-relationala.

• => Nevoia de a interoga datele XML asa cum se interogheaza structurile relationale.

C07 - DS

interogheaza structurile relationale.

• Astfel ca a fost nevoie de un limbaj specializat in interogarea datelor XML (stocate in fisiere externe sau stocate in coloane de tip XML, pe server-e ca SQL-Server sau Oracle).

XQuery = XML Query Language

– XQuery foloseste constructii XPath ca si sintaxa de localizare si, in plus, introduce constructii gen SQL pentru facilitati in interogarea datelor.

Observatii:– Sunt situatii in care XPath + XSLT ofera o mai buna interogare a datelor,

dar sunt si situatii in care mai bine se descurca XQuery.

C07 - DS

dar sunt si situatii in care mai bine se descurca XQuery.– SELECT-SQL este bazat pe algebra relationala – este specializat sa

interogheze date in structuri relationale; nu este facut sa interogheze structuri ierarhice, gen XML.

– Specificatii generale XQuery: este un limbaj non-procedural; exista o sintaxa XML pentru limbajul de interogare s.a.

– In primii ani de dezvoltare a XQuery s-au elaborat n specificatii. Aceste documente incearca sa cuprinda cat mai bine o specificatie XQuery.

– XQuery este inca in curs de dezvoltare (sau parti din el), specificatiile sunt complexe, dar se spera catre o clarificare si o simplificare a acestora. ☺(currently in Last Call)

– (Vezi: http://www.w3.org/XML/Query/)

• XQuery = 3 limbaje in 1:– sintaxa „surface” – sintaxa „human readable” care se aseamana cu

SQL pentru bd relationale– sintaxa alternativa XML-based (inca in dezvoltare sau dezvoltata)– limbaj formal algebric – defineste formal semanticile XQuery

C07 - DS

• Cateva reguli de sintaxa– XQuery este case-sensitive (minuscule)– o valoare string se include intre „” sau ‚’– o variabila este precedata de $– comentariile XQuery sunt delimitate de (: comentariu :)

• Documente XML folosite in exemple:

• Profi:

<catedre>

<catedra idc="C1" sefi="P11 P12">

Sisteme Informatice

</catedra>

<catedra idc="C2" sefi="P21">

Limbaje de programare

C07 - DS

Limbaje de programare

</catedra>

<prof idp="P11" cat="C1">

<nume>prof 1</nume>

<birou>333</birou>

<disciplina tip="obl">bd</disciplina>

<disciplina tip="opt">ds</disciplina>

<observatii>obs P1</observatii>

</prof>

<prof idp="P12" cat="C1">

<nume>prof 2</nume>

<birou>406</birou>

<disciplina tip="fac">pdpj</disciplina>

<observatii>obs prof 2</observatii>

</prof>

...

</catedre>

• Documente XML folosite in exemple:

• Produse:

<produse>

<produs idp="P4" categ="C1">

<denumire>basme</denumire>

<pret>55</pret>

<descriere>descriere basme</descriere>

C07 - DS

<descriere>descriere basme</descriere>

</produs>

<produs idp="P6" categ="C2">

<denumire>poezii</denumire>

<pret>100</pret>

<descriere>descriere poezii</descriere>

</produs>

</produse>

• Operatori

• XQuery suporta toti operatorii pentru XPath, plus un set de alti operatori. Dintre acestia:– aritmetici: binari + - * DIV MOD; unari + - data()

– de comparatie: = != < <= > >=

– logici: binari or and; functie unara not()

– sequence-related: paranteze (); secvente , *; range to; node sequences union,

C07 - DS

– sequence-related: paranteze (); secvente , *; range to; node sequences union, intersect, except; before after

• Observatie:

• Comparatii generale: = != < <= > >=

• Comparatii pe valoare: eq ne lt le gt ge

• Diferenta:– $bookstore//book/@q > 10 => intoarce true daca cel putin un atribut book/@q are

valoarea >10

– $bookstore//book/@q gt 10 => intoarce true daca exista un singur atribut intors de expresia XPath si valoarea lui este >10; daca expresia intoarce mai multe atribute, rezultatul este eroare

• Expresii

• Expresii de localizare

• Este tipul de expresie folosit pentru a localiza datele in arborele XML. O

C07 - DS

• Este tipul de expresie folosit pentru a localiza datele in arborele XML. O asemenea expresie returneaza un set de noduri sau o valoare de un tip primitiv (de exemplu: numarul de noduri dintr-un set) si nu returneaza noduri duplicat.

• Exemplu: pentru al 5-lea client, comenzile unui anumit vanzator

document(„nume_doc”)//client[5]/comanda[vanzator=”geo”]

• Expresii constructori de elemente / atribute

• Se poate utiliza XQuery pentru a genera noi elemente, nu doar pentru a cauta (precum in XPath + XSLT).

• O expresie se include intre {} pentru a indica faptul ca aceasta va fi evaluata, si nu doar tratata ca text.

C07 - DS

<rez>

<prof2 catedra="{/catedre/prof[2]/@cat}">

{/catedre/prof[2]/nume/text()}

</prof2>

</rez>

=>

<rez>

<prof2 catedra="C1">prof 2</prof2>

</rez>

• Expresii secventa

• XQuery suporta operatori pentru constructia, filtrarea si combinarea expresiilor.

• Secventele nu sunt imbricate.

C07 - DS

• Exemple de construire:

(10, 1, 2, 3, 4)

(10, (1, 2), (), (3, 4)) (similar)

(10, 1 to 4) (similar)

(salary, bonus) (toti fiii salary + fiii bonus ai elementului de context)

($price, $price) (daca $price=5 atunci (5, 5))

• Expresii secventa

• Filtrare pe secventa – cu ajutorul predicatelor XPath:

$produse[pret gt 100] (unde $produse contine o secventa de

C07 - DS

$produse[pret gt 100] (unde $produse contine o secventa de

preturi)

(1 to 100)[. mod 5 eq 0] (elementele divizibile cu 5)

(21 to 29)[5] (al 5-lea element al secventei)

$comenzi[fn:position() = (5 to 9)] (elementele de pe

pozitiile de la 5 la 9)

/studenti/student[3]/nume/text() =>> numele celui de-al 3-lea

student din secventa de studenti

• Expresii secventa

• Combinarea secventelor de noduri:

• Exemplu: fie elementele A, B, C si$seq1 este (A, B)

C07 - DS

$seq1 este (A, B)

$seq2 este (A, B)

$seq3 este (B, C)

=>

$seq1 union $seq2 = (A, B)

$seq2 union $seq3 = (A, B, C)

$seq1 intersect $seq2 = (A, B)

$seq2 intersect $seq3 = (B)

$seq1 except $seq2 = empty sequence

$seq2 except $seq3 = (A)

• Expresii FLWR (FLWOR)

• FLWR = for, let, where, return – cuvintele cheie folosite in acest tip de expresii

• Sau• FLWOR = for, let, where, order by, return• (echivalentul lui SELECT – FROM – WHERE – ORDER BY din SQL)

C07 - DS

• (echivalentul lui SELECT – FROM – WHERE – ORDER BY din SQL)

• O asemenea expresie poate sa – atribuie o valoare unei variabile, sa returneze o secventa de noduri sau valori primitive; pot fi folosite pentru a calcula join intre doua sau mai multe documente, pentru restructurarea datelor s.a.

• Contine:– una sau mai multe clauze FOR si/sau LET– o clauza optionala WHERE– o clauza optionala ORDER BY– o clauza RETURN

• Procesarea expresiilor FLWOR:

– FOR / LET Clauses

– ( => lista ordonata de noduri / variabile)

C07 - DS

– WHERE Clause

– ( => lista filtrata de noduri)

– ORDER BY Clause

– ( => lista ordonata de noduri)

– RETURN Clause

• Clauzele FOR

• FOR variabila IN expr_XPath ...

• numele variabilelor incep cu „$”• expr_XPath este o expresie XPath sau o secventa explicita• o variabila FOR ia pe rand ca valoare fiecare obiect din setul de noduri

C07 - DS

• o variabila FOR ia pe rand ca valoare fiecare obiect din setul de noduri returnat de expresia XPath

• tot ce urmeaza dupa FOR este executat o data pentru fiecare valoare a variabilei

• Clauzele FOR

• Urmeaza exemple scrise pe sintaxa SQL-Server; exista un tabel “txml1” care contine o coloana “doc” de tip XML. Metoda “query” aplicata unui XML (dintr-o variabila SQL sau coloana dintr-un tabel) permite executarea de interogari XQuery pe acel XML.

C07 - DS

SELECT iddoc, doc.query('

for $n in //prof/nume

return $n/text()

')

FROM txml1

where iddoc=2

=>

prof 1prof 2prof 3

SELECT iddoc, doc.query('

for $n in //prof/nume

return $n

')

FROM txml1

where iddoc=2

=>

<nume>prof 1</nume>

<nume>prof 2</nume>

<nume>prof 3</nume>

• Clauzele FOR

SELECT iddoc, doc.query('

for $n in (1, 2, 3)

return $n

C07 - DS

')

FROM txml1

where iddoc=2

=>

1 2 3

SELECT iddoc, doc.query('

for $n in (1, 2), $m in (3, 4)

return <pereche>{$n} si {$m}</pereche>

')

FROM txml1

where iddoc=2

=>

<pereche>1 si 3</pereche>

<pereche>1 si 4</pereche>

<pereche>2 si 3</pereche>

<pereche>2 si 4</pereche>

C7. XQuery

• Clauzele LET

• LET variabila:=expresie_XPath

• valoarea variabilei devine setul de noduri intors de expresia XPath (=>

C07 - DS

• valoarea variabilei devine setul de noduri intors de expresia XPath (=> variabila primeste ca valoare o secventa de zero, unul sau mai multe noduri)

• doar clauza LET nu produce iteratie

• Observatie: Clauza LET nu este implementata pe SQL 2005, este implementata pe SQL 2008.

• Clauzele LET

• Exemplu:let $fac:=/facultati/facultate/@denumire

return

C07 - DS

<nume_facultati>{$fac}</nume_facultati>=>

<nume_facultati>Mate-info Fizica ...</nume_facultati>

• Exemplu:let $x:=(1 to 5)

return <test>{$x}</test>

=>

<test>1 2 3 4 5</test>

• Diferenta dintre legarea variabilelor cu FOR / LET:

let $s := (<A/>, <B/>, <C/>)

return <out>{$s}</out>

=>

<out>

<A/> <B/> <C/>

C07 - DS

<A/> <B/> <C/>

</out>

Si

for $s in (<A/>, <B/>, <C/>)

return <out>{$s}</out>

=>

<out><A/></out>

<out><B/></out>

<out><C/></out>

• Clauza WHERE

• WHERE conditie

Exemplu:for $n in (2,3,4,5), $m in (4,5,6,7,8,9,10)

where ($m mod $n=0)

C07 - DS

where ($m mod $n=0)

return

<pereche>

<divizibile>{$m} si {$n}</divizibile>

</pereche>

=><pereche>

<divizibile>4 si 2</divizibile>

</pereche>

<pereche>

<divizibile>6 si 2</divizibile>

</pereche>

...

• Clauza ORDER BY

• Cu „order by” se poate sorta rezultatul unui query, in functie de una sau mai multe expresii, ascendent (implicit) sau descendent.

C07 - DS

• ORDER BY criteriu_ordonare [ascendent|descendent]

• Clauza ORDER BY

Exemplu:

for $n in (2,3,4,5), $m in (4,5,6,7,8,9,10)

C07 - DS

where ($m mod $n = 0)

order by $m

return

<pereche>

<divizibile>

{$m} si {$n}

</divizibile>

</pereche>

=>

<pereche>

<divizibile>4 si 2</divizibile>

</pereche>

<pereche>

<divizibile>4 si 4</divizibile>

</pereche>

<pereche>

<divizibile>5 si 5</divizibile>

</pereche>

...

• Clauza ORDER BY

• Exemplu:

<rezultat>

{

for $p in ("ioana", "alin", "vali", "maria")

C07 - DS

for $p in ("ioana", "alin", "vali", "maria")

order by $p

return $p

}

</rezultat>

=>

<rezultat>alin ioana maria vali</rezultat>

• Clauza ORDER BY

• Exemplu:

<rezultat>

{

C07 - DS

{

for $p in ("ioana", "alin", "vali", "maria")

order by $p

return

<prenume>

{$p}

</prenume>

}

</rezultat>

=>

<rezultat>

<prenume>alin</prenume>

<prenume>ioana</prenume>

<prenume>maria</prenume>

<prenume>vali</prenume>

</rezultat>

• Expresii conditionale

• Sunt structuri if-then-else de forma:

if (conditie)

C07 - DS

if (conditie)

then output1

else output2

• Clauza else este obligatorie. Daca nu este nimic de scris pentru ea, se lasa else ().

• Expresii conditionale

• Exemplu:for $n in (2,3,4,5), $m in (4,5,6,7,8,9,10)

return

<pereche>

{

C07 - DS

{

if ($m mod $n=0)

then <divizibile>{$m} si {$n}</divizibile>

else ()

}

</pereche>

<pereche>

<divizibile>4 si 2</divizibile>

</pereche>

<pereche />

<pereche>

<divizibile>6 si 2</divizibile>

</pereche>

<pereche />

...

• Exemplu

<profi>

{

for $n in //prof

return

<prof>

<profi>

<prof>

<cat>catedra 1</cat>

<nume_prof>prof 1</nume_prof>

C07 - DS

<prof>

{

if ($n/@cat="C1")

then <cat>catedra 1</cat>

else <cat>catedra 2</cat>

}

<nume_prof>

{$n/nume/text()}

</nume_prof>

</prof>

}

</profi>

<nume_prof>prof 1</nume_prof>

</prof>

<prof>

<cat>catedra 1</cat>

<nume_prof>prof 2</nume_prof>

</prof>

<prof>

<cat>catedra 2</cat>

<nume_prof>prof 3</nume_prof>

</prof>

</profi>

• Expresii cuantificate

• Expresiile cuantificate introduc cuvintele cheie „some” si „every”; acestea reprezinta cuantificatorii existential & universal.

C07 - DS

• Cuvantul „some” testeaza existenta a cel putin unui element care satisface o anumita conditie.

• Cuvantul „every” verifica daca toate elementele verifica o conditie.

• Exemplu: daca un prof are cel putin o disciplina de tip obligatoriu, ii afiseaza toate disciplinele predate

SELECT iddoc, doc.query('

<rezultat>

{

for $p in //prof

C07 - DS

for $p in //prof

where some $disc in $p/disciplina/@tip

satisfies ($disc="obl")

return

<element>

{$p/disciplina}

</element>

}

</rezultat>

')

FROM txml1

where iddoc=8

<rezultat>

<element>

<disciplina tip="obl">bd</disciplina>

<disciplina tip="opt">ds</disciplina>

</element>

</rezultat>

• Exemplu:

SELECT iddoc, doc.query('

<rezultat>

{

for $p in //prof

where every $disc in $p/disciplina/@tip

C07 - DS

where every $disc in $p/disciplina/@tip

satisfies ($disc="obl")

return

<element>

{$p/disciplina}

</element>

}

</rezultat>

')

FROM txml1

where iddoc=1

<rezultat />

• Exemplu: evaluare pe 9 tuple

some $x in (1, 2, 3), $y in (2, 3, 4)

satisfies $x + $y = 4

=> true

C07 - DS

=> true

every $x in (1, 2, 3), $y in (2, 3, 4)

satisfies $x + $y = 4

=> false

• Functii

• XQuery include functiile XPath, plus unele particulare, precum:

– functii de agregare: count() sum() avg() min() max()

– distinct() – elimina nodurile duplicat

C07 - DS

– distinct() – elimina nodurile duplicat

– empty() – intoarce True daca este o secventa de noduri goala

• Observatie: Se ofera posibilitatea de a definii functii proprii (user-defined) – de exemplu – pe SQL-Server 2008

• Exemplu:

select doc.query('

<facultate>

{

for $s in distinct-values(//student/cods)

order by $s

C07 - DS

return

<sectie>

<cod>{$s}</cod>

<denumire>{//sectie[cods = $s]/denumires/text()}

</denumire>

<nrstuds>{count(//student[cods = $s])}</nrstuds>

</sectie>

}

</facultate>

')

from txml where iddoc=4

• Exemplu:

C07 - DS

<facultate>

<sectie>

<cod>1</cod>

<denumire>Matematicã</denumire>

<nrstuds>4</nrstuds>

</sectie>

<sectie><sectie>

<cod>2</cod>

<denumire>Informaticã</denumire>

<nrstuds>11</nrstuds>

</sectie>

<sectie>

<cod>3</cod>

<denumire>Matematicã-Informaticã</denumire>

<nrstuds>10</nrstuds>

</sectie>

</facultate>

• Exemplu:

SELECT iddoc, doc.query('

<rezultate>

{

for $s in /studenti/student

return

<rezultat>

C07 - DS

<rezultat>

<nume>{$s/nume/text()}</nume>

<nr_note>{count($s/nota)}</nr_note>

<nota_min>{min($s/nota/valoare)}</nota_min>

<nota_max>{max($s/nota/valoare)}</nota_max>

<media_calc>{avg($s/nota/valoare)}</media_calc>

<media_data>{$s/media/text()}</media_data>

</rezultat>

}

</rezultate>

')

FROM txml1 where iddoc=3

• Exemplu:

C07 - DS

<rezultate>

<rezultat>

<nume>stud 1</nume>

<nr_note>3</nr_note>

<nota_min>8</nota_min>

<nota_max>10</nota_max>

<media_calc>9</media_calc><media_calc>9</media_calc>

<media_data />

</rezultat>

<rezultat>

<nume>stud 4</nume>

<nr_note>1</nr_note>

<nota_min>10</nota_min>

<nota_max>10</nota_max>

<media_calc>10</media_calc>

<media_data />

</rezultat>

</rezultate>

• Exemplu – not in / not exists: sectiile in care nu exista nici un student

select doc.query('

<facultate>

{

for $s in /root/sectie

where empty(/root/student[sectie=$s/cods])

C07 - DS

where empty(/root/student[sectie=$s/cods])

return

<info_sectie>

<sectie>{$s/denumires/text()}</sectie>

</info_sectie>

}

</facultate>

')

from txml1 where iddoc=4

<facultate>

<info_sectie>

<sectie>mate-info</sectie>

</info_sectie>

</facultate>

• Exemplu – “left join”: sunt afisate toate sectiile, si pentru fiecare sectie ii sunt afisati studentii (posibil multime vida)

select doc.query('

<facultate>

{

for $s in /root/sectie

return

<info_sectie>

C07 - DS

<info_sectie>

<sectie>{$s/denumires/text()}</sectie>

<studenti>

{

for $st in /root/student

where $s/cods=$st/sectie

return $st/nume

}

</studenti>

</info_sectie>

}

</facultate>

')

from txml1 where iddoc=4

• Exemplu:

<facultate>

<info_sectie>

<sectie>info</sectie>

<studenti>

C07 - DS

<studenti>

<nume>stud 1</nume>

<nume>stud 2</nume>

</studenti>

</info_sectie>

<info_sectie>

<sectie>info</sectie>

<studenti>

<nume>stud 4</nume>

</studenti>

</info_sectie>

<info_sectie>

<sectie>info</sectie>

<studenti />

</info_sectie>

</facultate>

• Exemplu – inner join: sunt afisate toate sectiile in care sunt studenti, si acesti studenti

select doc.query('

<facultate>

{

for $s in /studenti/sectie

where not(empty(/studenti/student[sectie=$s/cods]))

return

<info_sectie>

C07 - DS

<info_sectie>

<sectie>{$s/denumires/text()}</sectie>

<studenti>

{

for $st in /studenti/student

where $s/cods=$st/sectie

return $st/nume

}

</studenti>

</info_sectie>

}

</facultate>

')

from txml1 where iddoc=4

• Exemplu:

<facultate>

<info_sectie>

<sectie>info</sectie>

<studenti>

<nume>stud 1</nume>

C07 - DS

<nume>stud 1</nume>

<nume>stud 2</nume>

</studenti>

</info_sectie>

<info_sectie>

<sectie>mate</sectie>

<studenti>

<nume>stud 4</nume>

</studenti>

</info_sectie>

</facultate>

• Exemplu – inner join: sunt afisate toate sectiile in care sunt studenti, si acesti studenti

select doc.query

('<r>

C07 - DS

('<r>

{

for $se in //sectii, $st in //studenti[CodS=$se/CodS]

return ($se, $st)

}

</r>')

from txml1

where iddoc = 10

<r>

<sectii>

<CodS>1</CodS>

<DenumireS>Matematicã</DenumireS>

</sectii>

<studenti>

<CodS>1</CodS>

<NrMatricol>8481</NrMatricol>

<Nume>Alexandru Ionel</Nume>

C07 - DS

<sectii>

<CodS>2</CodS>

<DenumireS>Informaticã</DenumireS>

</sectii>

<studenti>

<CodS>2</CodS>

<NrMatricol>9259</NrMatricol>

<Nume>Lazar Paul-Daniel</Nume>

......

</studenti>

<sectii>

<CodS>1</CodS>

<DenumireS>Matematicã</DenumireS>

</sectii>

<studenti>

<CodS>1</CodS>

<NrMatricol>9105</NrMatricol>

<Nume>Muntean Alexandra</Nume>

...

</studenti>

...

</studenti>

<sectii>

<CodS>2</CodS>

<DenumireS>Informaticã</DenumireS>

</sectii>

<studenti>

<CodS>2</CodS>

<NrMatricol>9275</NrMatricol>

<Nume>Micu Ofelia-Emanuela</Nume>

...

</studenti>

...

</r>

Doar sectiile care au studenti

• Next 08

– XQuery - probleme

C07 - DS