Partilhar via


Exemplos: Usar o modo PATH

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

Os exemplos seguintes ilustram a utilização do modo PATH na geração de XML a partir de uma consulta SELECT. Muitas destas consultas são especificadas contra os documentos XML das instruções de fabrico de bicicletas, que são armazenados na coluna Instruções da tabela ProductModel.

Especificar uma consulta em modo PATH

Esta consulta especifica o modo FOR XML PATH.

USE AdventureWorks2022;
GO
SELECT
       ProductModelID,
       Name
FROM Production.ProductModel
WHERE ProductModelID=122 OR ProductModelID=119
FOR XML PATH;
GO

O resultado seguinte é um XML centrado no elemento, onde cada valor de coluna do conjunto de linhas resultante é envolto num elemento. Como a SELECT cláusula não especifica quaisquer aliases para os nomes das colunas, os nomes dos elementos filhos gerados são os mesmos que os respetivos nomes das colunas na SELECT cláusula. Para cada linha do conjunto de linhas é adicionada uma <row> etiqueta.

<row>
  <ProductModelID>122</ProductModelID>
  <Name>All-Purpose Bike Stand</Name>
</row>
<row>
  <ProductModelID>119</ProductModelID>
  <Name>Bike Wash</Name>
</row>

O resultado seguinte é o mesmo da consulta no modo RAW com a opção ELEMENTS especificada. Devolve XML centrado no elemento com um elemento predefinido <row> para cada linha do conjunto de resultados.

USE AdventureWorks2022;
GO
SELECT ProductModelID,
       Name
FROM Production.ProductModel
WHERE ProductModelID=122 OR ProductModelID=119
FOR XML RAW, ELEMENTS;

Pode, opcionalmente, especificar o nome do elemento da linha para sobrescrever o padrão <row>. Por exemplo, a consulta seguinte devolve o <ProductModel> elemento para cada linha do conjunto de linhas.

USE AdventureWorks2022;
GO
SELECT ProductModelID,
       Name
FROM Production.ProductModel
WHERE ProductModelID=122 or ProductModelID=119
FOR XML PATH ('ProductModel');
GO

O XML resultante terá um nome especificado do elemento da linha.

<ProductModel>
  <ProductModelID>122</ProductModelID>
  <Name>All-Purpose Bike Stand</Name>
</ProductModel>
<ProductModel>
  <ProductModelID>119</ProductModelID>
  <Name>Bike Wash</Name>
</ProductModel>

Se especificar uma string de comprimento zero, o elemento de enrolamento não é produzido.

USE AdventureWorks2022;
GO
SELECT ProductModelID,
       Name
FROM Production.ProductModel
WHERE ProductModelID=122 OR ProductModelID=119
FOR XML PATH ('');
GO

Este é o resultado:

<ProductModelID>122</ProductModelID>
<Name>All-Purpose Bike Stand</Name>
<ProductModelID>119</ProductModelID>
<Name>Bike Wash</Name>

Especificar nomes de colunas semelhantes ao XPath

Na consulta seguinte, o nome da ProductModelID coluna especificado começa por '@' e não contém uma marca de barra ('/'). Assim, um atributo do <row> elemento que tem o valor correspondente da coluna é criado no XML resultante.

USE AdventureWorks2022;
GO
SELECT ProductModelID AS "@id",
       Name
FROM Production.ProductModel
WHERE ProductModelID=122 OR ProductModelID=119
FOR XML PATH ('ProductModelData');
GO

Este é o resultado:

<ProductModelData id="122">
  <Name>All-Purpose Bike Stand</Name>
</ProductModelData>
<ProductModelData id="119">
  <Name>Bike Wash</Name>
</ProductModelData>

Pode adicionar um único elemento de nível superior especificando a opção root em FOR XML.

SELECT ProductModelID AS "@id",
       Name
FROM Production.ProductModel
WHERE ProductModelID=122 or ProductModelID=119
FOR XML PATH ('ProductModelData'), root ('Root');
GO

Para gerar uma hierarquia, pode incluir sintaxe semelhante a PATH. Por exemplo, mude o nome Name da coluna para "SomeChild/ModelName" e obterá XML com hierarquia, como mostrado neste resultado:

<Root>
  <ProductModelData id="122">
    <SomeChild>
      <ModelName>All-Purpose Bike Stand</ModelName>
    </SomeChild>
  </ProductModelData>
  <ProductModelData id="119">
    <SomeChild>
      <ModelName>Bike Wash</ModelName>
    </SomeChild>
  </ProductModelData>
</Root>

Além do ID e nome do modelo do produto, a consulta seguinte recupera as localizações das instruções de fabrico para o modelo do produto. Como a coluna Instruções é do tipo xml, especifica-se o método do tipo de dados query() XML para recuperar a localização.

SELECT ProductModelID AS "@id",
       Name,
       Instructions.query('declare namespace MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
                /MI:root/MI:Location
              ') AS ManuInstr
FROM Production.ProductModel
WHERE ProductModelID = 7
FOR XML PATH ('ProductModelData'), root ('Root');
GO

Este é o resultado parcial. Como a consulta especifica ManuInstr como nome da coluna, o XML devolvido pelo query() método é encapsulado numa <ManuInstr> etiqueta, como mostrado no seguinte:

<Root>
  <ProductModelData id="7">
    <Name>HL Touring Frame</Name>
    <ManuInstr>
      <MI:Location xmlns:MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions"
        <MI:step>...</MI:step>...
      </MI:Location>
      ...
    </ManuInstr>
  </ProductModelData>
</Root>

Na consulta XML FOR anterior, pode querer incluir espaços de nomes (namespaces) para os elementos <Root> e <ProductModelData>. Pode fazer isto definindo primeiro o prefixo para a ligação de namespace usando WITH XMLNAMESPACES e usando prefixos na consulta XML FOR. Para obter mais informações, veja Adicionar Namespaces a Consultas com WITH XMLNAMESPACES.

USE AdventureWorks2022;
GO
WITH XMLNAMESPACES (
   'uri1' AS ns1,
   'uri2' AS ns2,
   'https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions' as MI)
SELECT ProductModelID AS "ns1:ProductModelID",
       Name           AS "ns1:Name",
       Instructions.query('
                /MI:root/MI:Location
              ')
FROM Production.ProductModel
WHERE ProductModelID=7
FOR XML PATH ('ns2:ProductInfo'), root('ns1:root');
GO

O MI prefixo também está definido no WITH XMLNAMESPACES. Como resultado, o query() método do tipo xml especificado não define o prefixo no prólogo da consulta. Este é o resultado:

<ns1:root xmlns:MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions" xmlns="uri2" xmlns:ns2="uri2" xmlns:ns1="uri1">
  <ns2:ProductInfo>
    <ns1:ProductModelID>7</ns1:ProductModelID>
    <ns1:Name>HL Touring Frame</ns1:Name>
    <MI:Location xmlns:MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions" LaborHours="2.5" LotSize="100" MachineHours="3" SetupHours="0.5" LocationID="10" xmlns="">
    <MI:step>
      Insert <MI:material>aluminum sheet MS-2341</MI:material> into the <MI:tool>T-85A framing tool</MI:tool>.
    </MI:step>
    ...
    </MI:Location>
    ...
  </ns2:ProductInfo>
</ns1:root>

Gerar uma lista de valores usando o modo PATH

Para cada modelo de produto, esta consulta constrói uma lista de valores de IDs de produto. Para cada ID de produto, a consulta também constrói <ProductName> elementos aninhados, como mostrado neste fragmento XML:

<ProductModelData ProductModelID="7" ProductModelName="..." ProductIDs="product id list in the product model">
  <ProductName>...</ProductName>
  <ProductName>...</ProductName>
  ...
</ProductModelData>

Esta é a consulta que produz o XML que deseja:

USE AdventureWorks2022;
GO
SELECT ProductModelID     AS "@ProductModelID",
       Name               AS "@ProductModelName",
      (SELECT ProductID AS "data()"
       FROM   Production.Product
       WHERE  Production.Product.ProductModelID =
              Production.ProductModel.ProductModelID
       FOR XML PATH ('')) AS "@ProductIDs",
       (SELECT Name AS "ProductName"
       FROM   Production.Product
       WHERE  Production.Product.ProductModelID =
              Production.ProductModel.ProductModelID
        FOR XML PATH ('')) AS "ProductNames"
FROM   Production.ProductModel
WHERE  ProductModelID= 7 or ProductModelID=9
FOR XML PATH('ProductModelData');

Observe o seguinte da consulta anterior:

  • O primeiro aninhado SELECT devolve uma lista de IDs de Produto usando data() como nome da coluna. Como a consulta especifica uma cadeia vazia como nome do elemento linha em FOR XML PATH, nenhum elemento é gerado. Em vez disso, a lista de valores é atribuída ao ProductID atributo.

  • O segundo aninhado SELECT recupera os nomes dos produtos no modelo de produto. Gera elementos <ProductName> que são encapsulados no elemento <ProductNames>, porque a consulta especifica ProductNames como nome da coluna.

Este é o resultado parcial:

<ProductModelData PId="7" ProductModelName="HL Touring Frame" ProductIDs="885 887 ...">
  <ProductNames>
    <ProductName>HL Touring Frame - Yellow, 60</ProductName>
    <ProductName>HL Touring Frame - Yellow, 46</ProductName>
  </ProductNames>
  ...
</ProductModelData>
<ProductModelData PId="9" ProductModelName="LL Road Frame" ProductIDs="722 723 724 ...">
  <ProductNames>
    <ProductName>LL Road Frame - Black, 58</ProductName>
    <ProductName>LL Road Frame - Black, 60</ProductName>
    <ProductName>LL Road Frame - Black, 62</ProductName>
    ...
  </ProductNames>
</ProductModelData>

A subconsulta que constrói os nomes dos produtos devolve o resultado como uma cadeia que é entitizada e depois adicionada ao XML. Se adicionar a diretiva type, FOR XML PATH (''), type, a subquery devolve o resultado como tipo xml e não ocorre qualquer entitização.

USE AdventureWorks2022;
GO
SELECT ProductModelID AS "@ProductModelID",
      Name AS "@ProductModelName",
      (SELECT ProductID AS "data()"
       FROM   Production.Product
       WHERE  Production.Product.ProductModelID =
              Production.ProductModel.ProductModelID
       FOR XML PATH ('')
       ) AS "@ProductIDs",
       (
       SELECT Name AS "ProductName"
       FROM   Production.Product
       WHERE  Production.Product.ProductModelID =
              Production.ProductModel.ProductModelID
       FOR XML PATH (''), type
       ) AS "ProductNames"

FROM Production.ProductModel
WHERE ProductModelID= 7 OR ProductModelID=9
FOR XML PATH('ProductModelData');

Adicionar namespaces no XML resultante

Como descrito em Adicionar Espaços de Nomes Usando WITH XMLNAMESPACES, pode usar WITH XMLNAMESPACES para incluir namespaces nas consultas do modo PATH. Por exemplo, os nomes especificados na cláusula SELECT incluem prefixos de espaço de nomes. A seguinte consulta no modo PATH constrói XML com namespaces.

SELECT 'en'    as "English/@xml:lang",
       'food'  as "English",
       'ger'   as "German/@xml:lang",
       'Essen' as "German"
FOR XML PATH ('Translation')
GO

O @xml:lang atributo adicionado ao <English> elemento está definido no espaço de nomes xml predefinido.

Este é o resultado:

<Translation>
  <English xml:lang="en">food</English>
  <German xml:lang="ger">Essen</German>
</Translation>

A consulta seguinte é semelhante ao exemplo C, exceto que usa WITH XMLNAMESPACES para incluir namespaces no resultado XML. Para mais informações, veja Adicionar Espaços de Nome a Consultas com WITH XMLNAMESPACES.

USE AdventureWorks2022;
GO
WITH XMLNAMESPACES ('uri1' AS ns1,  DEFAULT 'uri2')
SELECT ProductModelID AS "@ns1:ProductModelID",
      Name AS "@ns1:ProductModelName",
      (SELECT ProductID AS "data()"
       FROM   Production.Product
       WHERE  Production.Product.ProductModelID =
              Production.ProductModel.ProductModelID
       FOR XML PATH ('')
       ) AS "@ns1:ProductIDs",
       (
       SELECT ProductID AS "@ns1:ProductID",
              Name AS "@ns1:ProductName"
       FROM   Production.Product
       WHERE  Production.Product.ProductModelID =
              Production.ProductModel.ProductModelID
       FOR XML PATH , type
       ) AS "ns1:ProductNames"
FROM Production.ProductModel
WHERE ProductModelID= 7 OR ProductModelID=9
FOR XML PATH('ProductModelData'), root('root');

Este é o resultado:

<root xmlns="uri2"
  xmlns:ns1="uri1">
  <ProductModelData ns1:ProductModelID="7" ns1:ProductModelName="HL Touring Frame" ns1:ProductIDs="885 887 888 889 890 891 892 893">
    <ns1:ProductNames>
      <row xmlns="uri2" xmlns:ns1="uri1" ns1:ProductID="885" ns1:ProductName="HL Touring Frame - Yellow, 60" />
      <row xmlns="uri2" xmlns:ns1="uri1" ns1:ProductID="887" ns1:ProductName="HL Touring Frame - Yellow, 46" />
      ...
    </ns1:ProductNames>
  </ProductModelData>
  <ProductModelData ns1:ProductModelID="9" ns1:ProductModelName="LL Road Frame" ns1:ProductIDs="722 723 724 725 726 727 728 729 730 736 737 738">
    <ns1:ProductNames>
      <row xmlns="uri2" xmlns:ns1="uri1" ns1:ProductID="722" ns1:ProductName="LL Road Frame - Black, 58" />
      ...
    </ns1:ProductNames>
  </ProductModelData>
</root>

Consulte também