Partilhar via


Expressões de caminho - Especificando predicados

Aplica-se a:SQL Server

Conforme descrito no tópico, Expressões de caminho no XQuery, uma etapa de eixo em uma expressão de caminho inclui os seguintes componentes:

O predicado opcional é a terceira parte da etapa do eixo em uma expressão de caminho.

Predicados

Um predicado é usado para filtrar uma sequência de nó aplicando um teste especificado. A expressão de predicado é colocada entre colchetes e está vinculada ao último nó de uma expressão de caminho.

Por exemplo, suponha que um valor de parâmetro SQL (x) do tipo de dados xml seja declarado, conforme mostrado a seguir:

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>  
'  

Nesse caso, as seguintes são expressões válidas que usam um valor de predicado de [1] em cada um dos três níveis de nó diferentes:

select @x.query('/People/Person/Name[1]')  
select @x.query('/People/Person[1]/Name')  
select @x.query('/People[1]/Person/Name')  

Observe que, em cada caso, o predicado se liga ao nó na expressão de caminho onde é aplicado. Por exemplo, a primeira expressão de caminho seleciona o primeiro elemento <Name> dentro de cada nó /People/Person e, com a instância XML fornecida, retorna o seguinte:

<Name>John</Name><Name>Goofy</Name><Name>Daffy</Name>  

No entanto, a expressão do segundo caminho seleciona todos os elementos <Name> que estão sob o primeiro nó /People/Person. Portanto, ele retorna o seguinte:

<Name>John</Name>  

Parênteses também podem ser usados para alterar a ordem de avaliação do predicado. Por exemplo, na expressão a seguir, um conjunto de parênteses é usado para separar o caminho de (/People/Person/Name) do predicado [1]:

select @x.query('(/People/Person/Name)[1]')  

Neste exemplo, a ordem em que o predicado é aplicado muda. Isso ocorre porque o caminho fechado é primeiro avaliado (/People/Person/Name) e, em seguida, o operador de predicado [1] é aplicado ao conjunto que contém todos os nós que correspondem ao caminho fechado. Sem os parênteses, a ordem de operação seria diferente, pois o [1] é aplicado como um teste de nó child::Name, semelhante ao exemplo de expressão do primeiro caminho.

Quantificadores e Predicados

Os quantificadores podem ser usados e adicionados mais de uma vez dentro das chaves do próprio predicado. Por exemplo, usando o exemplo anterior, o seguinte é um uso válido de mais de um quantificador dentro de uma subexpressão de predicado complexo.

select @x.query('/People/Person[contains(Name[1], "J") and xs:integer(Age[1]) < 40]/Name/text()')  

O resultado de uma expressão de predicado é convertido em um valor booleano e é referido como o valor verdade do predicado. Somente os nós na sequência para a qual o valor de verdade do predicado é True são retornados no resultado. Todos os outros nós são descartados.

Por exemplo, a expressão de caminho a seguir inclui um predicado em sua segunda etapa:

/child::root/child::Location[attribute::LocationID=10]  

A condição especificada por este predicado é aplicada a todos os filhos do nó do elemento <Location>. O resultado é que apenas os locais do centro de trabalho cujo valor do atributo LocationID é 10 são retornados.

A expressão de caminho anterior é executada na seguinte instrução 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  

Valores de verdade de predicados de computação

As seguintes regras são aplicadas para determinar o valor de verdade do predicado, de acordo com as especificações XQuery:

  1. Se o valor da expressão do predicado for uma sequência vazia, o valor da verdade do predicado será False.

    Por exemplo:

    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  
    

    A expressão de caminho nesta consulta retorna somente os nós de elemento <Location> que têm um atributo LotSize especificado. Se o predicado retornar uma sequência vazia para um <Location>específico, esse local do centro de trabalho não será retornado no resultado.

  2. Os valores de predicados só podem ser xs:inteiro, xs:Booleano ou node*. Para node*, o predicado é avaliado como True se houver nós e False para uma sequência vazia. Qualquer outro tipo numérico, como tipo duplo e float, gera um erro de digitação estático. O valor verdade do predicado de uma expressão é True se e somente se o inteiro resultante for igual ao valor da posição do contexto. Além disso, apenas valores literais inteiros e a função last() reduzem a cardinalidade da expressão de etapa filtrada para 1.

    Por exemplo, a consulta a seguir recupera o nó do terceiro elemento filho do elemento <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  
    

    Observe o seguinte da consulta anterior:

    • A terceira etapa da expressão especifica uma expressão de predicado cujo valor é 3. Portanto, o valor de verdade predicado desta expressão é True apenas para os nós cuja posição de contexto é 3.

    • A terceira etapa também especifica um caractere curinga (*) que indica todos os nós no teste de nó. No entanto, o predicado filtra os nós e retorna apenas o nó na terceira posição.

    • A consulta retorna o terceiro nó do elemento filho do elemento <Features> filhos do elemento <ProductDescription> filhos da raiz do documento.

  3. Se o valor da expressão de predicado é um valor de tipo simples do tipo Booleano, o valor de verdade de predicado é igual ao valor da expressão de predicado.

    Por exemplo, a consulta a seguir é especificada em relação a uma variável de tipo xml que contém uma instância XML, a instância XML de pesquisa do cliente. A consulta recupera os clientes que têm filhos. Nesta consulta, isso seria <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  
    

    Observe o seguinte da consulta anterior:

    • A expressão no para loop tem duas etapas e a segunda etapa especifica um predicado. O valor deste predicado é um valor de tipo booleano. Se esse valor for True, o valor de verdade do predicado também será True.

    • A consulta retorna o elemento <Customer> filhos, cujo valor de predicado é True, do elemento <Survey> filhos da raiz do documento. Este é o resultado:

      <CustomerWithChildren CustomerID="1"/>   
      
  4. Se o valor da expressão de predicado for uma sequência que contenha pelo menos um nó, o valor de verdade do predicado será True.

Por exemplo, a consulta a seguir recupera ProductModelID para modelos de produto cuja descrição do catálogo XML inclui pelo menos um recurso, um elemento filho do elemento <Features>, do namespace associado ao prefixo wm.

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  

Observe o seguinte da consulta anterior:

  • A cláusula WHERE especifica o método exist() (tipo de dados XML).

  • A expressão de caminho dentro do método exist() especifica um predicado na segunda etapa. Se a expressão de predicado retornar uma sequência de pelo menos um recurso, o valor de verdade dessa expressão de predicado será True. Nesse caso, como o método exist() retorna um True, o ProductModelID é retornado.

Digitação estática e filtros de predicados

Os predicados também podem afetar o tipo inferido estaticamente de uma expressão. Os valores literais inteiros e a função last() reduzem a cardinalidade da expressão de etapa filtrada para, no máximo, uma.