XQuery (2ª parte) Helena Galhardas DEI IST (baseado nos slides de Ioana Manolescu, acessíveis em: http://www-rocq.inria.fr/~abitebou/Master-SSD/slxquery.pdf ) Agenda Formulação de interrogações Expressões FLOWR Sumário das expressões FLWOR Claúsula order by Permite uma ou mais especificações de ordem, em que cada uma especifica uma expressão usada para ordenar os tuplos Exemplo: for $a in doc(“books.xml”)//author order by $a/last descending, $a/first descending return $a Collations Especifica o modo como as cadeias de caracteres são comparadas e, consequentemente, ordenadas Exemplo: A seguinte interrogação ordena os títulos usando uma collation do Inglês dos EUA for $t in doc(“books.xml”)//title order by $t collation http://www.example.com/collations/eng-us return $t Nota: A maior parte das interrogações usam a mesma collation para todas as especificações de ordenação Junções As expressões FLOWR tornam mais fácil expressar junções sobre documentos a la SQL. Exemplo: for $p in document("taxpayers.xml")//person for $n in document("neighbors.xml")//neighbor where $n/ssn = $p/ssn return <person> <ssn> { $p/ssn } </ssn> { $n/ name } <income> { $p/ income } </income> </person> Nota: A condição de junção pode ser expressa como um predicado XPath no segundo for ou na claúsula where. (Left) outer-join Exemplo: Obter o título de cada livro, independentemente se ele tem uma revisão associada. Se o livro tem uma revisão associada, então as notas encontradas na revisão são retornadas for $t in doc(“books.xml”)//title return <review> { $t } { for $e in doc(“reviews.xml”)//entry where $e/title = $t return $e/remarks } </review> Junção e agrupamento Exemplo: Obter a lista dos departamentos com mais do que 10 empregados, ordenados pela média dos salários. for $d in document("depts.xml")//deptno let $e:=document("emps.xml")//employee[deptno =$d] where count($e) >= 10 order by avg($e/salary) descending return <big-dept> { $d , <headcount>{ count($e) } </headcount>, <avgsal>{ avg($e/salary) } </avgsal> } </big-dept> Nota: A construção {e1,e2, ··· ,en} é equivalente a: {concat(e1,e2, ··· ,en)}. Operações sobre listas XQuery suporta operadores para manipular listas: 1. Concatenação 2. Operações de conjunto: união, intersecção, diferença 3. Funções: remove(), index-of (), count(), avg(), min(), max(), etc. Exemplo: Para cada editor, retorne o seu nome e o seu preço médio de livros. for $p in distinct-values(document("bib.xml")//publisher) let $a := avg (document("bib.xml")//book[publisher=$p]/price ) return <publisher> <name>{ $p/text() }</name> <avgprice>{ $a }</avgprice> </publisher> União, intersecção e diferença Combinam sequências de nós: cada um destes operadores combina duas sequências, e retorna uma sequência resultado pela ordem do documento. Exemplo: let $l := distinctvalues(doc(“books.xml”)//(author|editor)/last) order by $l return <last> { $l } </last> O operador except aceita duas sequências de nós como operandos e retorna uma sequência contendo todos os nós que ocorrem no primeiro operando, mas não no segundo. Exemplo: a interrogação seguinte retorna um livro com todos os seus filhos excepto o preço for $b in doc(“books.xml”)//book where $b/title = “TCP/IP Illustrated” return <book> { $b/@* } { $b/* except $b/price } </book> Expressões if-then-else Exemplo: Qual o “holding” dos documentos publicados? for $h in document("library.xml")//holding return <holding> { $h/title , if ($h/@type = "Journal") then $h/editor else $h/author } </holding> Expressões quantificadas: some some exprime o quantificador existencial Exemplo: Qual o documento que menciona actividades de “sailing” e “windsurfing” for $b in document("bib.xml")//book where some $p in $b//paragraph satisfies (contains($p,"sailing") and contains($p ,"windsurfing")) return $b/title Expressões quantificadas: every every exprime o quantificador universal Exemplo: Qual o documento onde cada parágrafo fala acerca de “sailing” for $b in document("bib.xml")//book where every $p in $b//paragraph satisfies contains($p ,"sailing") return $b/title Funções pré-definidas O XQuery tem um conjunto de funções e operadores prédefinidos, entre as quais: min(), max(), count(), sum(), avg() round(), floor(), ceiling(), concat(), etc distinct-values(), doc(), collection(), not(), etc Exemplo: Quais os livros onde nenhum autor tem como último nome Stevens for $b in doc(“books.xml”)//book where not (some $a in $b/author satisfies $a/last = “Stevens”) return $b Funções definidas pelo utilizador Se não conseguirmos encontrar a função XPath de que necessitamos, então podemos escrever a nossa própria Funções definidas pelo utilizador podem ser escritas em XQuery usando a seguinte sintaxe: declare function prefix:function_name($parameter as datatype) as returnDatatype { (: ...insert FLOWR/XPath expression here...:) }; Notas: O nome da função tem que ser precedido por um namespace O tipo de dados para os parâmetros e o valor de retorno é opcional É útil para estruturar interrogações complexas e para reutilizar código Exemplo declare function local:minPrice($p as xs:decimal, $d as xs:decimal) AS xs:decimal { let $disc := ($p * $d) div 100 return ($p - $disc) } Implementações do XQuery Entre aquelas que são de distribuição livre, temos: Galax : completa, mas não muito eficiente Saxon : em memória MonetDB : em memória; está entre os mais eficientes eXist : uma interface muito amigável QizX : completa, com xquery update BerkeleyDB XML : pertence à Oracle, agora SQL/XML: a ponte entre os dois mundos (1) As versões recentes do SQL (2003) incluem: Um tipo atómico XML nativo, que pode ser interrogado no estilo XQuery Um conjunto de funções de publicação XML: que permitem extrair elementos de XML a partir de dados relacionais usando interrogações Regras de mapeamento: permitem exportar tabelas relacionais em XML Vantagens: Manipulação uniforme de dados relacionais e XML Motor de interrogações relacionais bem explorado Facilidade de transformação de um formato no outro Desvantagens: Complexidade SQL/XML: a ponte entre os dois mundos (2) Funções de publicação XML: select xmlelement (name Customer , xmlattributes(c. city as city), xmlforest (c.CustID, c. Name as CustName )) from customer c Interrogações mistas: select customer , XMLExtract (order,'/order/@date') from orders where XMLExists(order,'/order[//desc/text()="Shoes"]') =1 A sintaxe SQL/XML precisa depende, muitas vezes, do vendedor. Referências Ioana Manolescu, slides about XQuery, course about “Web Data Management and Distribution”, Master Recherche Informatique Paris Sud, http://www- rocq.inria.fr/~abitebou/Master-SSD/slxquery.pdf www.perfectxml.com/XQuery.html XQuery: A Guided Tour (book chapter from XQuery from the Experts)