Metoda nodes() (xml datový typ)

platí pro:SQL ServerAzure SQL DatabaseAzure SQL Managed InstanceSQL databáze v Microsoft Fabric

Metoda nodes() je užitečná, když chcete roztrhat instanci XML datového typu do relačních dat. Umožňuje identifikovat uzly, které budou namapovány do nového řádku.

Každá instance XML datového typu má implicitně poskytnutý kontextový uzel. Pro XML instanci uloženou ve sloupci nebo proměnné je tento uzel dokumentačním uzlem. Uzel dokumentu je implicitní uzel nahoře v každé instanci XML datového typu.

Výsledkem metody nodes() je řádková sada obsahující logické kopie původních XML instancí. V těchto logických kopiích je kontextový uzel každé instance řádku nastaven na jeden z uzlů, který je identifikován s dotazovacím výrazem. Tímto způsobem mohou pozdější dotazy navigovat podle těchto kontextových uzlů.

Z řádků můžete získat více hodnot. Například můžete použít metodu value() na řádkovou sadu vrácenou nodes() a získat více hodnot z původní XML instance. Metoda value() při aplikaci na XML instanci vrací pouze jednu hodnotu.

Syntaxe

nodes (XQuery) as Table(Column)  

Arguments

XQuery
Je literál řetězce, výraz XQuery. Pokud dotazovací výraz konstruuje uzly, tyto konstruované uzly jsou vystaveny ve výsledné sadě řádků. Pokud dotazovací výraz vede k prázdné sekvenci, je řádková sada také prázdná. Pokud dotazovací výraz staticky vede k sekvenci obsahující atomární hodnoty místo uzlů, vznikne statická chyba.

Tabulka (sloupec)
Je název tabulky a název sloupce pro výslednou sadu řádků.

Poznámky

Jako příklad předpokládejme, že máte následující tabulku:

T (ProductModelID INT, Instructions XML)  

Následující dokument s výrobními instrukcemi je uložen v tabulce. Je zde pouze fragment. Všimněte si, že v dokumentu jsou tři výrobní místa.

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

Volání nodes() metody s dotazovacím výrazem /root/Location by vrátilo sadu řádků se třemi řádky, z nichž každý obsahoval logickou kopii původního XML dokumentu a kontextový prvek byl nastaven na jeden z <Location> uzlů:

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>  

Poté můžete tuto sadu řádků dotazovat pomocí metod xml datových typů. Následující dotaz extrahuje podstrom kontextové položky pro každý generovaný řádek:

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

Zde je výsledek:

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

Vrácená sada řádků si zachovala informace o typu. Metody typu xml, jako jsou query(), value(), exist() a nodes(), můžete použít na výsledek metody nodes(). Nicméně nelze použít metodu modify() k úpravě XML instance.

Také kontextový uzel v sadě řádků nelze materializovat. To znamená, že ho nelze použít v příkazu SELECT. Můžete ji však použít v IS NULL a COUNT(*).

Scénáře pro použití metody nodes() jsou stejné jako pro použití OPENXML (Transact-SQL), který poskytuje pohled na XML jako řádky. Nicméně nemusíte používat kurzory, když používáte metodu nodes() na tabulce obsahující několik řádků XML dokumentů.

Řádková sada vrácená metodou nodes() je bezejmenná řádková sada. Proto musí být explicitně pojmenován pomocí aliasingu.

Funkce nodes() nelze aplikovat přímo na výsledky uživatelsky definované funkce. Pro použití funkce nodes() s výsledkem skalární uživatelsky definované funkce můžete buď:

  • Přiřaďte výsledek uživatelem definované funkce proměnné
  • Použijte odvozenou tabulku k přiřazení sloupcového aliasu uživatelsky definované funkce return a poté použijte CROSS APPLY k výběru z aliasu.

Následující příklad ukazuje jeden způsob, jak vybrat CROSS APPLY z výsledku uživatelem definované funkce.

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

Použití metody nodes() proti proměnné typu xml

V následujícím příkladu je XML dokument, který má nejvyšší <Root> úroveň a tři <row> podelementy. Dotaz používá metodu nodes() k nastavení samostatných kontextových uzlů, jeden pro každý <row> prvek. Metoda nodes() vrací sadu řádků se třemi řádky. Každý řádek obsahuje logickou kopii původního XML, přičemž každý kontextový uzel identifikuje jiný <row> prvek v původním dokumentu.

Dotaz pak vrací kontextový uzel z každého řádku:

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  

V následujícím příkladu odpovídá metoda dotazu kontextovou položku a její obsah:

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

Aplikace rodičovského accessoru na kontextové uzly vrací prvek <Root> pro všechny tři:

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

Zde je výsledek:

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

Specifikace metody nodes() vůči sloupci typu xml

V tomto příkladu jsou použity instrukce výroby kol a jsou uloženy ve sloupci xml typu Instructions v tabulce ProductModel .

V následujícím příkladu nodes() je metoda specifikována vůči sloupci Instructionsxml typu v tabulce ProductModel .

Metoda nastavujenodes()<Locationprvky jako kontextové uzly tím, že určí > cestu./MI:root/MI:Location Výsledná sada řádků obsahuje logické kopie původního dokumentu, jednu pro každý <Location> uzel v dokumentu, s kontextovým uzlem nastaveným na daný <Location> prvek. Výsledkem je, že nodes() funkce poskytuje množinu kontextových <Location> uzlů.

Metoda query() proti této sadě řádků požaduje self::node a vrací prvek <Location> v každém řádku.

V tomto příkladu dotaz nastaví každý <Location> prvek jako kontextový uzel v dokumentu výrobních instrukcí konkrétního modelu produktu. Tyto kontextové uzly můžete použít k získání hodnot, jako jsou tyto:

  • Najděte identifikátory polohy v každé z nich <Location>

  • Získejte výrobní kroky (<step> podelementy) v každém z nich <Location>

Tento dotaz vrací kontextovou položku, ve které je v metodě '.' specifikována zkrácená syntaxe self::node() pro query() .

Všimněte si následujících věcí:

  • Metoda nodes() se aplikuje na sloupec Instrukce a vrací sadu řádků, T (C). Tato sada řádků obsahuje logické kopie původního dokumentu výrobních instrukcí s /root/Location kontextovou položkou.

  • CROSS APPLY se vztahuje nodes() na každý řádek v tabulce ProductModel a vrací pouze řádky, které vytvářejí výslednou množinu.

    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  
    

    Zde je částečný výsledek:

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

Aplikace nodes() na sadu řádků vrácenou jinou metodou nodes()

Následující kód dotazuje XML dokumenty na výrobní instrukce ve sloupci Instructions tabulky ProductModel . Dotaz vrací řádkovou sadu, která obsahuje ID produktového modelu, výrobní místa a výrobní kroky.

Všimněte si následujících věcí:

  • Metoda nodes() se aplikuje na sloupec Instructions a vrací řádkovou sadu T1 (Locations) . Tato sada řádků obsahuje logické kopie původního dokumentu výrobních instrukcí, přičemž /root/Location prvek slouží jako kontext položky.

  • nodes() se aplikuje na T1 (Locations) řádkovou sadu a vrací ji T2 (steps) zpět. Tato sada řádků obsahuje logické kopie původního dokumentu výrobních instrukcí, přičemž /root/Location/step prvek slouží jako kontext položky.

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         

Zde je výsledek:

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

Dotaz oznamuje MI prefix dvakrát. Místo toho můžete WITH XMLNAMESPACES použít k jednorázovému prohlášení prefixu a použít ho v dotazu:

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