路径表达式 - 指定谓词
适用于:SQL Server
如 主题 XQuery 中的路径表达式中所述,路径表达式中的轴步骤包括以下组件:
轴。
节点测试。 有关详细信息,请参阅 在路径表达式步骤中指定节点测试。
零个或多个谓词。 此为可选项。
可选的谓词是路径表达式中轴步骤的第三部分。
谓词
谓词通过应用指定的测试来筛选节点序列。 谓词表达式用方括号括起来并绑定到路径表达式中的最后一个节点。
例如,假设声明了 xml 数据类型 (x) 的 SQL 参数值,如下所示:
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')
请注意,在每种情况下,谓词都绑定到应用该谓词的路径表达式中的节点。 例如,第一个路径表达式选择每个 /人员/Person 节点中的第一<Name
>个元素,并使用提供的 XML 实例返回以下内容:
<Name>John</Name><Name>Goofy</Name><Name>Daffy</Name>
但是,第二个路径表达式选择第一个 /人员/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。 此外,只有整数文本值和 最后一个 () 函数将筛选的步骤表达式的基数降低到 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。
该查询返回文档根的 <
Customer
> Survey> 元素子元素的<元素子级,其谓词值为 True。 结果如下:<CustomerWithChildren CustomerID="1"/>
如果谓词表达式的值是一个至少包含一个节点的序列,则谓词真值为 True。
例如,以下查询从与 wm 前缀关联的命名空间中检索其 XML 目录说明至少包含一项功能(元素的<Features
>子元素)的产品模型的 ProductModelID。
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
请注意上述查询的以下方面:
WHERE 子句指定 xml 数据类型 () 的 exist () 方法 。
exist () 方法中的路径表达式指定第二步中的谓词。 如果谓词表达式返回至少一个功能的序列,则该谓词表达式的真值为 True。 在这种情况下,由于 exist () 方法返回 True,因此返回 ProductModelID。
静态类型化和谓词筛选器
谓词可能还会影响表达式的静态推断类型。 整数文本值和 最后一个 () 函数将筛选的步骤表达式的基数减少到最多 1。