Variable scope in for and let clauses

A variable that is bound in a for or let clause is in scope for the sub-expressions that appear after the variable binding.

This means that a for or let clause can reference variables that are bound in earlier clauses or in earlier bindings in the same clause.

The following examples demonstrate variable scope in for or let clauses. They assume that the PORDER column in the PURCHASEORDER table contains the following data:

<ipo:purchaseOrder
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:ipo="http://www.example.com/IPO"
   orderDate="2008-12-01">
  <shipTo exportCode="1" xsi:type="ipo:UKAddress">
    <name>Helen Zoe</name>
    <street>55 Eden Street</street>
    <city>San Jose</city>
    <state>CA</state>
    <postcode>CB1 1JR</postcode>
  </shipTo>
  <shipTo exportCode="1" xsi:type="ipo:UKAddress">
    <name>Joe Lee</name>
    <street>66 University Avenue</street>
    <city>Palo Alto</city>
    <state>CA</state>
    <postcode>CB1 1JR</postcode>
  </shipTo>
  <billTo xsi:type="ipo:USAddress">
    <name>Robert Smith</name>
    <street>8 Oak Avenue</street>
    <city>Old Town</city>
    <state>PA</state>
    <zip>95819</zip>
  </billTo>
  <items>
    <item partNum="833-AA">
      <productName>Lapis necklace</productName>
      <quantity>1</quantity>
      <USPrice>99.95</USPrice>
      <ipo:comment>Want this for the holidays!</ipo:comment>
      <shipDate>2008-12-05</shipDate>
    </item>
    <item partNum="945-ZG">
      <productName>Sapphire Bracelet</productName>
      <quantity>2</quantity>
      <USPrice>178.99</USPrice>
      <shipDate>2009-01-03</shipDate>
    </item>
  </items>
</ipo:purchaseOrder>
The following example shows that a variable can be bound in a clause and referenced in a later clause. In the SELECT statement, the FLWOR expression has the following clauses:
  • A let clause that binds the variable $item.
  • A for clause that references $item and binds the variable $pn.
  • A let clause that references both $item and $pn and binds the variables $n and $q.
SELECT XMLQUERY(
  'declare namespace ipo="http://www.example.com/IPO";
  let $item := $po/ipo:purchaseOrder/items/item
    for $pn in $item/@partNum
      let $n := $item[@partNum = $pn]/productName,
        $q := $item[@partNum = $pn]/fn:sum(quantity)
      return fn:concat("Quantity of ", $n, " = ", $q, ", ")'
  PASSING PORDER as "po")
  FROM PURCHASEORDER
The SELECT statement results in the following output:
Quantity of Lapis necklace = 1, Quantity of Sapphire Bracelet = 2,
The following example shows that two variables with the same name can be bound and referenced within the same scope. In the SELECT statement, the FLWOR expression has the following clauses:
  • A let clause that binds a variable named $iteration to 0.
  • A for clause that references a variable named $po that was bound by the PASSING clause, and binds a new $po variable.
  • A let clause that references the $iteration variable from the first let clause, and binds another variable named $iteration.
SELECT XMLQUERY(
  'declare namespace ipo="http://www.example.com/IPO";
  let $iteration := 0
  return
    for $po in $po/ipo:purchaseOrder/items/item/USPrice
    return
      let $iteration := $iteration + 1
      return
        <test iteration="{$iteration}">{$po}</test>'
  PASSING PORDER as "po") FROM PURCHASEORDER
The SELECT statement results in the following output:
<test iteration="1">
  <USPrice xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:ipo="http://www.example.com/IPO">
    99.95
  </USPrice>
</test>
<test iteration="1">
  <USPrice xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:ipo="http://www.example.com/IPO">
    178.99
  </USPrice>
</test>