Datypic Logo
XQuery

XQuery

Priscilla Walmsley (pwalmsley@datypic.com)

ISBN: 1491915102

2nd edition, 2015, O'Reilly Media, Inc.

Chapter 16: Writing Better Queries

Please note that the book contains many inline examples and informal tables that are not provided here.

Example 16-1. Making use of whitespace
Less clear query
for $prod in doc("catalog.xml")//product return
<product><num>{data($prod/number)}</num>
<price>{for $price in doc("prices.xml")//prod
where $prod/number = $price/@num
return data($price/price)}</price>
</product>
More clear query
for    $prod in doc("catalog.xml")//product
return <product>
         <num>{data($prod/number)}</num>
         <price>{for    $price in doc("prices.xml")//prod
                 where  $prod/number = $price/@num
                 return data($price/price)}</price>
       </product>
Example 16-2. Documenting a function with xqDoc
declare namespace functx = "http://www.functx.com";
(:~
: The <b>functx:substring-after-last</b> function returns the part
: of <b>$string</b> that appears after the last occurrence of
: <b>$delim</b>. If <b>$string</b> does not contain
: <b>$delim</b>, the entire string is returned.
:
: @param $string the string to substring
: @param $delim the delimiter
: @return the substring
:)
declare function functx:substring-after-last
($string as xs:string?, $delim as xs:string) as xs:string?
 { "function body here"  };
Example 16-3. Using the catch variables
xquery version "3.0";
declare namespace err = "http://www.w3.org/2005/xqt-errors";
let $order-date := doc("order.xml")/order/@date
return 
try {
  if (not($order-date)) 
  then error(QName("http://datypic.com/err", "MissingOrdDate"),
             "Order date must be present")
  else if (not($order-date castable as xs:date)) 
  then error(QName("http://datypic.com/err", "InvalidOrdDate"),
             "Order date must be YYYY-MM-DD")
  else concat("The order-date is ",
         format-date(xs:date($order-date), "[M01]/[D01]/[Y0001]"))
}
catch * { 
  concat("[", $err:line-number, ": ", $err:column-number,
         "] Error ", $err:code, ": ", $err:description)
}
Example 16-4. Avoid reevaluating the same expression
Less efficient query
if (doc("prices.xml")/prices/priceList/prod[price < 30])
then <bargain-bin>{
       doc("prices.xml")/*/priceList/prod[price < 30]
     }</bargain-bin>
else ()
More efficient query
let $bargains := doc("prices.xml")/prices/priceList/prod[price < 30]
return if ($bargains)
       then <bargain-bin>{$bargains}</bargain-bin>
       else ()
Example 16-5. Avoid unnecessary sorting
Less efficient query
let $doc := doc("catalog.xml")
return $doc//number | $doc//name
More efficient query
unordered {
  let $doc := doc("catalog.xml")
  return $doc//(number|name)
}
Example 16-6. Avoid expensive path expressions
Less efficient query
doc("catalog.xml")//number
More efficient query
doc("catalog.xml")/catalog/product/number
Example 16-7. Use predicates instead of where clauses
Less efficient query
for $prod in doc("catalog.xml")//product
where $prod/@dept = "ACC"
order by $prod/name
return $prod/name
More efficient query
for $prod in doc("catalog.xml")//product[@dept = "ACC"]
order by $prod/name
return $prod/name
Datypic XQuery Services