指定路径表达式步骤中的谓词
如主题 XQuery 中的路径表达式中所述,路径表达式中的轴步骤包含下列组件:
轴。
节点测试。有关详细信息,请参阅指定路径表达式步骤中的节点测试。
零个或多个谓词。此为可选项。
可选的谓词是路径表达式中轴步骤的第三部分。
谓词
谓词通过应用指定的测试来筛选节点序列。谓词表达式用方括号括起来并绑定到路径表达式中的最后一个节点。
例如,假定声明了 xml 数据类型的 SQL 参数值 (x),如下所示:
declare @x xml
set @x = '
<People>
<Person>
<Name>John</Name>
<Age>24</Age>
</Person>
<Person>
<Name>Goofy</Name>
<Age>54</Age>
</Person>
<Person>
<Name>Daffy</Name>
<Age>30</Age>
</Person>
</People>
'
在这种情况下,下表达式是有效的,它们在三个不同节点级别使用谓词值 [1]。
select @x.query('/People/Person/Name[1]')
select @x.query('/People/Person[1]/Name')
select @x.query('/People[1]/Person/Name')
请注意,在每种情况下,谓词都绑定到应用该谓词的路径表达式中的节点。例如,第一个路径表达式选择每个 /People/Person 节点中的第一个 <Name> 元素,然后使用提供的 XML 实例返回下列内容:
<Name>John</Name><Name>Goofy</Name><Name>Daffy</Name>
但是,第二个路径表达式选择第一个 /People/Person 节点下的所有 <Name> 元素。因此,它将返回下列内容:
<Name>John</Name>
括号还可以用来改变谓词的计算顺序。例如,在下列表达式中,用一组括号来分隔路径 (/People/Person/Name) 和谓词 [1]:
select @x.query('(/People/Person/Name)[1]')
在此示例中,谓词的应用顺序改变了。这是因为首先计算括起来的路径 (/People/Person/Name),然后将谓词 [1] 运算符应用于包含与括起来的路径匹配的所有节点的集合。如果没有括号,运算顺序就会不同,[1] 将应用为 child::Name 节点测试(与第一个路径表达式示例类似)。
量词和谓词
在谓词自身的括号内可多次使用和添加量词。例如,接上一个示例,下列是复杂谓词子表达式中多个量词的有效用法。
select @x.query('/People/Person[contains(Name[1], "J") and xs:integer(Age[1]) < 40]/Name/text()')
谓词表达式的结果将转换为布尔值并作为谓词真值来引用。结果中仅返回谓词真值为 True 的序列中的节点。所有其他节点均将放弃。
例如,下列路径表达式在其第二步中包含一个谓词:
/child::root/child::Location[attribute::LocationID=10]
此谓词指定的条件应用于所有 <Location> 元素节点子级。结果仅返回 LocationID 属性值为 10 的那些生产车间。
将在以下 SELECT 语句中执行上一个路径表达式:
SELECT Instructions.query('
declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
/child::AWMI:root/child::AWMI:Location[attribute::LocationID=10]
')
FROM Production.ProductModel
WHERE ProductModelID=7
计算谓词的真值
根据 XQuery 规范,在确定谓词的真值时应用下列规则:
如果谓词表达式的值是一个空序列,则谓词真值为 False。
例如:
SELECT Instructions.query(' declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions"; /child::AWMI:root/child::AWMI:Location[attribute::LotSize] ') FROM Production.ProductModel WHERE ProductModelID=7
此查询中的路径表达式仅返回指定了 LotSize 属性的 <Location> 元素节点。如果谓词返回特定 <Location> 的空序列,将不在结果中返回该生产车间。
谓词值只能为 xs:integer、xs:Boolean 或 node*。对于 node*,如果存在任何节点则谓词值为 True,对于空序列,谓词值为 False。对于任何其他数值类型(如双精度类型和浮点类型),将生成静态类型化错误。当且仅当所得到的整数等于上下文位置值时,表达式的谓词真值才为 True。此外,只有整数文字值和 last() 函数会将筛选的步骤表达式的基数减小到 1。
例如,下列查询将检索 <Features> 元素的第三个子元素节点。
SELECT CatalogDescription.query(' declare namespace PD="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription"; declare namespace wm="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelWarrAndMain"; /child::PD:ProductDescription/child::PD:Features/child::*[3] ') FROM Production.ProductModel WHERE ProductModelID=19
请注意上述查询的以下方面:
表达式中的第三步指定了值为 3 的谓词表达式。因此,只有对于上下文位置为 3 的节点,此表达式的谓词真值才为 True。
在第三步中还指定了可表示节点测试中的任意节点的通配符 (*)。但是,谓词将筛选节点,并且仅返回第三个位置的节点。
查询将返回文档根级的 <ProductDescription> 元素子级的 <Features> 元素子级的第三个子元素节点。
如果谓词表达式的值是一个布尔类型的简单类型值,则谓词真值将等于谓词表达式的值。
例如,指定对具有 XML 实例(客户调查 XML 实例)的 xml 类型变量进行下列查询。查询检索那些具有子级的客户。在此查询中,应该为 <HasChildren>1</HasChildren>。
declare @x xml set @x=' <Survey> <Customer CustomerID="1" > <Age>27</Age> <Income>20000</Income> <HasChildren>1</HasChildren> </Customer> <Customer CustomerID="2" > <Age>27</Age> <Income>20000</Income> <HasChildren>0</HasChildren> </Customer> </Survey> ' declare @y xml set @y = @x.query(' for $c in /child::Survey/child::Customer[( child::HasChildren[1] cast as xs:boolean ? )] return <CustomerWithChildren> { $c/attribute::CustomerID } </CustomerWithChildren> ') select @y
请注意上述查询的以下方面:
for 循环中的表达式有两个步骤,而且第二个步骤指定了一个谓词。此谓词的值是一个布尔类型值。如果此值为 True,则谓词的真值也为 True。
查询将返回文档根级的 <Survey> 元素子级的 <Customer> 元素子级(其谓词值为 True)。结果如下:
<CustomerWithChildren CustomerID="1"/>
如果谓词表达式的值是一个至少包含一个节点的序列,则谓词真值为 True。
例如,下列查询检索产品型号的 ProductModelID,此产品型号的 XML 目录说明至少包含与 wm 前缀关联的命名空间中的一个要素(<Features> 元素的子元素)。
SELECT ProductModelID
FROM Production.ProductModel
WHERE CatalogDescription.exist('
declare namespace PD="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
declare namespace wm="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelWarrAndMain";
/child::PD:ProductDescription/child::PD:Features[wm:*]
') = 1
静态类型化和谓词筛选器
谓词可能还会影响表达式的静态推断类型。整数文字值和 last() 函数会将筛选的步骤表达式的基数最多减少到 1。