Méthode nodes() (type de données xml)
S’applique à : SQL Server Azure SQL Database Azure SQL Managed Instance
La méthode nodes() s’avère utile pour éclater une instance de type de données xml en données relationnelles. Elle vous permet d'identifier les nœuds à mapper dans une nouvelle ligne.
Chaque instance de type de données xml possède un nœud de contexte fourni implicitement. Pour l’instance XML stockée dans une colonne ou variable, ce nœud est le nœud du document. Le nœud de document est le nœud implicite situé en haut de chaque instance de type de données xml.
Le résultat de la méthode nodes() est un ensemble de lignes qui contient des copies logiques des instances XML d’origine. Dans ces copies logiques, le nœud de contexte de chaque instance de ligne correspond à l’un des nœuds identifiés avec l’expression de requête. Ainsi, les requêtes ultérieures peuvent naviguer par rapport à ces nœuds de contexte.
Vous pouvez extraire plusieurs valeurs de l'ensemble de lignes. Par exemple, vous pouvez appliquer la méthode value() à l’ensemble de lignes renvoyé par nodes() , puis extraire plusieurs valeurs de l’instance XML d’origine. Appliquée à l’instance XML, la méthode value() ne retourne qu’une seule valeur.
Syntaxe
nodes (XQuery) as Table(Column)
Arguments
XQuery
Littéral de chaîne, représentant une expression XQuery. Si l'expression de requête construit des nœuds, ceux-ci sont exposés dans l'ensemble de lignes obtenu. Si l’expression de requête aboutit à une séquence vide, l’ensemble de lignes est également vide. Si l'expression de requête aboutit de façon statique à une séquence qui contient des valeurs atomiques au lieu de nœuds, une erreur statique est déclenchée.
Table(Column)
Nom de table et nom de colonne de l'ensemble de lignes obtenu.
Notes
Prenons par exemple la table suivante :
T (ProductModelID INT, Instructions XML)
Le document des instructions de fabrication suivant est stocké dans la table. Seule une partie de celui-ci est montrée. Le document mentionne trois sites de fabrication.
<root>
<Location LocationID="10"...>
<step>...</step>
<step>...</step>
...
</Location>
<Location LocationID="20" ...>
...
</Location>
<Location LocationID="30" ...>
...
</Location>
</root>
Un appel de la méthode nodes()
avec l'expression de requête /root/Location
renverrait un ensemble de lignes composé de trois lignes, contenant chacune une copie logique du document XML d'origine et associant l'élément de contexte à l'un des nœuds <Location>
:
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>
Vous pouvez alors interroger cet ensemble de lignes à l’aide de méthodes de type de données xml. La requête suivante extrait la sous-arborescence de l'élément de contexte pour chaque ligne générée :
SELECT T2.Loc.query('.')
FROM T
CROSS APPLY Instructions.nodes('/root/Location') AS T2(Loc)
Voici le résultat :
ProductModelID Instructions
----------------------------------
1 <Location LocationID="10" ... />
1 <Location LocationID="20" ... />
1 <Location LocationID="30" .../>
L’ensemble de lignes retourné a conservé les informations de type. Vous pouvez appliquer des méthodes de type de données xml, comme query() , value() , exist() et nodes() , au résultat d’une méthode nodes() . Toutefois, vous ne pouvez pas appliquer la méthode modify() pour modifier l’instance XML.
En outre, le nœud de contexte figurant dans l’ensemble de lignes ne peut pas être matérialisé. Vous ne pouvez donc pas l’utiliser dans une instruction SELECT. Toutefois, vous pouvez l'utiliser dans IS NULL et COUNT(*).
Les scénarios d’utilisation de la méthode nodes() sont les mêmes que ceux de la méthode OPENXML (Transact-SQL) qui affiche un ensemble de lignes de XML. Toutefois, vous n’avez pas besoin de recourir à des curseurs lorsque vous utilisez la méthode nodes() sur une table qui contient plusieurs lignes de documents XML.
L’ensemble de lignes retourné par la méthode nodes() est un ensemble de lignes sans nom. Il doit donc être nommé explicitement à l’aide d’un alias.
La fonction nodes() ne peut pas s’appliquer directement aux résultats d’une fonction définie par l’utilisateur. Pour utiliser la fonction nodes() avec le résultat d’une fonction scalaire définie par l’utilisateur, vous pouvez :
- Affecter le résultat de la fonction définie par l’utilisateur à une variable
- Utiliser une table dérivée pour affecter un alias de colonne à la valeur de retour d’une fonction définie par l’utilisateur, puis utiliser
CROSS APPLY
pour effectuer une sélection à partir de l’alias.
L'exemple suivant illustre une utilisation de CROSS APPLY
permettant d'opérer une sélection à partir du résultat d'une fonction définie par l'utilisateur.
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
Exemples
Utilisation de la méthode nodes() par rapport à une variable de type xml
L’exemple suivant montre un document XML qui possède un élément de niveau supérieur <Root
> et trois éléments enfants <row
> éléments enfants. La requête utilise la méthode nodes()
pour définir un nœud de contexte distinct par élément <row
>. La méthode nodes()
renvoie un ensemble de lignes composé de trois lignes. Chaque ligne possède une copie logique du document XML d’origine et chaque nœud de contexte identifie un élément <row
> distinct de ce document.
La requête renvoie ensuite le nœud de contexte depuis chaque ligne :
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
Dans l’exemple suivant, la méthode de requête retourne l’élément de contexte et son contenu :
<row id="1"><name>Larry</name><oflw>some text</oflw></row>
<row id="2"><name>moe</name></row>
<row id="3"/>
L’application de l’accesseur parent aux nœuds de contexte renvoie l’élément <Root
> pour les trois lignes :
SELECT T.c.query('..') AS result
FROM @x.nodes('/Root/row') T(c)
GO
Voici le résultat :
<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>
Spécification de la méthode nodes() par rapport à une colonne de type xml
Cet exemple utilise les instructions de fabrication de vélo, stockées dans la colonne Instructions de type xml de la table ProductModel.
Dans l’exemple suivant, la méthode nodes()
est spécifiée par rapport à la colonne Instructions
de type xml de la table ProductModel
.
La méthode nodes()
définit les éléments <Location
> en tant que nœuds de contexte en spécifiant le chemin d’accès /MI:root/MI:Location
. L’ensemble de lignes obtenu comprend une copie logique du document d’origine par nœud <Location
> du document et le nœud de contexte a pour valeur l’élément <Location
>. Par conséquent, la fonction nodes()
fournit un ensemble de nœuds de contexte <Location
>.
La méthode query()
appliquée à cet ensemble de lignes demande self::node
et renvoie l’élément <Location>
de chaque ligne.
Dans cet exemple, la requête définit chaque élément <Location
> en tant que nœud de contexte du document d’instructions de fabrication d’un modèle de produit spécifique. Ces nœuds de contexte vous permettent d’effectuer les opérations d’extraction suivantes :
Rechercher les ID d’emplacement dans chaque élément <
Location
>Récupérer les étapes de fabrication (éléments enfants <
step
>) dans chaque <Location
>
Cette requête renvoie l'élément de contexte, dans lequel est spécifiée la syntaxe abrégée '.'
de self::node()
, dans la méthode query()
.
Notez les points suivants :
La méthode
nodes()
est appliquée à la colonne Instructions et renvoie l'ensemble de lignesT (C)
. Cet ensemble de lignes contient des copies logiques du document d'origine des instructions de fabrication et indique/root/Location
en guise d'élément de contexte.CROSS APPLY applique
nodes()
à chaque ligne de la tableProductModel
et renvoie uniquement les lignes qui génèrent un ensemble de résultats.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
Voici le résultat partiel :
<MI:Location LocationID="10" ...> <MI:step ... /> ... </MI:Location> <MI:Location LocationID="20" ... > <MI:step ... /> ... </MI:Location> ...
Application de la méthode nodes() à l'ensemble de lignes renvoyé par une autre méthode nodes()
Le code suivant interroge les documents XML des instructions de fabrication stockés dans la colonne Instructions
de la table ProductModel
. La requête renvoie un ensemble de lignes qui contient l'ID du modèle de produit, ainsi que les sites et les étapes de fabrication.
Notez les points suivants :
La méthode
nodes()
est appliquée à la colonneInstructions
et renvoie l'ensemble de lignesT1 (Locations)
. Cet ensemble de lignes contient des copies logiques du document d'origine des instructions de fabrication et indique/root/Location
en guise de contexte d'élément.nodes()
est appliqué à l'ensemble de lignesT1 (Locations)
et renvoie l'ensemble de lignesT2 (steps)
. Cet ensemble de lignes contient des copies logiques du document d'origine des instructions de fabrication et indique/root/Location/step
en guise de contexte d'élément.
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
Voici le résultat :
ProductModelID LocID Step
----------------------------
7 10 <step ... />
7 10 <step ... />
...
7 20 <step ... />
7 20 <step ... />
7 20 <step ... />
...
La requête déclare le préfixe MI
deux fois. À la place, vous pouvez recourir à WITH XMLNAMESPACES
pour déclarer le préfixe une fois et l'utiliser dans la requête :
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
Voir aussi
Ajouter des espaces de noms aux requêtes avec WITH XMLNAMESPACES
Créer des instances de données XML
Méthodes de type de données xml