XQuery
Priscilla Walmsley (pwalmsley@datypic.com)
ISBN: 1491915103
2nd edition, , 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
clausesLess 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