Partilhar via


Método nodes() (Tipo de Dados xml)

Aplica-se a:SQL ServerAzure SQL DatabaseAzure SQL Managed InstanceBase de dados SQL no Microsoft Fabric

O método nodes() é útil quando se quer fragmentar uma instância de tipo de dado xml em dados relacionais. Permite-te identificar nós que serão mapeados para uma nova linha.

Cada instância de tipo de dado xml tem um nó de contexto implicitamente fornecido. Para a instância XML armazenada numa coluna ou variável, este nó é o nó do documento. O nó documento é o nó implícito no topo de cada instância de tipo de dado xml .

O resultado do método nodes() é um conjunto de linhas que contém cópias lógicas das instâncias XML originais. Nestas cópias lógicas, o nó de contexto de cada instância de linha é definido para um dos nós identificados com a expressão de consulta. Desta forma, consultas posteriores podem navegar em relação a estes nós de contexto.

Podes recuperar múltiplos valores do conjunto de linhas. Por exemplo, pode aplicar o método value() ao conjunto de linhas devolvido pelos nodes() e recuperar múltiplos valores da instância XML original. O método value(), quando aplicado à instância XML, devolve apenas um valor.

Sintaxe

nodes (XQuery) as Table(Column)  

Arguments

XQuery
É um literal de cadeia, uma expressão XQuery. Se a expressão de consulta constrói nós, estes nós construídos são expostos no conjunto de linhas resultante. Se a expressão de consulta resultar numa sequência vazia, o conjunto de linhas também fica vazio. Se a expressão de consulta resultar estaticamente numa sequência que contém valores atómicos em vez de nós, é gerado um erro estático.

Tabela (Coluna)
É o nome da tabela e o nome da coluna para o conjunto de linhas resultante.

Observações

Como exemplo, suponha que tem a tabela seguinte:

T (ProductModelID INT, Instructions XML)  

O seguinte documento de instruções de fabrico está armazenado na tabela. Apenas um fragmento é mostrado. Note que há três locais de fabrico no documento.

<root>  
  <Location LocationID="10"...>  
     <step>...</step>  
     <step>...</step>  
      ...  
  </Location>  
  <Location LocationID="20" ...>  
       ...  
  </Location>  
  <Location LocationID="30" ...>  
       ...  
  </Location>  
</root>  

Uma nodes() invocação de método com a expressão /root/Location de consulta retornaria um conjunto de linhas com três linhas, cada uma contendo uma cópia lógica do documento XML original, e com o elemento de contexto definido para um dos <Location> nós:

Product  
ModelID      Instructions  
----------------------------------  
1      <root><Location LocationID="10" ... />  
             <Location LocationID="20" ... />  
             <Location LocationID="30" .../></root>  
1      <root><Location LocationID="10" ... />  
             <Location LocationID="20" ... />  
             <Location LocationID="30" .../></root>  
1      <root><Location LocationID="10" ... />  
             <Location LocationID="20" ... />  
             <Location LocationID="30" .../></root>  

Pode então consultar este conjunto de linhas usando métodos de tipo de dados xml . A consulta seguinte extrai a subárvore do item de contexto para cada linha gerada:

SELECT T2.Loc.query('.')  
FROM T  
CROSS APPLY Instructions.nodes('/root/Location') AS T2(Loc)   

Aqui está o resultado:

ProductModelID  Instructions  
----------------------------------  
1        <Location LocationID="10" ... />  
1        <Location LocationID="20" ... />  
1        <Location LocationID="30" .../>  

O conjunto de linhas devolvido manteve a informação do tipo. Pode aplicar métodos de tipo de dados xml , como query(), value(), exist() e nodes(), ao resultado de um método nodes( ). No entanto, não podes aplicar o método modify() para modificar a instância XML.

Além disso, o nó de contexto no rowset não pode ser materializado. Ou seja, não podes usá-lo numa instrução SELECT. No entanto, podes usá-lo em IS NULL e COUNT(*).

Os cenários para usar o método nodes() são os mesmos que para usar OPENXML (Transact-SQL), que fornece uma vista de rowsets do XML. No entanto, não precisa de usar cursores quando utiliza o método nodes() numa tabela que contém várias linhas de documentos XML.

O conjunto de linhas devolvido pelo método nodes() é um conjunto de linhas sem nome. Portanto, tem de ser explicitamente nomeado usando aliasing.

A função nodes() não pode ser aplicada diretamente aos resultados de uma função definida pelo utilizador. Para usar a função nodes() com o resultado de uma função escalar definida pelo utilizador, pode:

  • Atribuir o resultado da função definida pelo utilizador a uma variável
  • Use uma tabela derivada para atribuir um alias de coluna ao valor de retorno da função definida pelo utilizador e depois use CROSS APPLY para selecionar a partir do alias.

O exemplo seguinte mostra uma forma de selecionar CROSS APPLY a partir do resultado de uma função definida pelo utilizador.

USE AdventureWorks;  
GO  
  
CREATE FUNCTION XTest()  
RETURNS XML  
AS  
BEGIN  
RETURN '<document/>';  
END;  
GO  
  
SELECT A2.B.query('.')  
FROM  
(SELECT dbo.XTest()) AS A1(X)   
CROSS APPLY X.nodes('.') A2(B);  
GO  
  
DROP FUNCTION XTest;  
GO  

Examples

Usar o método nodes() contra uma variável do tipo xml

No exemplo seguinte, há um documento XML que tem um <Root> elemento de topo e três <row> elementos filhos. A consulta utiliza o nodes() método para definir nós de contexto separados, um para cada <row> elemento. O nodes() método devolve um conjunto de linhas com três linhas. Cada linha tem uma cópia lógica do XML original, com cada nó de contexto a identificar um elemento diferente <row> no documento original.

A consulta devolve então o nó de contexto de cada linha:

DECLARE @x XML   
SET @x='<Root>  
    <row id="1"><name>Larry</name><oflw>some text</oflw></row>  
    <row id="2"><name>moe</name></row>  
    <row id="3" />  
</Root>'  
SELECT T.c.query('.') AS result  
FROM   @x.nodes('/Root/row') T(c)  
GO  

No seguinte exemplo de resultado, o método de consulta devolve o elemento de contexto e o seu conteúdo:

<row id="1"><name>Larry</name><oflw>some text</oflw></row>  
<row id="2"><name>moe</name></row>  
<row id="3"/>  

Aplicar o acessório pai nos nós de contexto retorna o <Root> elemento para os três:

SELECT T.c.query('..') AS result  
FROM   @x.nodes('/Root/row') T(c)  
GO  

Aqui está o resultado:

<Root>  
    <row id="1"><name>Larry</name><oflw>some text</oflw></row>  
    <row id="2"><name>moe</name></row>  
    <row id="3" />  
</Root>  
<Root>  
    <row id="1"><name>Larry</name><oflw>some text</oflw></row>  
    <row id="2"><name>moe</name></row>  
    <row id="3" />  
</Root>  
<Root>  
    <row id="1"><name>Larry</name><oflw>some text</oflw></row>  
    <row id="2"><name>moe</name></row>  
    <row id="3" />  
</Root>  

Especificar o método nodes() contra uma coluna do tipo xml

As instruções de fabrico da bicicleta são usadas neste exemplo e estão armazenadas na coluna do tipo xml de Instruções da tabela ProductModel .

No exemplo seguinte, o nodes() método é especificado contra a Instructions coluna do tipo xml na ProductModel tabela.

O nodes() método define os<Location>elementos como nós de contexto especificando o /MI:root/MI:Location caminho. O conjunto de linhas resultante inclui cópias lógicas do documento original, uma para cada <Location> nó do documento, com o nó de contexto definido para o <Location> elemento. Como resultado, a nodes() função fornece um conjunto de <Location> nós de contexto.

O query() método contra este conjunto de linhas solicita self::node e devolve o <Location> elemento em cada linha.

Neste exemplo, a consulta define cada <Location> elemento como um nó de contexto no documento de instruções de fabrico de um modelo de produto específico. Pode usar estes nós de contexto para recuperar valores como estes:

  • Encontre IDs de Localização em cada um <Location>

  • Recuperar os passos de fabrico (<step> elementos filhos) em cada um <Location>

Esta consulta devolve o elemento de contexto, no qual a sintaxe '.' abreviada para self::node() é especificada, no query() método.

Tenha em atenção o seguinte:

  • O nodes() método é aplicado à coluna Instruções e devolve um conjunto de linhas, T (C). Este conjunto de linhas contém cópias lógicas do documento original de instruções de fabrico com /root/Location como elemento de contexto.

  • CROSS APPLY aplica-se nodes() a cada linha da ProductModel tabela e devolve apenas as linhas que produzem um conjunto de resultados.

    SELECT C.query('.') as result  
    FROM Production.ProductModel  
    CROSS APPLY Instructions.nodes('  
    declare namespace MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";  
    /MI:root/MI:Location') as T(C)  
    WHERE ProductModelID=7  
    

    Aqui está o resultado parcial:

    <MI:Location LocationID="10"  ...>  
       <MI:step ... />  
          ...  
    </MI:Location>  
    <MI:Location LocationID="20"  ... >  
        <MI:step ... />  
          ...  
    </MI:Location>  
    ...  
    

Aplicar nodes() ao conjunto de linhas devolvido por outro método nodes()

O código seguinte consulta os documentos XML para as instruções de fabrico na Instructions coluna da ProductModel tabela. A consulta devolve um conjunto de linhas que contém o ID do modelo do produto, locais de fabrico e passos de fabrico.

Tenha em atenção o seguinte:

  • O nodes() método é aplicado à Instructions coluna e devolve o conjunto de T1 (Locations) linhas. Este conjunto de linhas contém cópias lógicas do documento original de instruções de fabrico, com /root/Location o elemento como contexto do item.

  • nodes() é aplicado ao T1 (Locations) conjunto de linhas e devolve o T2 (steps) conjunto de linhas. Este conjunto de linhas contém cópias lógicas do documento original de instruções de fabrico, com /root/Location/step o elemento como contexto do item.

SELECT ProductModelID, Locations.value('./@LocationID','int') AS LocID,  
steps.query('.') AS Step         
FROM Production.ProductModel         
CROSS APPLY Instructions.nodes('         
declare namespace MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";         
/MI:root/MI:Location') AS T1(Locations)         
CROSS APPLY T1.Locations.nodes('         
declare namespace MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";         
./MI:step ') AS T2(steps)         
WHERE ProductModelID=7         
GO         

Aqui está o resultado:

ProductModelID LocID Step         
----------------------------         
7      10   <step ... />         
7      10   <step ... />         
...         
7      20   <step ... />         
7      20   <step ... />         
7      20   <step ... />         
...         

A consulta declara o MI prefixo duas vezes. Em vez disso, pode usar WITH XMLNAMESPACES para declarar o prefixo uma vez e usá-lo na consulta:

WITH XMLNAMESPACES (  
   'https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions' AS MI)  
  
SELECT ProductModelID, Locations.value('./@LocationID','int') AS LocID,  
steps.query('.') AS Step         
FROM Production.ProductModel         
CROSS APPLY Instructions.nodes('         
/MI:root/MI:Location') AS T1(Locations)         
CROSS APPLY T1.Locations.nodes('         
./MI:step ') as T2(steps)         
WHERE ProductModelID=7         
GO    

Ver também

Adicionar namespaces a consultas com WITH XMLNAMESPACES
Criar instâncias de dados XML
Métodos de Tipos de Dados XML